Re: reading photoshop layers
From: Mike D Sutton (EDais_at_mvps.org)
Date: 01/25/05
- Next message: Martin Enke: "Change resulution (DPI) of a device context"
- Next in thread: Warren Galyen: "Re: reading photoshop layers"
- Reply: Warren Galyen: "Re: reading photoshop layers"
- Messages sorted by: [ date ] [ thread ]
Date: Tue, 25 Jan 2005 17:49:01 -0000
> 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/
- Next message: Martin Enke: "Change resulution (DPI) of a device context"
- Next in thread: Warren Galyen: "Re: reading photoshop layers"
- Reply: Warren Galyen: "Re: reading photoshop layers"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|