WindowsIconReader.st
author claus
Wed, 13 Oct 1993 01:32:33 +0100
changeset 3 78aaa5408119
parent 0 3f9277473954
child 5 4d55b551dc57
permissions -rw-r--r--
*** empty log message ***

"
 COPYRIGHT (c) 1993 by Claus Gittinger
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

ImageReader subclass:#WindowsIconReader
         instanceVariableNames:''
         classVariableNames:''
         poolDictionaries:''
         category:'Graphics-Support'
!

WindowsIconReader comment:'

COPYRIGHT (c) 1993 by Claus Gittinger
              All Rights Reserved

this class provides methods for loading and saving Windows and OS2
icon files..

%W% %E%
written Jun 93 by claus
'!

!WindowsIconReader methodsFor:'reading from file'!

fromWindowsFile: aFilename 
    | fileSize header inDepth
      rawMap rMap gMap bMap srcIndex dstIndex
      data4 mask tmp bytesPerRow|

    inStream := FileStream readonlyFileNamed:aFilename.
    inStream isNil ifTrue:[
        'open error' printNewline. 
        ^ nil
    ].

    inStream binary.
    fileSize := inStream size.

    "read the header"

    header := ByteArray uninitializedNew:16r50.
    inStream nextBytes:16r50 into:header.
    width := header at:7.
    height := header at:8.
    inDepth := header at:16r25.

    "read the colormap"

    rawMap := ByteArray uninitializedNew:(16*3).
    inStream nextBytes:(16*3) into:rawMap.
    rMap := Array new:16.
    gMap := Array new:16.
    bMap := Array new:16.
    srcIndex := 1.
    1 to:16 do:[:i |
        rMap at:i put:(rawMap at:srcIndex).
        srcIndex := srcIndex + 1.
        gMap at:i put:(rawMap at:srcIndex).
        srcIndex := srcIndex + 1.
        bMap at:i put:(rawMap at:srcIndex).
        srcIndex := srcIndex + 1.
    ].

    inStream position:16r7F.

    "read the data bits"

    bytesPerRow := width * inDepth + 7 // 8.
    data4 := ByteArray uninitializedNew:(height * bytesPerRow).
    inStream nextBytes:(height * bytesPerRow) into:data4.

    "read mask"

"
    mask := ByteArray new:(width * height / 8).
    inStream nextBytes:(width * height / 8) into:mask.
"

    "stupid: last row first"

    tmp := ByteArray uninitializedNew:(height * bytesPerRow).
    srcIndex := 1.
    dstIndex := (height - 1) * bytesPerRow + 1.
    1 to:height do:[:row |
        tmp replaceFrom:dstIndex to:(dstIndex + bytesPerRow - 1)
                   with:data4 startingAt:srcIndex.
        srcIndex := srcIndex + bytesPerRow.
        dstIndex := dstIndex - bytesPerRow.
    ].
    data4 := tmp.

    "expand into bytes"

    data := ByteArray new:(width * height).
    data4 expandPixels:inDepth width:width height:height
                  into:data mapping:nil.

    photometric := #palette.
    samplesPerPixel := 1.
    bitsPerSample := #(8).
    colorMap := Array with:rMap with:gMap with:bMap.
    inStream close.

    "
     |i f|
     i := Image fromFile:'/LocalLibrary/Images/WIN_icons/ibm.ico'.
     f := i asFormOn:Display.
     v drawOpaqueForm:(f ) x:5 y:5.
     v drawOpaqueForm:(f magnifyBy:2@2) x:45 y:5
    "
!

fromOS2File: aFilename 
    | fileSize header inDepth
      rawMap rMap gMap bMap srcIndex dstIndex
      data4 mask tmp bytesPerRow nColors nByte|

    inStream := FileStream readonlyFileNamed:aFilename.
    inStream isNil ifTrue:[
        'open error' printNewline. 
        ^ nil
    ].

    inStream binary.
    fileSize := inStream size.

    "read the header"

    header := ByteArray uninitializedNew:8r110.
    inStream nextBytes:16 into:header.
    (header startsWith:#(73 67)) ifTrue:[
        "IC format"
        inStream nextBytes:10 into:header startingAt:17.
        width := header at:7.
        height := header at:9.
        inDepth := 2 "header at:11". "where is it"
    ] ifFalse:[
        inStream nextBytes:(8r110-16) into:header startingAt:17.
        width := header at:8r101.
        height := header at:8r103.
        inDepth := header at:8r107.
    ].

    "read the colormap"

    nColors := 1 bitShift:inDepth.

    rawMap := ByteArray uninitializedNew:(nColors*3).
    inStream nextBytes:(nColors*3) into:rawMap.
    rMap := Array new:nColors.
    gMap := Array new:nColors.
    bMap := Array new:nColors.
    srcIndex := 1.
    1 to:nColors do:[:i |
        bMap at:i put:(rawMap at:srcIndex).
        srcIndex := srcIndex + 1.
        gMap at:i put:(rawMap at:srcIndex).
        srcIndex := srcIndex + 1.
        rMap at:i put:(rawMap at:srcIndex).
        srcIndex := srcIndex + 1.
    ].

    "read mask"

    nByte := width * height + 7 // 8.
    mask := ByteArray uninitializedNew:nByte.
    inStream nextBytes:nByte into:mask.

    "what is this"

    inStream nextBytes:nByte into:mask.

    "read the data bits"

    bytesPerRow := width * inDepth + 7 // 8.
    data4 := ByteArray uninitializedNew:(height * bytesPerRow).
    inStream nextBytes:(height * bytesPerRow) into:data4.

    "stupid: last row first"

    tmp := ByteArray new:(height * bytesPerRow).
    srcIndex := 1.
    dstIndex := (height - 1) * bytesPerRow + 1.
    1 to:height do:[:row |
        tmp replaceFrom:dstIndex to:(dstIndex + bytesPerRow - 1)
                   with:data4 startingAt:srcIndex.
        srcIndex := srcIndex + bytesPerRow.
        dstIndex := dstIndex - bytesPerRow.
    ].
    data4 := tmp.

    "expand into bytes"

    data := ByteArray new:(width * height).
    data4 expandPixels:inDepth width:width height:height
                  into:data mapping:nil.

    photometric := #palette.
    samplesPerPixel := 1.
    bitsPerSample := #(8).
    colorMap := Array with:rMap with:gMap with:bMap.
    inStream close.

    "
     |i f|
     i := Image fromFile:'/LocalLibrary/Images/OS2/dos3.ico'.
     f := i asFormOn:Display.
     v drawOpaqueForm:(f magnifyBy:2@2) x:5 y:5
    "
!

fromWindowsBMPFile: aFilename 
    | fileSize header inDepth
      rawMap rMap gMap bMap srcIndex dstIndex
      data4 mask tmp bytesPerRow|

    inStream := FileStream readonlyFileNamed:aFilename.
    inStream isNil ifTrue:[
        'open error' printNewline. 
        ^ nil
    ].

    inStream binary.
    fileSize := inStream size.

    "read the header"

    header := ByteArray uninitializedNew:16r50.
    inStream nextBytes:16r50 into:header.
    ((header at:15) == 40) ifTrue:[
        width := (header at:19) + ((header at:20) * 256).
        height := (header at:23) + ((header at:24) * 256).
        inDepth := header at:29.
    ].
    ((header at:15) == 12) ifTrue:[
        width := (header at:19) + ((header at:20) * 256).
        height := (header at:21) + ((header at:22) * 256).
        inDepth := header at:25.
    ].

    width isNil ifTrue:[
        ^ nil
    ].

    "read the colormap"

    rawMap := ByteArray uninitializedNew:(16*3).
    inStream nextBytes:(16*3) into:rawMap.
    rMap := Array new:16.
    gMap := Array new:16.
    bMap := Array new:16.
    srcIndex := 1.
    1 to:16 do:[:i |
        rMap at:i put:(rawMap at:srcIndex).
        srcIndex := srcIndex + 1.
        gMap at:i put:(rawMap at:srcIndex).
        srcIndex := srcIndex + 1.
        bMap at:i put:(rawMap at:srcIndex).
        srcIndex := srcIndex + 1.
    ].

    inStream position:16r78.

    "read the data bits"

    bytesPerRow := width * inDepth + 7 // 8.
    data4 := ByteArray uninitializedNew:(height * bytesPerRow).
    inStream nextBytes:(height * bytesPerRow) into:data4.

    "read mask"

"
    mask := ByteArray new:(width * height / 8).
    inStream nextBytes:(width * height / 8) into:mask.
"

    "stupid: last row first"

    tmp := ByteArray uninitializedNew:(height * bytesPerRow).
    srcIndex := 1.
    dstIndex := (height - 1) * bytesPerRow + 1.
    1 to:height do:[:row |
        tmp replaceFrom:dstIndex to:(dstIndex + bytesPerRow - 1)
                   with:data4 startingAt:srcIndex.
        srcIndex := srcIndex + bytesPerRow.
        dstIndex := dstIndex - bytesPerRow.
    ].
    data4 := tmp.

    "expand into bytes"

    data := ByteArray new:(width * height).
    data4 expandPixels:inDepth width:width height:height
                  into:data mapping:nil.

    photometric := #palette.
    samplesPerPixel := 1.
    bitsPerSample := #(8).
    colorMap := Array with:rMap with:gMap with:bMap.
    inStream close.

!

fromFile: aFilename 
    | fileSize header |

    inStream := FileStream readonlyFileNamed:aFilename.
    inStream isNil ifTrue:[
        'open error' printNewline. 
        ^ nil
    ].

    inStream binary.
    fileSize := inStream size.

    fileSize < 16 ifTrue:[
        inStream close.
        self error:'short file'.
        ^ nil
    ].

    header := ByteArray uninitializedNew:16.
    inStream nextBytes:16 into:header.
    (header startsWith:#(66 77)) ifTrue:[     "BM"
        inStream close.
        ^ self fromWindowsBMPFile:aFilename
    ].
    (header startsWith:#(66 65)) ifTrue:[     "BA"
        inStream close.
        ^ self fromOS2File:aFilename
    ].
    (header startsWith:#(73 67)) ifTrue:[     "IC"
        inStream close.
        ^ self fromOS2File:aFilename
    ].
    (header startsWith:#(0 0 1 0 1 0)) ifTrue:[
        inStream close.
        ^ self fromWindowsFile:aFilename
    ].
    self error:'format not supported'.
    inStream close.
    ^ nil

    "Image fromFile:'/LocalLibrary/Images/OS2_icons/dos.ico'"
! !