Results 1 to 6 of 6

Thread: Simple PSD File Generator

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Simple PSD File Generator

    I finally figured out how to do this. It generates a native Photoshop PSD file, 3 channels, 8bits per pixel, 256x256 size image. I set all the header stuff as constants basically (though I didn't use the Const statement, I used Dim, and then set them with var = val type lines farther down, so I could later make routines to set the values at runtime). I set them as constants for now because Photoshop (having originated as Mac software) uses Big Endian number in its main file format. And unlike TIFF where you can set II for Intel format (little endian) or MM for Mac format (big endian), Photoshops files are REQUIRE the multibyte values to be big endian, and conversion routines are not trivial. So I opted (for now) to just create a test image generator program with fixed values for all the multibyte values (which is ALL of the entries in the header, so I have fixed width, fixed height, fixed bitdepth, etc). That's why it's more of a fixed size test image generator than a true graphics software or image converter. Though later I plan to expand this to use the CopyMemory API to create a Little to Big Endian converter so I can change these values at runtime.

    This is my program's current code.
    Code:
    Private Sub Form_Load()
    Dim Pix(255, 255, 2) As Byte
    
    For y = 0 To 255
    For x = 0 To 255
    Pix(x, y, 0) = (x * 4) And 255
    Pix(x, y, 1) = (y * 4) And 255
    Pix(x, y, 2) = (x \ 64) * 17 + (y \ 64) * 68
    Next x
    Next y
    
    
    Dim Sig As String
    Dim Ver As Integer
    Dim Reserved(5) As Byte
    Dim Chan As Integer
    Dim PHeight As Long
    Dim PWidth As Long
    Dim Depth As Integer
    Dim PMode As Integer
    Dim NullLen As Long
    Dim CompMethod As Integer
    
    Sig = "8BPS"
    Ver = &H100
    Chan = &H300
    PHeight = &H10000
    PWidth = &H10000
    Depth = &H800
    PMode = &H300
    Open "c:\temp\test.psd" For Binary As #1
    Put #1, 1, Sig
    Put #1, , Ver
    Put #1, , Reserved()
    Put #1, , Chan
    Put #1, , PHeight
    Put #1, , PWidth
    Put #1, , Depth
    Put #1, , PMode
    Put #1, , NullLen
    Put #1, , NullLen
    Put #1, , NullLen
    Put #1, , CompMethod
    Put #1, , Pix()
    Close #1
    
    End
    End Sub

  2. #2
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Simple PSD File Generator

    Those variables may be grouped in a UDT.

    Code:
    Private Type PSD_Format
        Sig         As String * 4
        Ver         As Integer
        Reserved(5) As Byte
        Chan        As Integer
        PHeight     As Long
        PWidth      As Long
        Depth       As Integer
        PMode       As Integer
        NullLen(2)  As Long
        CompMethod  As Integer
    End Type
    
    Private Sub Form_Load()
        Dim Pix(255, 255, 2) As Byte, x As Integer, y As Integer, PSD As PSD_Format
    
        With PSD
            .Sig = "8BPS"
            .Ver = &H100
            .Chan = &H300
            .PHeight = &H10000
            .PWidth = &H10000
            .Depth = &H800
            .PMode = &H300
        End With
    
        For y = 0 To 255
            For x = 0 To 255
                Pix(x, y, 0) = (x * 4) And 255
                Pix(x, y, 1) = (y * 4) And 255
                Pix(x, y, 2) = (x \ 64) * 17 + (y \ 64) * 68
            Next x
        Next y
    
        Open "C:\Temp\Test.psd" For Binary As #1
            Put #1, 1&, PSD
            Put #1, , Pix()
        Close #1
    
        End
    End Sub
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  3. #3

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Simple PSD File Generator

    Actually those variables are all part of different structures. For example, NullLen is used 3 times because there are 3 optional structures, who's only mandatory part is the length field. To indicate you won't use the structure, the length must be 0. So NullLen is actually not part of the header, but rather is used 3 times to specify that those 3 optional structures are not present in the file. The actual PSD file header ends after PMode. And CompMethod is Compression Method, which is the one field in the single-field header for the image data structure (which of course is followed by the actual image data), and tells how the image data is compressed (or even if it is not compressed), where 0 is uncompressed, 1 is RLE compressed, 2 is ZIP compressed (normal ZIP), and 3 is ZIP compressed (with a predictive algorithm).

    So putting all those data field into one header User Defined Type is technically not correct (even though it would work).

  4. #4

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Simple PSD File Generator

    And I just now finished writing the two needed endian conversion functions, which utilize the CopyMemory API call. Below is the code needed for this.

    Code:
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
    
    Private Function ConvEndInt(ByVal Value As Integer) As Integer
    Dim tempval As Integer
    CopyMemory VarPtr(tempval), VarPtr(Value) + 1, 1
    CopyMemory VarPtr(tempval) + 1, VarPtr(Value), 1
    ConvEndInt = tempval
    End Function
    
    Private Function ConvEndLong(ByVal Value As Long) As Long
    Dim tempval As Long
    CopyMemory VarPtr(tempval), VarPtr(Value) + 3, 1
    CopyMemory VarPtr(tempval) + 1, VarPtr(Value) + 2, 1
    CopyMemory VarPtr(tempval) + 2, VarPtr(Value) + 1, 1
    CopyMemory VarPtr(tempval) + 3, VarPtr(Value), 1
    ConvEndLong = tempval
    End Function

  5. #5

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Simple PSD File Generator

    And now I've finished my more complete implementation of the program. It converts Little-Endian numbers to the required Bit-Endian numbers at runtime. This particular sample program generates a 640x480 color test pattern, and saves it as a PSD file.

    Code:
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
    
    Private Type PSD_Format
     Sig As String * 4
     Ver As Integer
     Reserved(5) As Byte
     ChanCount As Integer
     ImageHeight As Long
     ImageWidth As Long
     BitDepth As Integer
     ColorMode As Integer
    End Type
    
    Private Enum CMode
     Bitmap = 0
     IndexedColor = 1
     Grayscale = 2
     RGB = 3
     CMYK = 4
     Multichannel = 7
     Duotone = 8
     Lab = 9
    End Enum
    
    Private Function ConvEndInt(ByVal Value As Integer) As Integer
    Dim tempval As Integer
    CopyMemory VarPtr(tempval), VarPtr(Value) + 1, 1
    CopyMemory VarPtr(tempval) + 1, VarPtr(Value), 1
    ConvEndInt = tempval
    End Function
    
    Private Function ConvEndLong(ByVal Value As Long) As Long
    Dim tempval As Long
    CopyMemory VarPtr(tempval), VarPtr(Value) + 3, 1
    CopyMemory VarPtr(tempval) + 1, VarPtr(Value) + 2, 1
    CopyMemory VarPtr(tempval) + 2, VarPtr(Value) + 1, 1
    CopyMemory VarPtr(tempval) + 3, VarPtr(Value), 1
    ConvEndLong = tempval
    End Function
    
    Private Sub FillHeader(ByRef PSD_Header As PSD_Format, ByVal NumberOfChannels As Integer, ByVal ImgWidth As Long, ByVal ImgHeight As Long, ByVal ChannelBitDepth As Integer, ByVal ColorMode As CMode)
    With PSD_Header
    .Sig = "8BPS"
    .Ver = &H100
    .ChanCount = ConvEndInt(NumberOfChannels)
    .ImageHeight = ConvEndLong(ImgHeight)
    .ImageWidth = ConvEndLong(ImgWidth)
    .BitDepth = ConvEndInt(ChannelBitDepth)
    .ColorMode = ConvEndInt(ColorMode)
    End With
    End Sub
    
    Private Sub Form_Load()
    Dim PSD As PSD_Format
    Dim Pix() As Byte
    ReDim Pix(640 - 1, 480 - 1, 2)
    FillHeader PSD, 3, 640, 480, 8, RGB
    
    For y = 0 To 480 - 1
    For x = 0 To 640 - 1
    Pix(x, y, 0) = (x Mod 40) * (255 / 39)
    Pix(x, y, 1) = (x \ 40) * (255 / 15)
    Pix(x, y, 2) = y / (480 - 1) * 255
    Next x
    Next y
    
    Open "c:\temp\test.psd" For Binary As #1
    Put #1, 1, PSD
    Put #1, , 0&
    Put #1, , 0&
    Put #1, , 0&
    Put #1, , 0
    Put #1, , Pix()
    Close #1
    End
    End Sub

  6. #6

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Simple PSD File Generator

    And yes the official PSD specification if VERY EXTENSIVE! It can save just about any type of data that can be in an image in Photoshop (layers, masks, alpha channels, thumbnails, slices, text boxes, etc). Basically it seems designed to save the entire internal state of a given image processing session for a given image. But once you figure out the minimum requirements to just save a basic image without all the fancy features, in this form it has fewer header fields than a standard Windows BMP file! Only downside is that it uses Big-Endian format, so any datafield that is a 2byte or 4byte integer has to be converted to Big-Endian prior to saving in the file. Also unike most image formats, it stores the color data in planar order (rather than interleaved order), so ALL of the red channel data goes first, then ALL the green channel data, then ALL the blue channel data. This though is very simple to fix in just changing how you Dim (or Redim) your pixel array in VB6.

    In case you would like to know what the format is like, and see just how extensive the full specs are, read the attached PDF file. I got it from Adobe's webpage with their official specs http://www.adobe.com/devnet-apps/pho...50577409_72092
    and then saving it and taking out the unneeded HTML code (parts for specs on tiff files, the page's table of contents, etc), and then saving the resulting web page to a PDF file (so when I posted it here I didn't need to upload a whole zip file with the CSS and JS files etc, as the PDF file contains all the webpage's needed formatting in one file).
    Attached Images Attached Images

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width