TMI-134: Cannot read PSD images with PSD Layer Mask data size 28

This commit is contained in:
Harald Kuhr 2015-05-05 11:40:54 +02:00
parent 1a8948ece9
commit 9b71a0cba7
2 changed files with 93 additions and 31 deletions

View File

@ -74,7 +74,7 @@ final class PSDLayerInfo {
long extraDataSize = pInput.readUnsignedInt(); long extraDataSize = pInput.readUnsignedInt();
// Layer mask/adjustment layer data // Layer mask/adjustment layer data
int layerMaskDataSize = pInput.readInt(); // May be 0, 20 or 36 bytes... int layerMaskDataSize = pInput.readInt(); // May be 0, 20 or variable (up to 55) bytes...
if (layerMaskDataSize != 0) { if (layerMaskDataSize != 0) {
layerMaskData = new PSDLayerMaskData(pInput, layerMaskDataSize); layerMaskData = new PSDLayerMaskData(pInput, layerMaskDataSize);
} }

View File

@ -47,42 +47,90 @@ final class PSDLayerMaskData {
private int defaultColor; private int defaultColor;
private int flags; private int flags;
private boolean large; private int maskParams;
private int realFlags; private int userMaskDensity;
private int realUserBackground; private double userMaskFeather;
private int realTop; private int vectorMaskDensity;
private int realLeft; private double vectorMaskFeather;
private int realBottom;
private int realRight;
PSDLayerMaskData(final ImageInputStream pInput, final int pSize) throws IOException { PSDLayerMaskData(final ImageInputStream pInput, final int pSize) throws IOException {
if (pSize != 20 && pSize != 36) { if (pSize < 20 || pSize > 55) {
throw new IIOException("Illegal PSD Layer Mask data size: " + pSize + " (expected 20 or 36)"); throw new IIOException("Illegal PSD Layer Mask data size: " + pSize + " (expected between 20 and 55)");
} }
// Rectangle enclosing layer mask: Top, left, bottom, right.
top = pInput.readInt(); top = pInput.readInt();
left = pInput.readInt(); left = pInput.readInt();
bottom = pInput.readInt(); bottom = pInput.readInt();
right = pInput.readInt(); right = pInput.readInt();
// Default color. 0 or 255
defaultColor = pInput.readUnsignedByte(); defaultColor = pInput.readUnsignedByte();
// Flags.
// bit 0 = position relative to layer
// bit 1 = layer mask disabled
// bit 2 = invert layer mask when blending (Obsolete)
// bit 3 = indicates that the user mask actually came from rendering other data
// bit 4 = indicates that the user and/or vector masks have parameters applied to them
flags = pInput.readUnsignedByte(); flags = pInput.readUnsignedByte();
if (pSize == 20) { int dataLeft = pSize - 18;
if ((flags & 0x10) != 0) {
// Mask Parameters. Only present if bit 4 of Flags set above.
maskParams = pInput.readUnsignedByte();
dataLeft--;
// Mask Parameters bit flags present as follows:
// bit 0 = user mask density, 1 byte
// bit 1 = user mask feather, 8 byte, double
// bit 2 = vector mask density, 1 byte
// bit 3 = vector mask feather, 8 bytes, double
if ((maskParams & 0x01) != 0) {
userMaskDensity = pInput.readByte();
dataLeft--;
}
if ((maskParams & 0x02) != 0) {
userMaskFeather = pInput.readDouble();
dataLeft -= 8;
}
if ((maskParams & 0x04) != 0) {
vectorMaskDensity = pInput.readByte();
dataLeft--;
}
if ((maskParams & 0x08) != 0) {
vectorMaskFeather = pInput.readDouble();
dataLeft -= 8;
}
}
// Padding. Only present if size = 20. Otherwise the following is present
if (pSize == 20 && dataLeft == 2) {
pInput.readShort(); // Pad pInput.readShort(); // Pad
dataLeft -= 2;
} }
else { else {
// TODO: What to make out of this? if (dataLeft >= 2) {
large = true; // Real Flags. Same as Flags information above.
flags = pInput.readUnsignedByte();
dataLeft--;
// Real user mask background. 0 or 255.
defaultColor = pInput.readUnsignedByte();
dataLeft--;
}
if (dataLeft >= 16) {
// Rectangle enclosing layer mask: Top, left, bottom, right.
top = pInput.readInt();
left = pInput.readInt();
bottom = pInput.readInt();
right = pInput.readInt();
dataLeft -= 16;
}
}
realFlags = pInput.readUnsignedByte(); if (dataLeft > 0) {
realUserBackground = pInput.readUnsignedByte(); pInput.skipBytes(dataLeft);
realTop = pInput.readInt();
realLeft = pInput.readInt();
realBottom = pInput.readInt();
realRight = pInput.readInt();
} }
} }
@ -97,40 +145,54 @@ final class PSDLayerMaskData {
builder.append(", default color: ").append(defaultColor); builder.append(", default color: ").append(defaultColor);
builder.append(", flags: ").append(Integer.toBinaryString(flags)); builder.append(", flags: ").append(Integer.toBinaryString(flags));
// TODO: Maybe the flag bits have oposite order?
builder.append(" ("); builder.append(" (");
if ((flags & 0x01) != 0) { if ((flags & 0x01) != 0) {
builder.append("Pos. rel. to layer"); builder.append("relative");
} }
else { else {
builder.append("Pos. abs."); builder.append("absolute");
} }
if ((flags & 0x02) != 0) { if ((flags & 0x02) != 0) {
builder.append(", Mask disabled"); builder.append(", disabled");
} }
else { else {
builder.append(", Mask enabled"); builder.append(", enabled");
} }
if ((flags & 0x04) != 0) { if ((flags & 0x04) != 0) {
builder.append(", Invert mask"); builder.append(", inverted");
} }
if ((flags & 0x08) != 0) { if ((flags & 0x08) != 0) {
builder.append(", Unknown bit 3"); builder.append(", from rendered data");
} }
if ((flags & 0x10) != 0) { if ((flags & 0x10) != 0) {
builder.append(", Unknown bit 4"); builder.append(", has parameters");
} }
if ((flags & 0x20) != 0) { if ((flags & 0x20) != 0) {
builder.append(", Unknown bit 5"); builder.append(", unknown flag (bit 5)");
} }
if ((flags & 0x40) != 0) { if ((flags & 0x40) != 0) {
builder.append(", Unknown bit 6"); builder.append(", unknown flag (bit 6)");
} }
if ((flags & 0x80) != 0) { if ((flags & 0x80) != 0) {
builder.append(", Unknown bit 7"); builder.append(", unknown flag (bit 7)");
} }
builder.append(")"); builder.append(")");
if ((flags & 0x10) != 0) {
if ((maskParams & 0x01) != 0) {
builder.append(", userMaskDensity: ").append(userMaskDensity);
}
if ((maskParams & 0x02) != 0) {
builder.append(", userMaskFeather: ").append(userMaskFeather);
}
if ((maskParams & 0x04) != 0) {
builder.append(", vectorMaskDensity: ").append(vectorMaskDensity);
}
if ((maskParams & 0x08) != 0) {
builder.append(", vectorMaskFeather: ").append(vectorMaskFeather);
}
}
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }