Re: reading photoshop layers

From: Warren Galyen (wgalyen_at_modomail.com)
Date: 01/27/05


Date: Thu, 27 Jan 2005 12:01:59 -0800

Mike D Sutton wrote:
>>I've actually found a graphics library that supports PSD files with
>>layers at http://www.soft-gems.net/Graphics.php#GraphicEx. Unfortunately
>>its written in Delphi and I have no experience whatsoever with this
>>langauge.
>
>
> Delphi isn't too bad at all to work with, I use it on a regular basis at work and find it to be somewhere in the middle
> between C#, C++ and VB, although probably most so to C# (as you would expect having been headed up by the same guy
> (Anders Hejlsberg)), but even without knowing either you can probably read the majority of Delphi code and made a
> reasonable guess as to it's meaning.
>
> Are you sure this library supports individual layer extraction though? I had a quick look and couldn't see anything in
> the docs or in the source code itself that suggested it could decode individual layers, although the colourspace
> conversion code would be handy to pull out..
> As for parsing the format yourself, the structure is simple enough (split into 5 segments), each segment can be read
> individually (or skipped entirely) and most have a sub-tagging system that breaks the internal data down into individual
> records. Non-understood tags within that can be ignored since each is stored in the same way with an ID and size
> prefixing the data itself, so writing a parser for the format knowing nothing about the data within it is a reasonably
> trivial task, going into more detail where required.
> The layers section is the most complex as it contains many sub-layers of data to get down to individual attributes and
> image data itself, but even then a few hours with a hex editor and some version of the format spec. (I was working from
> a 3.0 spec. to start with) and you'll have a pretty good understanding of the format.
> Having not worked with the format (at least in code, I probably use Photoshop itself almost every day) for a good few
> years it literally took a day to go from nothing to a working class that could extract the composite image including
> PackBits decompression, parse the structure of the layers section and extract the data blocks for each layer image (it
> doesn't expose them yet, but that's simply because I ran out of time and had to get on with real work instead ;)
> Really though, not a complex format at all since you can pick and choose which areas to go into detail to and simply
> ignore the rest.
> Hope this helps,
>
> Mike
>
>
> P.s. Here's a few of the utility functions from my class which should solve some of the more tedious stuff including
> endian swapping integers, and PackBits decompression:
>
> '***
> Private Declare Function RtlFillMemory Lib "Kernel32.dll" ( _
> ByRef Destination As Any, ByVal Length As Long, ByVal Fill As Byte) As Long
> Private Declare Sub RtlMoveMemory Lib "Kernel32.dll" ( _
> ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
>
> ' DWord endian flip
> Private Function FlipDWord(ByVal inDWord As Long) As Long
> FlipDWord = _
> (((inDWord And &HFF000000) \ &H1000000) And &HFF&) Or _
> ((inDWord And &HFF0000) \ &H100&) Or _
> ((inDWord And &HFF00&) * &H100&) Or _
> ((inDWord And &H7F&) * &H1000000)
> If (inDWord And &H80&) Then FlipDWord = FlipDWord Or &H80000000
> End Function
>
> ' Word endian flip
> Private Function FlipWord(ByVal inWord As Integer) As Integer ' Endian swap on Word
> FlipWord = ((inWord And &H7F) * &H100) Or (((inWord And &HFF00) \ &H100) And &HFF)
> If (inWord And &H80) Then FlipWord = FlipWord Or &H8000
> End Function
>
> ' Signed to unsigned Word conversion
> Private Function SWordToUWord(ByVal inWord As Integer) As Long
> SWordToUWord = inWord And &H7FFF& ' Signed to unsigned Word
> If (inWord And &H8000) Then SWordToUWord = SWordToUWord Or &H8000&
> End Function
>
> ' PackBits decompression routine (No buffer overflow protection though..)
> Private Function UnpackBitsPtr(ByRef inRLE() As Byte, ByVal inRLESize As Long, _
> ByVal outRAWPtr As Long) As Boolean
> Dim RLEPos As Long, RunLength As Long
> Dim RAWPos As Long
>
> Do
> If (inRLE(RLEPos) = &H80) Then
> ' No-op, should never appear but ignore if it does
> ElseIf (inRLE(RLEPos) And &H80) Then
> RunLength = &H101 - inRLE(RLEPos) ' RLE run
> Call RtlFillMemory(ByVal (outRAWPtr + RAWPos), _
> RunLength, inRLE(RLEPos + 1))
> RLEPos = RLEPos + 2
> Else
> RunLength = inRLE(RLEPos) + 1 ' RAW run
> Call RtlMoveMemory(ByVal (outRAWPtr + RAWPos), _
> inRLE(RLEPos + 1), RunLength)
> RLEPos = RLEPos + RunLength + 1
> End If
>
> RAWPos = RAWPos + RunLength
> Loop While RLEPos < inRLESize
> End Function
> '***
>
>
> - Microsoft Visual Basic MVP -
> E-Mail: EDais@mvps.org
> WWW: http://EDais.mvps.org/
>
>

Thanks a lot Mike for the starting point!



Relevant Pages

  • Re: reading photoshop layers
    ... Delphi isn't too bad at all to work with, I use it on a regular basis at work and find it to be somewhere in the middle ... the docs or in the source code itself that suggested it could decode individual layers, ... As for parsing the format yourself, the structure is simple enough, each segment can be read ... Private Function FlipWordAs Integer ' Endian swap on Word ...
    (microsoft.public.vb.winapi.graphics)
  • Re: comp.lang.pascal.delphi.misc miniFAQ (full version)
    ... Why does the debugger show my For loop variable counting down, ... Does Delphi have an equivalent to the VB Split function? ... > the number of decimal places to display - Format and FormatFloat. ... Added a link to Henry Bartlett's Delphi newsgroups page. ...
    (alt.comp.lang.borland-delphi)
  • Re: comp.lang.pascal.delphi.misc miniFAQ (full version)
    ... Why does the debugger show my For loop variable counting down, ... Does Delphi have an equivalent to the VB Split function? ... > the number of decimal places to display - Format and FormatFloat. ... Added a link to Henry Bartlett's Delphi newsgroups page. ...
    (comp.lang.pascal.delphi.misc)
  • Re: Self Decrypting Archive Freeware?
    ... mike wrote: ... >> current compression program. ... All I care about is that I have some old hardware that ... common format you have assurance that the FORMAT will be ...
    (sci.crypt)
  • Re: calulate working hours and minutes between 2 dates and times
    ... the original answer from mike works with the last bit from Peo Sjoblom ... Format both as general ... Task are presented across the rows so for example arrival time column ...
    (microsoft.public.excel.misc)