blob: b4e7d994a771928581550b2c130411e613e1eab5 [file] [log] [blame]
import 'dart:typed_data';
import 'package:archive/archive.dart';
import '../../image_exception.dart';
import '../../util/input_buffer.dart';
import '../../util/output_buffer.dart';
import 'exr_channel.dart';
import 'exr_compressor.dart';
import 'exr_part.dart';
abstract class ExrPxr24Compressor extends ExrCompressor {
factory ExrPxr24Compressor(
ExrPart header, int maxScanLineSize, int numScanLines) =
InternalExrPxr24Compressor;
}
class InternalExrPxr24Compressor extends InternalExrCompressor
implements ExrPxr24Compressor {
InternalExrPxr24Compressor(
ExrPart header, this._maxScanLineSize, this._numScanLines)
: super(header as InternalExrPart);
int numScanLines() => _numScanLines;
Uint8List compress(InputBuffer inPtr, int x, int y, [int width, int height]) {
throw new ImageException('Pxr24 compression not yet supported.');
}
Uint8List uncompress(InputBuffer inPtr, int x, int y,
[int width, int height]) {
List<int> data = _zlib.decodeBytes(inPtr.toUint8List());
if (data == null) {
throw new ImageException('Error decoding pxr24 compressed data');
}
if (_output == null) {
_output = OutputBuffer(size: _numScanLines * _maxScanLineSize);
}
_output.rewind();
int tmpEnd = 0;
List<int> ptr = [0, 0, 0, 0];
Uint32List pixel = Uint32List(1);
Uint8List pixelBytes = Uint8List.view(pixel.buffer);
if (width == null) {
width = header.width;
}
if (height == null) {
height = header.linesInBuffer;
}
int minX = x;
int maxX = x + width - 1;
int minY = y;
int maxY = y + height - 1;
if (maxX > header.width) {
maxX = header.width - 1;
}
if (maxY > header.height) {
maxY = header.height - 1;
}
decodedWidth = (maxX - minX) + 1;
decodedHeight = (maxY - minY) + 1;
int numChannels = header.channels.length;
for (int yi = minY; yi <= maxY; ++yi) {
for (int ci = 0; ci < numChannels; ++ci) {
ExrChannel ch = header.channels[ci];
if ((y % ch.ySampling) != 0) {
continue;
}
int n = numSamples(ch.xSampling, minX, maxX);
pixel[0] = 0;
switch (ch.type) {
case ExrChannel.TYPE_UINT:
ptr[0] = tmpEnd;
ptr[1] = ptr[0] + n;
ptr[2] = ptr[1] + n;
tmpEnd = ptr[2] + n;
for (int j = 0; j < n; ++j) {
int diff = (data[ptr[0]++] << 24) |
(data[ptr[1]++] << 16) |
(data[ptr[2]++] << 8);
pixel[0] += diff;
for (int k = 0; k < 4; ++k) {
_output.writeByte(pixelBytes[k]);
}
}
break;
case ExrChannel.TYPE_HALF:
ptr[0] = tmpEnd;
ptr[1] = ptr[0] + n;
tmpEnd = ptr[1] + n;
for (int j = 0; j < n; ++j) {
int diff = (data[ptr[0]++] << 8) | data[ptr[1]++];
pixel[0] += diff;
for (int k = 0; k < 2; ++k) {
_output.writeByte(pixelBytes[k]);
}
}
break;
case ExrChannel.TYPE_FLOAT:
ptr[0] = tmpEnd;
ptr[1] = ptr[0] + n;
ptr[2] = ptr[1] + n;
tmpEnd = ptr[2] + n;
for (int j = 0; j < n; ++j) {
int diff = (data[ptr[0]++] << 24) |
(data[ptr[1]++] << 16) |
(data[ptr[2]++] << 8);
pixel[0] += diff;
for (int k = 0; k < 4; ++k) {
_output.writeByte(pixelBytes[k]);
}
}
break;
}
}
}
return _output.getBytes() as Uint8List;
}
ZLibDecoder _zlib = ZLibDecoder();
int _maxScanLineSize;
int _numScanLines;
OutputBuffer _output;
}