#648: Simplified logic, code style fixes and clean up.

This commit is contained in:
Harald Kuhr 2021-12-28 16:49:41 +01:00
parent dc0bdcbd5b
commit b30fb4f8c3
4 changed files with 85 additions and 104 deletions

View File

@ -946,48 +946,8 @@ public final class PSDImageReader extends ImageReaderBase {
metadata.layerCount = layerCount; metadata.layerCount = layerCount;
if (pParseData && metadata.layerInfo == null) { if (pParseData && metadata.layerInfo == null) {
PSDLayerInfo[] layerInfos = new PSDLayerInfo[Math.abs(layerCount)]; metadata.layerInfo = readLayerInfo(Math.abs(layerCount));
Stack<List<PSDLayerInfo>> groupStack = new Stack<>();
List<PSDLayerInfo> groupedLayerInfo = null;
for (int i = 0; i < layerInfos.length; i++) {
PSDLayerInfo layerInfo = new PSDLayerInfo(header.largeFormat, imageInput);
layerInfos[i] = layerInfo;
if (layerInfo.sectionDividerSettingType == PSDLayerInfo.SectionDividerSetting.BOUNDING_SECTION_DIVIDER) {
if (groupedLayerInfo == null) {
groupedLayerInfo = new LinkedList<>();
groupStack.add(groupedLayerInfo);
} else {
groupStack.add(groupedLayerInfo);
groupedLayerInfo = new LinkedList<>();
}
layerInfo.sectionDivider = true;
}
else if (layerInfo.sectionDividerSettingType == PSDLayerInfo.SectionDividerSetting.OPEN_FOLDER ||
layerInfo.sectionDividerSettingType == PSDLayerInfo.SectionDividerSetting.CLOSED_FOLDER) {
// can't happen but for defense logic
if (groupedLayerInfo == null) {
continue;
}
for (PSDLayerInfo info : groupedLayerInfo) {
info.groupLayerId = layerInfo.getLayerId();
}
groupedLayerInfo = groupStack.pop();
groupedLayerInfo.add(layerInfo);
layerInfo.group = true;
}
else {
if (groupedLayerInfo != null) {
groupedLayerInfo.add(layerInfo);
}
}
}
metadata.layerInfo = Arrays.asList(layerInfos);
metadata.layersStart = imageInput.getStreamPosition(); metadata.layersStart = imageInput.getStreamPosition();
} }
long read = imageInput.getStreamPosition() - pos; long read = imageInput.getStreamPosition() - pos;
@ -999,7 +959,6 @@ public final class PSDImageReader extends ImageReaderBase {
metadata.layerInfo = Collections.emptyList(); metadata.layerInfo = Collections.emptyList();
} }
// Global LayerMaskInfo (18 bytes or more..?) // Global LayerMaskInfo (18 bytes or more..?)
// 4 (length), 2 (colorSpace), 8 (4 * 2 byte color components), 2 (opacity %), 1 (kind), variable (pad) // 4 (length), 2 (colorSpace), 8 (4 * 2 byte color components), 2 (opacity %), 1 (kind), variable (pad)
long globalLayerMaskInfoLength = imageInput.readUnsignedInt(); // NOTE: Not long for PSB! long globalLayerMaskInfoLength = imageInput.readUnsignedInt(); // NOTE: Not long for PSB!
@ -1030,6 +989,33 @@ public final class PSDImageReader extends ImageReaderBase {
} }
} }
private List<PSDLayerInfo> readLayerInfo(int layerCount) throws IOException {
PSDLayerInfo[] layerInfos = new PSDLayerInfo[layerCount];
List<PSDLayerInfo> groupedLayerInfo = Collections.emptyList();
for (int i = 0; i < layerInfos.length; i++) {
PSDLayerInfo layerInfo = new PSDLayerInfo(header.largeFormat, imageInput);
layerInfos[i] = layerInfo;
if (layerInfo.isDivider) {
groupedLayerInfo = new LinkedList<>();
}
else if (layerInfo.isGroup) {
for (PSDLayerInfo info : groupedLayerInfo) {
info.groupId = layerInfo.getLayerId();
}
groupedLayerInfo = Collections.emptyList();
}
else if (groupedLayerInfo != Collections.EMPTY_LIST) {
groupedLayerInfo.add(layerInfo);
}
}
return Arrays.asList(layerInfos);
}
private BufferedImage readLayerData(final int layerIndex, final ImageReadParam param) throws IOException { private BufferedImage readLayerData(final int layerIndex, final ImageReadParam param) throws IOException {
final int width = getLayerWidth(layerIndex); final int width = getLayerWidth(layerIndex);
final int height = getLayerHeight(layerIndex); final int height = getLayerHeight(layerIndex);
@ -1044,7 +1030,7 @@ public final class PSDImageReader extends ImageReaderBase {
// Even if raw/imageType has no alpha, the layers may still have alpha... // Even if raw/imageType has no alpha, the layers may still have alpha...
ImageTypeSpecifier imageType = getRawImageTypeForLayer(layerIndex); ImageTypeSpecifier imageType = getRawImageTypeForLayer(layerIndex);
BufferedImage layer = getDestination(param, getImageTypes(layerIndex + 1), Math.max(1, width), Math.max(1, height)); BufferedImage layer = getDestination(param, getImageTypes(layerIndex + 1), width, height);
imageInput.seek(findLayerStartPos(layerIndex)); imageInput.seek(findLayerStartPos(layerIndex));

View File

@ -52,16 +52,15 @@ final class PSDLayerInfo {
final PSDLayerBlendMode blendMode; final PSDLayerBlendMode blendMode;
final PSDLayerMaskData layerMaskData; final PSDLayerMaskData layerMaskData;
final PSDChannelSourceDestinationRange[] ranges; final PSDChannelSourceDestinationRange[] ranges;
private final String layerName; private final String layerName;
private final String unicodeLayerName;
private String unicodeLayerName; private final int layerId;
private int layerId;
Integer groupLayerId; int groupId = -1;
Boolean group = false; final boolean isGroup;
Boolean sectionDivider = false; final boolean isDivider;
SectionDividerSetting sectionDividerSettingType;
PSDLayerInfo(final boolean largeFormat, final ImageInputStream pInput) throws IOException { PSDLayerInfo(final boolean largeFormat, final ImageInputStream pInput) throws IOException {
top = pInput.readInt(); top = pInput.readInt();
@ -114,6 +113,10 @@ final class PSDLayerInfo {
layerNameSize += skip; layerNameSize += skip;
} }
int layerId = -1;
String unicodeLayerName = null;
int sectionDividerSettingType = 0;
// Parse "Additional layer data" // Parse "Additional layer data"
long additionalLayerInfoStart = pInput.getStreamPosition(); long additionalLayerInfoStart = pInput.getStreamPosition();
long expectedEnd = additionalLayerInfoStart + extraDataSize - layerMaskDataSize - 4 - layerBlendingDataSize - 4 - layerNameSize; long expectedEnd = additionalLayerInfoStart + extraDataSize - layerMaskDataSize - 4 - layerBlendingDataSize - 4 - layerNameSize;
@ -138,7 +141,6 @@ final class PSDLayerInfo {
// System.out.println("key: " + PSDUtil.intToStr(resourceKey)); // System.out.println("key: " + PSDUtil.intToStr(resourceKey));
// System.out.println("length: " + resourceLength); // System.out.println("length: " + resourceLength);
switch (resourceKey) { switch (resourceKey) {
case PSD.luni: case PSD.luni:
unicodeLayerName = PSDUtil.readUnicodeString(pInput); unicodeLayerName = PSDUtil.readUnicodeString(pInput);
@ -149,24 +151,37 @@ final class PSDLayerInfo {
if (resourceLength != 4) { if (resourceLength != 4) {
throw new IIOException(String.format("Expected layerId length == 4: %d", resourceLength)); throw new IIOException(String.format("Expected layerId length == 4: %d", resourceLength));
} }
layerId = pInput.readInt(); layerId = pInput.readInt();
break; break;
case PSD.lsct: case PSD.lsct:
sectionDividerSettingType = SectionDividerSetting.valueOf(pInput.readInt()); if (resourceLength < 4) {
throw new IIOException(String.format("Expected sectionDividerSetting length >= 4: %d", resourceLength));
}
sectionDividerSettingType = pInput.readInt();
// length >= 12: '8BIM' + 4byte blend mode, length >= 16, 4byte sub type
pInput.skipBytes(resourceLength - 4); pInput.skipBytes(resourceLength - 4);
break; break;
default: default:
// TODO: Parse more data... // TODO: Parse more data...
pInput.skipBytes(resourceLength); pInput.skipBytes(resourceLength);
break; break;
} }
// Re-align in case we got the length incorrect // Re-align in case we got the resource length incorrect
if (pInput.getStreamPosition() != resourceStart + resourceLength) { if (pInput.getStreamPosition() != resourceStart + resourceLength) {
pInput.seek(resourceStart + resourceLength); pInput.seek(resourceStart + resourceLength);
} }
} }
this.layerId = layerId;
this.unicodeLayerName = unicodeLayerName;
isGroup = sectionDividerSettingType == 1 || sectionDividerSettingType == 2;
isDivider = sectionDividerSettingType == 3;
// Re-align in case we got the length incorrect // Re-align in case we got the length incorrect
if (pInput.getStreamPosition() != expectedEnd) { if (pInput.getStreamPosition() != expectedEnd) {
pInput.seek(expectedEnd); pInput.seek(expectedEnd);
@ -197,26 +212,19 @@ final class PSDLayerInfo {
} }
builder.append(", ranges: ").append(Arrays.toString(ranges)); builder.append(", ranges: ").append(Arrays.toString(ranges));
builder.append(", layer name: \"").append(getLayerName()).append("\""); builder.append(", layer name: \"").append(getLayerName()).append("\"");
builder.append(", layer id: ").append(getLayerId());
if (groupId != -1) {
builder.append(", group id: ").append(groupId);
}
if (isGroup) {
builder.append(", isGroup");
}
if (isDivider) {
builder.append(", isDivider");
}
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }
public enum SectionDividerSetting {
LAYER(0), OPEN_FOLDER(1), CLOSED_FOLDER(2), BOUNDING_SECTION_DIVIDER(3);
SectionDividerSetting(int value) { this.value = value;}
private final int value;
public int value() { return value; }
public static SectionDividerSetting valueOf(int value){
for(SectionDividerSetting rt : SectionDividerSetting.values()){
if(rt.value == value){
return rt;
}
}
return null;
}
}
} }

View File

@ -37,6 +37,7 @@ import com.twelvemonkeys.imageio.metadata.iptc.IPTC;
import com.twelvemonkeys.imageio.metadata.tiff.TIFF; import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
import com.twelvemonkeys.lang.StringUtil; import com.twelvemonkeys.lang.StringUtil;
import com.twelvemonkeys.util.FilterIterator; import com.twelvemonkeys.util.FilterIterator;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataNode;
@ -388,21 +389,21 @@ public final class PSDMetadata extends AbstractMetadata {
node.setAttribute("bottom", String.valueOf(psdLayerInfo.bottom)); node.setAttribute("bottom", String.valueOf(psdLayerInfo.bottom));
node.setAttribute("right", String.valueOf(psdLayerInfo.right)); node.setAttribute("right", String.valueOf(psdLayerInfo.right));
node.setAttribute("layerId", String.valueOf(psdLayerInfo.getLayerId())); node.setAttribute("layerId", String.valueOf(psdLayerInfo.getLayerId()));
node.setAttribute("groupLayerId", String.valueOf(psdLayerInfo.groupLayerId)); if (psdLayerInfo.groupId != -1) {
node.setAttribute("groupId", String.valueOf(psdLayerInfo.groupId));
}
node.setAttribute("blendMode", PSDUtil.intToStr(psdLayerInfo.blendMode.blendMode)); node.setAttribute("blendMode", PSDUtil.intToStr(psdLayerInfo.blendMode.blendMode));
node.setAttribute("opacity", String.valueOf(psdLayerInfo.blendMode.opacity)); // 0-255 node.setAttribute("opacity", String.valueOf(psdLayerInfo.blendMode.opacity)); // 0-255
node.setAttribute("clipping", getClippingValue(psdLayerInfo.blendMode.clipping)); // Enum: 0: Base, 1: Non-base, n: unknown node.setAttribute("clipping", getClippingValue(psdLayerInfo.blendMode.clipping)); // Enum: 0: Base, 1: Non-base, n: unknown
node.setAttribute("flags", String.valueOf(psdLayerInfo.blendMode.flags)); node.setAttribute("flags", String.valueOf(psdLayerInfo.blendMode.flags));
if ((psdLayerInfo.group)){ if ((psdLayerInfo.isGroup)) {
node.setAttribute("group", String.valueOf(psdLayerInfo.group)); node.setAttribute("group", "true");
} }
if ((psdLayerInfo.isDivider)) {
if ((psdLayerInfo.sectionDivider)) { node.setAttribute("sectionDivider", "true");
node.setAttribute("sectionDivider", String.valueOf(psdLayerInfo.sectionDivider));
} }
if ((psdLayerInfo.blendMode.flags & 0x01) != 0) { if ((psdLayerInfo.blendMode.flags & 0x01) != 0) {
node.setAttribute("transparencyProtected", "true"); node.setAttribute("transparencyProtected", "true");
} }

View File

@ -545,38 +545,24 @@ public class PSDImageReaderTest extends ImageReaderAbstractTest<PSDImageReader>
assertEquals(layerInfos.size(), 5); assertEquals(layerInfos.size(), 5);
PSDLayerInfo groupedLayer = null; PSDLayerInfo sectionDividerLayer = layerInfos.get(1);
PSDLayerInfo groupLayer = null; PSDLayerInfo groupedLayer = layerInfos.get(2);
PSDLayerInfo sectionDividerLayer = null; PSDLayerInfo groupLayer = layerInfos.get(3);
for (PSDLayerInfo layerInfo : layerInfos) {
if (layerInfo.getLayerId() == 5) {
groupedLayer = layerInfo;
}
if (layerInfo.getLayerId() == 6) {
groupLayer = layerInfo;
}
if (layerInfo.getLayerId() == 7) {
sectionDividerLayer = layerInfo;
}
}
assertNotNull(groupedLayer); assertNotNull(groupedLayer);
assertEquals((int) groupedLayer.groupLayerId, 6); assertEquals(groupedLayer.groupId, 6);
assertEquals(groupedLayer.group, false); assertFalse(groupedLayer.isGroup);
assertEquals(groupedLayer.sectionDivider, false); assertFalse(groupedLayer.isDivider);
assertNotNull(groupLayer); assertNotNull(groupLayer);
assertNull(groupLayer.groupLayerId); assertEquals(-1, groupLayer.groupId);
assertEquals(groupLayer.group, true); assertTrue(groupLayer.isGroup);
assertEquals(groupLayer.sectionDivider, false); assertFalse(groupLayer.isDivider);
assertNotNull(sectionDividerLayer); assertNotNull(sectionDividerLayer);
assertNull(sectionDividerLayer.groupLayerId); assertEquals(-1, sectionDividerLayer.groupId);
assertEquals(sectionDividerLayer.group, false); assertFalse(sectionDividerLayer.isGroup);
assertEquals(sectionDividerLayer.sectionDivider, true); assertTrue(sectionDividerLayer.isDivider);
} }
} }
} }