Tiff with layers boolean?

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Tiff with layers boolean?

Post by fmw42 »

In PSD, it adds a new 0 layer, which is the flattened combination of the two original layers in the TIFF.
246246
Posts: 190
Joined: 2015-07-06T07:38:22-07:00
Authentication code: 1151

Re: Tiff with layers boolean?

Post by 246246 »

IT seems Layer-readable tiff contains 8BIMLayr in 37724 tag, as documented in http://partners.adobe.com/public/develo ... toshop.pdf

Code: Select all

$ tiffinfo greenscreen_people_sitting/xoio_people_sitting_001.tif 2> /dev/null | perl -ne 'if (/^\s*Tag 37724:\s*(.*)/) {print map {s/^0x(.*)/pack("H*", sprintf("%02x", hex($1)))/re} split(/,/, $1)}' | strings | grep 8BIMLayr
8BIMLayr
 
But unreadable one does not contain it, instead it contains MIB8ryaL

Code: Select all

$ tiffinfo test.tif 2> /dev/null | perl -ne 'if (/^\s*Tag 37724:\s*(.*)/) {print map {s/^0x(.*)/pack("H*", sprintf("%02x", hex($1)))/re} split(/,/, $1)}' | strings | grep 8BIMLayr     
                    
$ tiffinfo test.tif 2> /dev/null | perl -ne 'if (/^\s*Tag 37724:\s*(.*)/) {print map {s/^0x(.*)/pack("H*", sprintf("%02x", hex($1)))/re} split(/,/, $1)}' | strings | grep MIB8ryaL
MIB8ryaL
246246
Posts: 190
Joined: 2015-07-06T07:38:22-07:00
Authentication code: 1151

Re: Tiff with layers boolean?

Post by 246246 »

When I save tiff in Photoshop (CS6 Windows), if I select Byte Order as Macintosh, the bytes will becomes 8BIMLayr, that is detectable layer from ImageMagick.
But if I select IBM PC, it becomes MIB8ryaL that is undetectable for ImageMagick.

I'm not sure it is a spec of photoshop, but quick search lead me to the following that shows it happened at least in 2004. http://macscripter.net/viewtopic.php?id=9191

For comparison, here is the one saved Byte Order as Macintosh (MSB) from the same psd.
https://www.dropbox.com/s/ognl1qtj5g55i ... 2.tif?dl=0

Both has the exact same bytes of 37724 (0x953c) tag:

Code: Select all

$ exiv2 -pS test{,2}.tif | egrep -i '(STRUCTURE|offset \||0x935c)'
STRUCTURE OF TIFF FILE (II): test.tif
 address |    tag                           |      type |    count |   offset | value
     298 | 0x935c                           | UNDEFINED |   111516 |    92724 |  ...
STRUCTURE OF TIFF FILE (MM): test2.tif
 address |    tag                           |      type |    count |   offset | value
     298 | 0x935c                           | UNDEFINED |   111516 |    95440 |  ...
First several bytes are the following.

Code: Select all

$ od -cv -j 92724 -N 111516 test.tif | head -50
0265064   A   d   o   b   e       P   h   o   t   o   s   h   o   p
0265104   D   o   c   u   m   e   n   t       D   a   t   a       B   l
0265124   o   c   k  \0   M   I   B   8   n   r   T   M  \0  \0  \0  \0
0265144   M   I   B   8   r   y   a   L 035 263 001  \0 002  \0 025  \0
0265164  \0  \0 026  \0  \0  \0   d 001  \0  \0   q 001  \0  \0 004  \0
0265204 377 377   e 303  \0  \0  \0  \0 030  \r  \0  \0 001  \0   4 231
0265224  \0  \0 002  \0 030  \r  \0  \0   M   I   B   8   m   r   o   n
0265244 377  \0  \b  \0   , 001  \0  \0  \0  \0  \0  \0   (  \0  \0  \0
0265264  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377
0265304  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377
0265324  \0  \0 377 377  \0  \0 377 377  \a   L   a   y   e   r       0
0265344   M   I   B   8   i   n   u   l 024  \0  \0  \0  \a  \0  \0  \0
0265364   L  \0   a  \0   y  \0   e  \0   r  \0      \0   0  \0  \0  \0
0265404   M   I   B   8   d   i   y   l 004  \0  \0  \0  \b  \0  \0  \0
0265424   M   I   B   8   l   b   l   c 004  \0  \0  \0 001  \0  \0  \0
0265444   M   I   B   8   x   f   n   i 004  \0  \0  \0  \0  \0  \0  \0
0265464   M   I   B   8   o   k   n   k 004  \0  \0  \0  \0  \0  \0  \0
0265504   M   I   B   8   f   p   s   l 004  \0  \0  \0  \0  \0  \0  \0
0265524   M   I   B   8   r   l   c   l  \b  \0  \0  \0  \0  \0  \0  \0
0265544  \0  \0  \0  \0   M   I   B   8   d   m   h   s   H  \0  \0  \0
0265564 001  \0  \0  \0   M   I   B   8   t   s   u   c  \0  \0  \0  \0
0265604   4  \0  \0  \0 020  \0  \0  \0 001  \0  \0  \0  \0  \0  \b  \0
0265624  \0  \0   m   e   t   a   d   a   t   a 001  \0  \0  \0  \t  \0
0265644  \0  \0   l   a   y   e   r   T   i   m   e   b   u   o   d   Y
0265664 336   ` 356   `   q 325   A  \0   M   I   B   8   p   r   x   f
0265704 020  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0265724  \0  \0  \0  \0   k  \0  \0  \0   o  \0  \0  \0 022 001  \0  \0
0265744   ! 001  \0  \0 004  \0 377 377   l   #  \0  \0  \0  \0   ^  \a
0265764  \0  \0 001  \0   ^  \a  \0  \0 002  \0   ^  \a  \0  \0   M   I
0266004   B   8   m   r   o   n 263  \0  \b  \0   , 001  \0  \0  \0  \0
0266024  \0  \0   (  \0  \0  \0  \0  \0 377 377  \0  \0 377 377  \0  \0
0266044 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0
0266064 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377  \a   L
0266104   a   y   e   r       1   M   I   B   8   i   n   u   l 024  \0
0266124  \0  \0  \a  \0  \0  \0   L  \0   a  \0   y  \0   e  \0   r  \0
0266144      \0   1  \0  \0  \0   M   I   B   8   d   i   y   l 004  \0
0266164  \0  \0  \t  \0  \0  \0   M   I   B   8   l   b   l   c 004  \0
0266204  \0  \0 001  \0  \0  \0   M   I   B   8   x   f   n   i 004  \0
0266224  \0  \0  \0  \0  \0  \0   M   I   B   8   o   k   n   k 004  \0
0266244  \0  \0  \0  \0  \0  \0   M   I   B   8   f   p   s   l 004  \0
0266264  \0  \0  \0  \0  \0  \0   M   I   B   8   r   l   c   l  \b  \0
0266304  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0   M   I   B   8   d   m
0266324   h   s   H  \0  \0  \0 001  \0  \0  \0   M   I   B   8   t   s
0266344   u   c  \0  \0  \0  \0   4  \0  \0  \0 020  \0  \0  \0 001  \0
0266364  \0  \0  \0  \0  \b  \0  \0  \0   m   e   t   a   d   a   t   a
0266404 001  \0  \0  \0  \t  \0  \0  \0   l   a   y   e   r   T   i   m
0266424   e   b   u   o   d 315 336   ` 356   `   q 325   A  \0   M   I
0266444   B   8   p   r   x   f 020  \0  \0  \0  \0  \0  \0  \0  \0  \0
0266464  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0 001  \0  \f  \0  \f  \0
0266504  \f  \0  \f  \0 020  \0 024  \0 030  \0 036  \0   $  \0   (  \0

Code: Select all

$ od -cv -j 95440 -N 111516 test2.tif | head -50
0272320   A   d   o   b   e       P   h   o   t   o   s   h   o   p
0272340   D   o   c   u   m   e   n   t       D   a   t   a       B   l
0272360   o   c   k  \0   8   B   I   M   M   T   r   n  \0  \0  \0  \0
0272400   8   B   I   M   L   a   y   r  \0 001 263 035  \0 002  \0  \0
0272420  \0 025  \0  \0  \0 026  \0  \0 001   d  \0  \0 001   q  \0 004
0272440 377 377  \0  \0 303   e  \0  \0  \0  \0  \r 030  \0 001  \0  \0
0272460 231   4  \0 002  \0  \0  \r 030   8   B   I   M   n   o   r   m
0272500 377  \0  \b  \0  \0  \0 001   ,  \0  \0  \0  \0  \0  \0  \0   (
0272520  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377
0272540  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377
0272560  \0  \0 377 377  \0  \0 377 377  \a   L   a   y   e   r       0
0272600   8   B   I   M   l   u   n   i  \0  \0  \0 024  \0  \0  \0  \a
0272620  \0   L  \0   a  \0   y  \0   e  \0   r  \0      \0   0  \0  \0
0272640   8   B   I   M   l   y   i   d  \0  \0  \0 004  \0  \0  \0  \b
0272660   8   B   I   M   c   l   b   l  \0  \0  \0 004 001  \0  \0  \0
0272700   8   B   I   M   i   n   f   x  \0  \0  \0 004  \0  \0  \0  \0
0272720   8   B   I   M   k   n   k   o  \0  \0  \0 004  \0  \0  \0  \0
0272740   8   B   I   M   l   s   p   f  \0  \0  \0 004  \0  \0  \0  \0
0272760   8   B   I   M   l   c   l   r  \0  \0  \0  \b  \0  \0  \0  \0
0273000  \0  \0  \0  \0   8   B   I   M   s   h   m   d  \0  \0  \0   H
0273020  \0  \0  \0 001   8   B   I   M   c   u   s   t  \0  \0  \0  \0
0273040  \0  \0  \0   4  \0  \0  \0 020  \0  \0  \0 001  \0  \0  \0  \0
0273060  \0  \b   m   e   t   a   d   a   t   a  \0  \0  \0 001  \0  \0
0273100  \0  \t   l   a   y   e   r   T   i   m   e   d   o   u   b   A
0273120 325   q 257 355 241 027   5  \0   8   B   I   M   f   x   r   p
0273140  \0  \0  \0 020  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0273160  \0  \0  \0  \0  \0  \0  \0   k  \0  \0  \0   o  \0  \0 001 022
0273200  \0  \0 001   !  \0 004 377 377  \0  \0   #   l  \0  \0  \0  \0
0273220  \a   ^  \0 001  \0  \0  \a   ^  \0 002  \0  \0  \a   ^   8   B
0273240   I   M   n   o   r   m 263  \0  \b  \0  \0  \0 001   ,  \0  \0
0273260  \0  \0  \0  \0  \0   (  \0  \0 377 377  \0  \0 377 377  \0  \0
0273300 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0
0273320 377 377  \0  \0 377 377  \0  \0 377 377  \0  \0 377 377  \a   L
0273340   a   y   e   r       1   8   B   I   M   l   u   n   i  \0  \0
0273360  \0 024  \0  \0  \0  \a  \0   L  \0   a  \0   y  \0   e  \0   r
0273400  \0      \0   1  \0  \0   8   B   I   M   l   y   i   d  \0  \0
0273420  \0 004  \0  \0  \0  \t   8   B   I   M   c   l   b   l  \0  \0
0273440  \0 004 001  \0  \0  \0   8   B   I   M   i   n   f   x  \0  \0
0273460  \0 004  \0  \0  \0  \0   8   B   I   M   k   n   k   o  \0  \0
0273500  \0 004  \0  \0  \0  \0   8   B   I   M   l   s   p   f  \0  \0
0273520  \0 004  \0  \0  \0  \0   8   B   I   M   l   c   l   r  \0  \0
0273540  \0  \b  \0  \0  \0  \0  \0  \0  \0  \0   8   B   I   M   s   h
0273560   m   d  \0  \0  \0   H  \0  \0  \0 001   8   B   I   M   c   u
0273600   s   t  \0  \0  \0  \0  \0  \0  \0   4  \0  \0  \0 020  \0  \0
0273620  \0 001  \0  \0  \0  \0  \0  \b   m   e   t   a   d   a   t   a
0273640  \0  \0  \0 001  \0  \0  \0  \t   l   a   y   e   r   T   i   m
0273660   e   d   o   u   b   A 325   q 257 355 241 027 253  \0   8   B
0273700   I   M   f   x   r   p  \0  \0  \0 020  \0  \0  \0  \0  \0  \0
0273720  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0 001  \0  \f  \0  \f
0273740  \0  \f  \0  \f  \0 020  \0 024  \0 030  \0 036  \0   $  \0   (
josephaaroncampbell
Posts: 40
Joined: 2015-07-14T19:18:45-07:00
Authentication code: 1151
Location: Chicago, IL

Re: Tiff with layers boolean?

Post by josephaaroncampbell »

dlemstra wrote:Can you share your image on something like dropbox? The one where you think/know that it has layers?

The following link has two image files:

https://www.dropbox.com/sh/xrfaiejq7k8x ... gmjCa?dl=0

1. a layered tiff created using Adobe Photoshop CS5 called "layers_pSHOP.tif"
2. a layered tiff created using Image Magick called "layers_IM.tif"


I hope this helps. The '%[tiff:has-layers]' does not function on either image using version:
ImageMagick 6.9.1-10 Q16 x64 2015-07-25 (binary release)
windows 7 professional x64

thank you for your help!
josephaaroncampbell
Posts: 40
Joined: 2015-07-14T19:18:45-07:00
Authentication code: 1151
Location: Chicago, IL

Re: Tiff with layers boolean?

Post by josephaaroncampbell »

246246 wrote:When I save tiff in Photoshop (CS6 Windows), if I select Byte Order as Macintosh, the bytes will becomes 8BIMLayr, that is detectable layer from ImageMagick.
But if I select IBM PC, it becomes MIB8ryaL that is undetectable for ImageMagick.
I had thought about this earlier. I wish I would have tried it. I just did a test and saved a layered tiff in photoshop using the MAC byte order. Sure enough "%[tiff:has-layers]" worked and returned 'true'. (thanks for adding this!)

Now that I can see how this works, is there a way for this to function with 'IBM PC' byte order?

My end goal is to scan several thousand tiff files looking for layered tiffs and I am sure they are all in the 'IBM PC' byte order.

Thank You!
User avatar
dlemstra
Posts: 1570
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Tiff with layers boolean?

Post by dlemstra »

I will work on a fix for this later this week and get back to this topic when I am done.
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate
246246
Posts: 190
Joined: 2015-07-06T07:38:22-07:00
Authentication code: 1151

Re: Tiff with layers boolean?

Post by 246246 »

josephaaroncampbell wrote: Now that I can see how this works, is there a way for this to function with 'IBM PC' byte order?
I have tried to create a patch (against 6.9.1-10) and currently it works for your image (and my image also).
It needs a verification from developers, and may have better approach, but it is enough small for upload here.

Hope it saving time for developers.

Code: Select all

diff -uprN coders.org/psd.c coders/psd.c
--- coders.org/psd.c	2015-07-25 05:15:38.000000000 +0900
+++ coders/psd.c	2015-08-11 05:14:32.457317121 +0900
@@ -479,7 +479,7 @@ static inline size_t GetPSDPacketSize(Im
 static inline MagickSizeType GetPSDSize(const PSDInfo *psd_info,Image *image)
 {
   if (psd_info->version == 1)
-    return((MagickSizeType) ReadBlobMSBLong(image));
+    return((MagickSizeType)(image->endian==2 ? ReadBlobMSBLong(image) : ReadBlobLSBLong(image)));
   return((MagickSizeType) ReadBlobMSBLongLong(image));
 }
 
@@ -592,55 +592,55 @@ static void ParseImageResourceBlocks(Ima
   return;
 }
 
-static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode)
+static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode, MagickStatusType isLsb)
 {
   if (mode == (const char *) NULL)
     return(OverCompositeOp);
-  if (LocaleNCompare(mode,"norm",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"norm":"mron",4) == 0)
     return(OverCompositeOp);
-  if (LocaleNCompare(mode,"mul ",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"mul ":" lum",4) == 0)
     return(MultiplyCompositeOp);
-  if (LocaleNCompare(mode,"diss",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"diss":"ssid",4) == 0)
     return(DissolveCompositeOp);
-  if (LocaleNCompare(mode,"diff",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"diff":"ffid",4) == 0)
     return(DifferenceCompositeOp);
-  if (LocaleNCompare(mode,"dark",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"dark":"krad",4) == 0)
     return(DarkenCompositeOp);
-  if (LocaleNCompare(mode,"lite",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"lite":"etil",4) == 0)
     return(LightenCompositeOp);
-  if (LocaleNCompare(mode,"hue ",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"hue ":" euh",4) == 0)
     return(HueCompositeOp);
-  if (LocaleNCompare(mode,"sat ",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"sat ":" tas",4) == 0)
     return(SaturateCompositeOp);
-  if (LocaleNCompare(mode,"colr",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"colr":"rloc",4) == 0)
     return(ColorizeCompositeOp);
-  if (LocaleNCompare(mode,"lum ",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"lum ":" mul",4) == 0)
     return(LuminizeCompositeOp);
-  if (LocaleNCompare(mode,"scrn",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"scrn":"nrcs",4) == 0)
     return(ScreenCompositeOp);
-  if (LocaleNCompare(mode,"over",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"over":"revo",4) == 0)
     return(OverlayCompositeOp);
-  if (LocaleNCompare(mode,"hLit",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"hLit":"tiLh",4) == 0)
     return(HardLightCompositeOp);
-  if (LocaleNCompare(mode,"sLit",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"sLit":"tiLs",4) == 0)
     return(SoftLightCompositeOp);
-  if (LocaleNCompare(mode,"smud",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"smud":"dums",4) == 0)
     return(ExclusionCompositeOp);
-  if (LocaleNCompare(mode,"div ",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"div ":" vid",4) == 0)
     return(ColorDodgeCompositeOp);
-  if (LocaleNCompare(mode,"idiv",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"idiv":"vidi",4) == 0)
     return(ColorBurnCompositeOp);
-  if (LocaleNCompare(mode,"lbrn",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"lbrn":"nrbl",4) == 0)
     return(LinearBurnCompositeOp);
-  if (LocaleNCompare(mode,"lddg",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"lddg":"gddl",4) == 0)
     return(LinearDodgeCompositeOp);
-  if (LocaleNCompare(mode,"lLit",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"lLit":"tiLl",4) == 0)
     return(LinearLightCompositeOp);
-  if (LocaleNCompare(mode,"vLit",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"vLit":"tiLv",4) == 0)
     return(VividLightCompositeOp);
-  if (LocaleNCompare(mode,"pLit",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"pLit":"tiLp",4) == 0)
     return(PinLightCompositeOp);
-  if (LocaleNCompare(mode,"hMix",4) == 0)
+  if (LocaleNCompare(mode,isLsb==MagickFalse?"hMix":"xiMh",4) == 0)
     return(HardMixCompositeOp);
   return(OverCompositeOp);
 }
@@ -827,16 +827,20 @@ static inline MagickOffsetType *ReadPSDR
 
   ssize_t
     y;
+  
+  MagickStatusType
+    isLsb;
 
+  isLsb = image->endian == 1 ? MagickTrue : MagickFalse;
   offsets=(MagickOffsetType *) AcquireQuantumMemory(size,sizeof(*offsets));
   if(offsets != (MagickOffsetType *) NULL)
     {
       for (y=0; y < (ssize_t) size; y++)
       {
         if (psd_info->version == 1)
-          offsets[y]=(MagickOffsetType) ReadBlobMSBShort(image);
+          offsets[y]=(MagickOffsetType) (isLsb == MagickTrue ? ReadBlobLSBShort(image) : ReadBlobMSBShort(image));
         else
-          offsets[y]=(MagickOffsetType) ReadBlobMSBLong(image);
+          offsets[y]=(MagickOffsetType) (isLsb == MagickTrue ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image));
       }
     }
   return offsets;
@@ -1134,7 +1138,8 @@ static MagickStatusType ReadPSDLayer(Ima
     message[MaxTextExtent];
 
   MagickStatusType
-    status;
+    status,
+    isLsb;
 
   PSDCompressionType
     compression;
@@ -1142,12 +1147,13 @@ static MagickStatusType ReadPSDLayer(Ima
   ssize_t
     j;
 
+  isLsb = image->endian == 1 ? MagickTrue : MagickFalse;
+
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
       "    setting up new layer image");
   (void) SetImageBackgroundColor(layer_info->image);
-  layer_info->image->compose=PSDBlendModeToCompositeOperator(
-    layer_info->blendkey);
+  layer_info->image->compose=PSDBlendModeToCompositeOperator(layer_info->blendkey, isLsb);
   if (layer_info->visible == MagickFalse)
     {
       layer_info->image->compose=NoCompositeOp;
@@ -1179,7 +1185,7 @@ static MagickStatusType ReadPSDLayer(Ima
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
         "    reading data for channel %.20g",(double) j);
 
-    compression=(PSDCompressionType) ReadBlobMSBShort(layer_info->image);
+    compression=(PSDCompressionType) (isLsb == MagickTrue) ? ReadBlobLSBShort(layer_info->image) : ReadBlobMSBShort(layer_info->image);
     layer_info->image->compression=ConvertPSDCompression(compression);
     if (layer_info->channel_info[j].type == -1)
       layer_info->image->matte=MagickTrue;
@@ -1222,7 +1228,8 @@ ModuleExport MagickStatusType ReadPSDLay
     size;
 
   MagickStatusType
-    status;
+    status,
+    isLsb;
 
   register ssize_t
     i;
@@ -1232,21 +1239,23 @@ ModuleExport MagickStatusType ReadPSDLay
     j,
     number_layers;
 
+  isLsb = image->endian == 1 ? MagickTrue : MagickFalse;
+  
   size=GetPSDSize(psd_info,image);
   if (size == 0)
     {
       /*
         Skip layers & masks.
       */
-      (void) ReadBlobMSBLong(image);
+      (isLsb == MagickTrue) ? (void) ReadBlobLSBLong(image) : (void) ReadBlobMSBLong(image);
       count=ReadBlob(image,4,(unsigned char *) type);
       status=MagickFalse;
-      if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
+      if ((count == 0) || (LocaleNCompare(type,(isLsb == MagickTrue) ? "MIB8" : "8BIM",4) != 0))
         return(MagickTrue);
       else
         {
           count=ReadBlob(image,4,(unsigned char *) type);
-          if ((count != 0) && (LocaleNCompare(type,"Lr16",4) == 0))
+          if ((count != 0) && (LocaleNCompare(type,(isLsb == MagickTrue) ? "61rL": "Lr16",4) == 0))
             size=GetPSDSize(psd_info,image);
           else
             return(MagickTrue);
@@ -1256,7 +1265,7 @@ ModuleExport MagickStatusType ReadPSDLay
   if (size != 0)
     {
       layer_info=(LayerInfo *) NULL;
-      number_layers=(short) ReadBlobMSBShort(image);
+      number_layers=(short)((isLsb == MagickTrue) ? ReadBlobLSBShort(image) : ReadBlobMSBShort(image));
 
       if (number_layers < 0)
         {
@@ -1307,13 +1316,13 @@ ModuleExport MagickStatusType ReadPSDLay
         if (image->debug != MagickFalse)
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
             "  reading layer #%.20g",(double) i+1);
-        layer_info[i].page.y=(int) ReadBlobMSBLong(image);
-        layer_info[i].page.x=(int) ReadBlobMSBLong(image);
-        y=(int) ReadBlobMSBLong(image);
-        x=(int) ReadBlobMSBLong(image);
+        layer_info[i].page.y=(int)(isLsb == MagickTrue ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image));
+        layer_info[i].page.x=(int)(isLsb == MagickTrue ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image));
+        y=(int)(isLsb == MagickTrue ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image));
+        x=(int)(isLsb == MagickTrue ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image));
         layer_info[i].page.width=(ssize_t) (x-layer_info[i].page.x);
         layer_info[i].page.height=(ssize_t) (y-layer_info[i].page.y);
-        layer_info[i].channels=ReadBlobMSBShort(image);
+        layer_info[i].channels=isLsb == MagickTrue ? ReadBlobLSBShort(image) : ReadBlobMSBShort(image);
         if (layer_info[i].channels > MaxPSDChannels)
           {
             layer_info=DestroyLayerInfo(layer_info,number_layers);
@@ -1328,7 +1337,7 @@ ModuleExport MagickStatusType ReadPSDLay
             layer_info[i].page.width,(double) layer_info[i].channels);
         for (j=0; j < (ssize_t) layer_info[i].channels; j++)
         {
-          layer_info[i].channel_info[j].type=(short) ReadBlobMSBShort(image);
+          layer_info[i].channel_info[j].type=(short)(isLsb == MagickTrue ? ReadBlobLSBShort(image) : ReadBlobMSBShort(image));
           layer_info[i].channel_info[j].size=(size_t) GetPSDSize(psd_info,
             image);
           if (image->debug != MagickFalse)
@@ -1338,7 +1347,7 @@ ModuleExport MagickStatusType ReadPSDLay
               (double) layer_info[i].channel_info[j].size);
         }
         count=ReadBlob(image,4,(unsigned char *) type);
-        if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
+        if ((count == 0) || (LocaleNCompare(type,(isLsb == MagickTrue)?"MIB8":"8BIM",4) != 0))
           {
             if (image->debug != MagickFalse)
               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -1361,7 +1370,7 @@ ModuleExport MagickStatusType ReadPSDLay
             layer_info[i].visible ? "true" : "false");
         (void) ReadBlobByte(image);  /* filler */
 
-        size=ReadBlobMSBLong(image);
+        size=(isLsb == MagickTrue) ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image);
         if (size != 0)
           {
             MagickSizeType
@@ -1371,19 +1380,19 @@ ModuleExport MagickStatusType ReadPSDLay
             if (image->debug != MagickFalse)
               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                 "    layer contains additional info");
-            length=ReadBlobMSBLong(image);
+            length=(isLsb == MagickTrue) ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image);
             combined_length=length+4;
             if (length != 0)
               {
                 /*
                   Layer mask info.
                 */
-                layer_info[i].mask.page.y=(int) ReadBlobMSBLong(image);
-                layer_info[i].mask.page.x=(int) ReadBlobMSBLong(image);
+                layer_info[i].mask.page.y=(int)(isLsb == MagickTrue ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image));
+                layer_info[i].mask.page.x=(int)(isLsb == MagickTrue ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image));
                 layer_info[i].mask.page.height=(size_t)
-                  (ReadBlobMSBLong(image)-layer_info[i].mask.page.y);
+                  ((isLsb == MagickTrue ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image))-layer_info[i].mask.page.y);
                 layer_info[i].mask.page.width=(size_t)
-                  (ReadBlobMSBLong(image)-layer_info[i].mask.page.x);
+                  ((isLsb == MagickTrue ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image))-layer_info[i].mask.page.x);
                 layer_info[i].mask.background=(unsigned char) ReadBlobByte(
                   image);
                 layer_info[i].mask.flags=(unsigned char) ReadBlobByte(image);
@@ -1411,7 +1420,7 @@ ModuleExport MagickStatusType ReadPSDLay
                       image->filename);
                   }
               }
-            length=ReadBlobMSBLong(image);
+            length=(isLsb == MagickTrue) ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image);
             combined_length+=length+4;
             if (length != 0)
               {
@@ -1427,8 +1436,8 @@ ModuleExport MagickStatusType ReadPSDLay
                 */
                 for (j=0; j < (ssize_t) (length); j+=8)
                 {
-                  size_t blend_source=ReadBlobMSBLong(image);
-                  size_t blend_dest=ReadBlobMSBLong(image);
+                  size_t blend_source=(isLsb == MagickTrue) ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image);
+                  size_t blend_dest=(isLsb == MagickTrue) ? ReadBlobLSBLong(image) : ReadBlobMSBLong(image);
                   if (image->debug != MagickFalse)
                     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                       "        source(%x), dest(%x)",(unsigned int)
diff -uprN coders.org/tiff.c coders/tiff.c
--- coders.org/tiff.c	2015-07-24 10:06:38.000000000 +0900
+++ coders/tiff.c	2015-08-11 05:02:21.920607749 +0900
@@ -971,13 +971,13 @@ static void TIFFReadPhotoshopLayers(Imag
     return;
   for (i=0; i < (ssize_t) layer_info->length-8; i++)
   {
-    if (LocaleNCompare((const char *) (layer_info->datum+i),"8BIM",4) != 0)
+    if (LocaleNCompare((const char *) (layer_info->datum+i),image->endian==2?"8BIM":"MIB8",4) != 0)
       continue;
     i+=4;
-    if ((LocaleNCompare((const char *) (layer_info->datum+i),"Layr",4) == 0) ||
-        (LocaleNCompare((const char *) (layer_info->datum+i),"LMsk",4) == 0) ||
-        (LocaleNCompare((const char *) (layer_info->datum+i),"Lr16",4) == 0) ||
-        (LocaleNCompare((const char *) (layer_info->datum+i),"Lr32",4) == 0))
+    if ((LocaleNCompare((const char *) (layer_info->datum+i),image->endian==2?"Layr":"ryaL",4) == 0) ||
+        (LocaleNCompare((const char *) (layer_info->datum+i),image->endian==2?"LMsk":"ksML",4) == 0) ||
+        (LocaleNCompare((const char *) (layer_info->datum+i),image->endian==2?"Lr16":"61rL",4) == 0) ||
+        (LocaleNCompare((const char *) (layer_info->datum+i),image->endian==2?"Lr32":"23rL",4) == 0))
       break;
   }
   i+=4;
User avatar
dlemstra
Posts: 1570
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Tiff with layers boolean?

Post by dlemstra »

Thanks for the help. I was hoping that I did not have to touch psd.c but it seems I have to :)

It might be a better idea to set the endian to MSBEndian inside psd.c on line 1832 before we call ReadPSDLayers(). And then we can replace the calls to ReadBlobMSBShort with ReadBlobShort inside ReadPSDLayers. And to get rid of the lsb check inside PSDBlendModeToCompositeOperator we could also reverse layer_info.blendkey on line 1351 if the endian is LSB.

You are more then welcome to submit a new patch for this, but I can also do this myself tomorrow.
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate
246246
Posts: 190
Joined: 2015-07-06T07:38:22-07:00
Authentication code: 1151

Re: Tiff with layers boolean?

Post by 246246 »

josephaaroncampbell wrote:I had thought about this earlier. I wish I would have tried it. I just did a test and saved a layered tiff in photoshop using the MAC byte order. Sure enough "%[tiff:has-layers]" worked and returned 'true'. (thanks for adding this!)
I noticed one minor limitation (even in MAC Byte Order). If you saved empty layer in Photpshop - one layer has some image and another is really blank, it still exists in Photoshop when reopened. But ImageMagick ignore it, "%[tiff:has-layers]" does not return true. However it happens also true in psd, so I think it is limited feature. I believe it is usually harmless. But If you have to consider such tiff as "has-layers", you have to check binary (inside 37724 tag) somehow whether it contains 8BIMLayr (or MIB8ryaL). I hope you don't have such weird tiff. :D
dlemstra wrote:Thanks for the help. I was hoping that I did not have to touch psd.c but it seems I have to :)
I also hoped so... I have to spend some time to find ReadPSDRLEOffsets() need to be fixed.
dlemstra wrote:You are more then welcome to submit a new patch for this, but I can also do this myself tomorrow.
Of course you can do a better job, I'm just learning from source and do a quick & dirty work.
And we have time rags, so please do refine it by yourself. Good Luck! :D
User avatar
dlemstra
Posts: 1570
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Tiff with layers boolean?

Post by dlemstra »

Would it be possible for either of you to share a 16-bit LSB Tiff file from Photoshop? I would like to test my changes with a 16-bit file also.
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate
josephaaroncampbell
Posts: 40
Joined: 2015-07-14T19:18:45-07:00
Authentication code: 1151
Location: Chicago, IL

Re: Tiff with layers boolean?

Post by josephaaroncampbell »

dlemstra wrote:Would it be possible for either of you to share a 16-bit LSB Tiff file from Photoshop? I would like to test my changes with a 16-bit file also.

The following link is for a 16bit tiff with layers from photoshop. I confirmed the endianness with IM as LSB using the identify -verbose command.

https://www.dropbox.com/s/1ba9l0j8sl5pl ... B.tif?dl=0

Thanks!
User avatar
dlemstra
Posts: 1570
Joined: 2013-05-04T15:28:54-07:00
Authentication code: 6789
Contact:

Re: Tiff with layers boolean?

Post by dlemstra »

Thanks for providing that file (I love the colors :) ). I just submitted a patch to our GIT repository to resolve this issue for LSB TIFF files. This will be resolved in the next version of ImageMagick (6.9.2-0).
.NET + ImageMagick = Magick.NET https://github.com/dlemstra/Magick.NET, @MagickNET, Donate
josephaaroncampbell
Posts: 40
Joined: 2015-07-14T19:18:45-07:00
Authentication code: 1151
Location: Chicago, IL

Re: Tiff with layers boolean?

Post by josephaaroncampbell »

dlemstra wrote:Thanks for providing that file (I love the colors :) ). I just submitted a patch to our GIT repository to resolve this issue for LSB TIFF files. This will be resolved in the next version of ImageMagick (6.9.2-0).

Thanks! and I just downloaded the newest binary and can confirm that this is working for files created in photoshop.

Thank you so much for working on this!!
josephaaroncampbell
Posts: 40
Joined: 2015-07-14T19:18:45-07:00
Authentication code: 1151
Location: Chicago, IL

Re: Tiff with layers boolean?

Post by josephaaroncampbell »

I present a working windows batch file that contains the '%[tiff:has-layers]" to return the file names of images that contain photoshop layers:

Code: Select all

 
  
:: this script returns true or false if tiff file has layers, then output filename of true images to txt file
 
 @ECHO OFF
 
  :: change the drive to the supplied image file or folders drive location
  %~d1

  ::make the file/folder the current directory
  CD "%~p1"

  ::for every tiff DO the following actions

  FOR %%a in (*.tif) DO (
	ECHO 1: %%a
		FOR /F %%b IN ('identify -quiet -format "%%[tiff:has-layers]" %%a[0]') DO (
			ECHO 2: %%b
			 IF %%b == true ECHO %%a>>IM.txt 
                )
  )
  
  PAUSE 
Im new to this so if there are any pieces of advice please feel free to let me know. but thanks again to everyone who helped.

ImageMagick 6.9.2-0 Q16 x64 2015-08-15
Windows 7 Pro x64bit
246246
Posts: 190
Joined: 2015-07-06T07:38:22-07:00
Authentication code: 1151

Re: Tiff with layers boolean?

Post by 246246 »

246246 wrote: I noticed one minor limitation (even in MAC Byte Order). If you saved empty layer in Photoshop - one layer has some image and another is really blank, it still exists in Photoshop when reopened. But ImageMagick ignore it, "%[tiff:has-layers]" does not return true. However it happens also true in psd, so I think it is limited feature. I believe it is usually harmless. But If you have to consider such tiff as "has-layers", you have to check binary (inside 37724 tag) somehow whether it contains 8BIMLayr (or MIB8ryaL). I hope you don't have such weird tiff. :D
Another odd one found at viewtopic.php?f=1&t=28259

This case "%[tiff:has-layers]" returns true but not seen layer in Photoshop.

Code: Select all

d:\tmp>identify -quiet Original.tif
Original.tif[0] TIFF 1200x1200 1200x1200+0+0 8-bit CMYK 6.542MB 0.016u 0:00.017
Original.tif[1] TIFF 1140x696 1140x696+30+252 8-bit CMYK 0.000u 0:00.006

d:\tmp>identify -quiet Original.tif[0]
Original.tif[0]=>Original.tif TIFF 1200x1200 1200x1200+0+0 8-bit CMYK 0.000u 0:00.000

d:\tmp>identify -quiet Original.tif[1]

d:\tmp>identify -quiet -format "%[tiff:has-layers]\n" Original.tif[0]
true
frame [1] seems to be 0 byte ...

Code: Select all

d:\tmp>identify -quiet -verbose Original.tif | find /i "Filesize"
  Filesize: 6.542MB
  Filesize: 0B
Post Reply