mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-05 04:25:29 -04:00
Support Group Layer in psd (#648)
(cherry picked from commit dc0bdcbd5bb2506ef69262126fb6e5830d5e9e4c)
This commit is contained in:
parent
6c27ec6b30
commit
c0b2769e3b
@ -708,4 +708,5 @@ interface PSD extends com.twelvemonkeys.imageio.metadata.psd.PSD {
|
|||||||
int PxSD = 'P' << 24 | 'x' << 16 | 'S' << 8 | 'D';
|
int PxSD = 'P' << 24 | 'x' << 16 | 'S' << 8 | 'D';
|
||||||
int luni = 'l' << 24 | 'u' << 16 | 'n' << 8 | 'i';
|
int luni = 'l' << 24 | 'u' << 16 | 'n' << 8 | 'i';
|
||||||
int lyid = 'l' << 24 | 'y' << 16 | 'i' << 8 | 'd';
|
int lyid = 'l' << 24 | 'y' << 16 | 'i' << 8 | 'd';
|
||||||
|
int lsct = 'l' << 24 | 's' << 16 | 'c' << 8 | 't';
|
||||||
}
|
}
|
||||||
|
@ -947,8 +947,42 @@ public final class PSDImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
if (pParseData && metadata.layerInfo == null) {
|
if (pParseData && metadata.layerInfo == null) {
|
||||||
PSDLayerInfo[] layerInfos = new PSDLayerInfo[Math.abs(layerCount)];
|
PSDLayerInfo[] layerInfos = new PSDLayerInfo[Math.abs(layerCount)];
|
||||||
|
|
||||||
|
Stack<List<PSDLayerInfo>> groupStack = new Stack<>();
|
||||||
|
List<PSDLayerInfo> groupedLayerInfo = null;
|
||||||
|
|
||||||
for (int i = 0; i < layerInfos.length; i++) {
|
for (int i = 0; i < layerInfos.length; i++) {
|
||||||
layerInfos[i] = new PSDLayerInfo(header.largeFormat, imageInput);
|
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.layerInfo = Arrays.asList(layerInfos);
|
||||||
|
@ -57,6 +57,12 @@ final class PSDLayerInfo {
|
|||||||
private String unicodeLayerName;
|
private String unicodeLayerName;
|
||||||
private int layerId;
|
private int layerId;
|
||||||
|
|
||||||
|
Integer groupLayerId;
|
||||||
|
Boolean group = false;
|
||||||
|
Boolean sectionDivider = false;
|
||||||
|
|
||||||
|
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();
|
||||||
left = pInput.readInt();
|
left = pInput.readInt();
|
||||||
@ -132,6 +138,7 @@ 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);
|
||||||
@ -144,7 +151,10 @@ final class PSDLayerInfo {
|
|||||||
}
|
}
|
||||||
layerId = pInput.readInt();
|
layerId = pInput.readInt();
|
||||||
break;
|
break;
|
||||||
|
case PSD.lsct:
|
||||||
|
sectionDividerSettingType = SectionDividerSetting.valueOf(pInput.readInt());
|
||||||
|
pInput.skipBytes(resourceLength - 4);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// TODO: Parse more data...
|
// TODO: Parse more data...
|
||||||
pInput.skipBytes(resourceLength);
|
pInput.skipBytes(resourceLength);
|
||||||
@ -191,4 +201,22 @@ final class PSDLayerInfo {
|
|||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,12 +387,22 @@ public final class PSDMetadata extends AbstractMetadata {
|
|||||||
node.setAttribute("left", String.valueOf(psdLayerInfo.left));
|
node.setAttribute("left", String.valueOf(psdLayerInfo.left));
|
||||||
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("groupLayerId", String.valueOf(psdLayerInfo.groupLayerId));
|
||||||
|
|
||||||
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)){
|
||||||
|
node.setAttribute("group", String.valueOf(psdLayerInfo.group));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((psdLayerInfo.sectionDivider)) {
|
||||||
|
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");
|
||||||
}
|
}
|
||||||
|
@ -247,6 +247,11 @@ public final class PSDMetadataFormat extends IIOMetadataFormatImpl {
|
|||||||
addAttribute("LayerInfo", "opacity", DATATYPE_INTEGER, false, "0");
|
addAttribute("LayerInfo", "opacity", DATATYPE_INTEGER, false, "0");
|
||||||
addAttribute("LayerInfo", "clipping", DATATYPE_STRING, false, "base", Arrays.asList("base", "non-base"));
|
addAttribute("LayerInfo", "clipping", DATATYPE_STRING, false, "base", Arrays.asList("base", "non-base"));
|
||||||
addAttribute("LayerInfo", "flags", DATATYPE_INTEGER, false, "0");
|
addAttribute("LayerInfo", "flags", DATATYPE_INTEGER, false, "0");
|
||||||
|
addAttribute("LayerInfo", "layerId", DATATYPE_INTEGER, false, null);
|
||||||
|
addAttribute("LayerInfo", "groupLayerId", DATATYPE_INTEGER, false, null);
|
||||||
|
addAttribute("LayerInfo", "group", DATATYPE_BOOLEAN, false, "false");
|
||||||
|
addAttribute("LayerInfo", "sectionDivider", DATATYPE_INTEGER, false, "false");
|
||||||
|
|
||||||
|
|
||||||
// Redundant (derived from flags)
|
// Redundant (derived from flags)
|
||||||
addAttribute("LayerInfo", "transparencyProtected", DATATYPE_BOOLEAN, false, "false");
|
addAttribute("LayerInfo", "transparencyProtected", DATATYPE_BOOLEAN, false, "false");
|
||||||
|
@ -532,4 +532,51 @@ public class PSDImageReaderTest extends ImageReaderAbstractTest<PSDImageReader>
|
|||||||
assertEquals("If_The_Layer_Name_Is_Really_Long_Oh_No_What_Do_I_Do", ((IIOMetadataNode) layerInfo.item(0)).getAttribute("name"));
|
assertEquals("If_The_Layer_Name_Is_Really_Long_Oh_No_What_Do_I_Do", ((IIOMetadataNode) layerInfo.item(0)).getAttribute("name"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGroupLayerRead() throws IOException {
|
||||||
|
PSDImageReader imageReader = createReader();
|
||||||
|
|
||||||
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/psd/layer_group_32bit5x5.psd"))) {
|
||||||
|
imageReader.setInput(stream);
|
||||||
|
|
||||||
|
IIOMetadata metadata = imageReader.getImageMetadata(0);
|
||||||
|
List<PSDLayerInfo> layerInfos = ((PSDMetadata) metadata).layerInfo;
|
||||||
|
|
||||||
|
assertEquals(layerInfos.size(), 5);
|
||||||
|
|
||||||
|
PSDLayerInfo groupedLayer = null;
|
||||||
|
PSDLayerInfo groupLayer = null;
|
||||||
|
PSDLayerInfo sectionDividerLayer = null;
|
||||||
|
for (PSDLayerInfo layerInfo : layerInfos) {
|
||||||
|
if (layerInfo.getLayerId() == 5) {
|
||||||
|
groupedLayer = layerInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layerInfo.getLayerId() == 6) {
|
||||||
|
groupLayer = layerInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layerInfo.getLayerId() == 7) {
|
||||||
|
sectionDividerLayer = layerInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(groupedLayer);
|
||||||
|
assertEquals((int) groupedLayer.groupLayerId, 6);
|
||||||
|
assertEquals(groupedLayer.group, false);
|
||||||
|
assertEquals(groupedLayer.sectionDivider, false);
|
||||||
|
|
||||||
|
assertNotNull(groupLayer);
|
||||||
|
assertNull(groupLayer.groupLayerId);
|
||||||
|
assertEquals(groupLayer.group, true);
|
||||||
|
assertEquals(groupLayer.sectionDivider, false);
|
||||||
|
|
||||||
|
assertNotNull(sectionDividerLayer);
|
||||||
|
assertNull(sectionDividerLayer.groupLayerId);
|
||||||
|
assertEquals(sectionDividerLayer.group, false);
|
||||||
|
assertEquals(sectionDividerLayer.sectionDivider, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user