blob: 1c998817edbc9d3ad50646a04d59d7a1821a8b96 [file] [log] [blame]
import 'dart:typed_data';
import '../../image_exception.dart';
import '../../util/input_buffer.dart';
class PsdChannel {
static const int RED = 0;
static const int GREEN = 1;
static const int BLUE = 2;
static const int BLACK = 3;
static const int ALPHA = -1;
static const int MASK = -2;
static const int REAL_MASK = -3;
static const int COMPRESS_NONE = 0;
static const int COMPRESS_RLE = 1;
static const int COMPRESS_ZIP = 2;
static const int COMPRESS_ZIP_PREDICTOR = 3;
int id;
int dataLength;
Uint8List data;
PsdChannel(this.id, this.dataLength);
PsdChannel.read(InputBuffer input, this.id, int width, int height,
int bitDepth, int compression, Uint16List lineLengths, int planeNumber) {
readPlane(
input, width, height, bitDepth, compression, lineLengths, planeNumber);
}
void readPlane(InputBuffer input, int width, int height, int bitDepth,
[int compression, Uint16List lineLengths, int planeNum = 0]) {
if (compression == null) {
compression = input.readUint16();
}
switch (compression) {
case COMPRESS_NONE:
_readPlaneUncompressed(input, width, height, bitDepth);
break;
case COMPRESS_RLE:
if (lineLengths == null) {
lineLengths = _readLineLengths(input, height);
}
_readPlaneRleCompressed(
input, width, height, bitDepth, lineLengths, planeNum);
break;
default:
throw new ImageException('Unsupported compression: $compression');
}
}
Uint16List _readLineLengths(InputBuffer input, int height) {
Uint16List lineLengths = Uint16List(height);
for (int i = 0; i < height; ++i) {
lineLengths[i] = input.readUint16();
}
return lineLengths;
}
void _readPlaneUncompressed(
InputBuffer input, int width, int height, int bitDepth) {
int len = width * height;
if (bitDepth == 16) {
len *= 2;
}
if (len > input.length) {
data = Uint8List(len);
data.fillRange(0, len, 255);
return;
}
InputBuffer imgData = input.readBytes(len);
data = imgData.toUint8List();
}
void _readPlaneRleCompressed(InputBuffer input, int width, int height,
int bitDepth, Uint16List lineLengths, int planeNum) {
int len = width * height;
if (bitDepth == 16) {
len *= 2;
}
data = Uint8List(len);
int pos = 0;
int lineIndex = planeNum * height;
if (lineIndex >= lineLengths.length) {
data.fillRange(0, data.length, 255);
return;
}
for (int i = 0; i < height; ++i) {
int len = lineLengths[lineIndex++];
InputBuffer s = input.readBytes(len);
_decodeRLE(s, data, pos);
pos += width;
}
}
void _decodeRLE(InputBuffer src, Uint8List dst, int dstIndex) {
while (!src.isEOS) {
int n = src.readInt8();
if (n < 0) {
n = 1 - n;
int b = src.readByte();
for (int i = 0; i < n; ++i) {
dst[dstIndex++] = b;
}
} else {
n++;
for (int i = 0; i < n; ++i) {
dst[dstIndex++] = src.readByte();
}
}
}
}
}