TargaReader.st
changeset 1738 9c85e9d8326b
parent 1577 a8851bce16c5
child 1745 4fa0fad2a463
--- a/TargaReader.st	Fri Apr 04 19:07:54 2003 +0200
+++ b/TargaReader.st	Fri Apr 04 19:18:18 2003 +0200
@@ -13,7 +13,7 @@
 "{ Package: 'stx:libview2' }"
 
 ImageReader subclass:#TargaReader
-	instanceVariableNames:'orientation'
+	instanceVariableNames:'orientation bytesPerRow bytesPerPixel'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Graphics-Images-Support'
@@ -55,6 +55,44 @@
         ST80FormReader SunRasterReader TIFFReader WindowsIconReader 
         XBMReader XPMReader XWDReader
 "
+!
+
+format
+"
+    Shorts etc. are lsb.
+
+    offset:
+
+        1       lenID           byte
+        2       hasColorMap     byte
+        3       imageType       byte
+                         1   MapRGB  
+                         2   RawRGB   
+                         3   RawMono   
+                         9   MapEnCode 
+                         10  RawEnCode 
+        4, 5    cmapOffset      short
+        6, 7    cmapLength      short
+        8       cmapEntrySize   short
+        9,10    xOrg            short
+        11,12   yOrg            short
+
+        13,14   width 
+        15,16   height 
+        17      depth 
+        18      flags
+                        0000 xxxx  attribute-bits-per-pixel
+                        0000 0001  greysc
+                        0000 0010  colour
+                        0000 0011  mapped
+                        0000 0100  rleEncoded
+                        0000 1000  interlaced
+                        00xx 0000  origin (0 -> lower-left / 1 -> l-r / 2 -> u-l / 3 -> u-r)
+                        xx00 0000  interleave (0 -> none / 1 -> odd/even / 2 ->4-fould / 3 reserved)
+
+        19..    len             lenID-bytes
+        ..      colorMap        cmapLength*3 bytes iff hasColorMap ~~ 0
+"
 ! !
 
 !TargaReader class methodsFor:'initialization'!
@@ -123,228 +161,65 @@
 
 !TargaReader methodsFor:'reading from file'!
 
-fromStream:aStream
-    "read a targa-image from aFileName. return the receiver (with all
-     relevant instance variables set for the image) or nil on error"
-
-    |depth flags lenID hasColorMap imageType 
-     cmapOffset cmapLength cmapEntrySize xOrg yOrg
-     t bytesPerPixel bytesPerRow rowIdx startIdx endIdx rle|
-
-    inStream := aStream.
-    aStream binary.
-
-    lenID := aStream next.
-    hasColorMap := aStream next.
-    imageType := aStream next.
-    cmapOffset := aStream nextShortMSB:false.
-    cmapLength := aStream nextShortMSB:false.
-    cmapEntrySize := aStream next.
-    xOrg := aStream nextShortMSB:false.
-    yOrg := aStream nextShortMSB:false.
-
-    width := aStream nextShortMSB:false.
-    height := aStream nextShortMSB:false.
-    depth := aStream next.
-    (#(8 "16" 24 32) includes:depth) ifFalse:[
-        ^ self fileFormatError:('unsupported depth: ', depth printString).
-    ].
-    depth == 32 ifTrue:[
-        'TargaReader [info]: alpha channel ignored' infoPrintCR.
-    ] ifFalse:[
-        'TargaReader [info]: depth: ' infoPrint. depth infoPrintCR.
-    ].
-
-    "/ MapRGB == 1
-    "/ RawRGB == 2
-    "/ RawMono == 3
-    "/ MapEnCode == 9
-    "/ RawEnCode == 10
+handleImageOrientation
+    |rowIdx startIdx endIdx t|
 
-    (#(1 2 9 10) includes:imageType) ifFalse:[
-        "/ 'TargaReader [warning]: unsupported imageType: ' errorPrint. imageType errorPrintCR.
-        ^ self fileFormatError:('unsupported imageType: ', imageType printString).
-    ].
-    'TargaReader [info]: imageType: ' infoPrint. imageType infoPrintCR.
-
-    "/ flags:
-    "/    0000 xxxx  attribute-bits-per-pixel
-    "/    0000 0001  greysc
-    "/    0000 0010  colour
-    "/    0000 0011  mapped
-    "/    0000 0100  rleEncoded
-    "/    0000 1000  interlaced
-    "/    00xx 0000  origin (0 -> lower-left / 1 -> l-r / 2 -> u-l / 3 -> u-r)
-    "/    xx00 0000  interleave (0 -> none / 1 -> odd/even / 2 ->4-fould / 3 reserved)
-    "/
-    flags := aStream next.
-
-    (flags bitAnd:2r11000000) ~~ 0 ifTrue:[
-        ^ self fileFormatError:('unsupported interlace: ' , flags printString).
-    ].
-
-    rle := flags bitTest:2r000001000.
-    flags := flags bitAnd:2r111110111.
-
-    (flags bitAnd:2r00001111) ~~ 0 ifTrue:[
-        ^ self fileFormatError:('unsupported flags: ' , flags printString).
-    ].
-
-    (flags bitAnd:2r00110000) == 16r20 ifTrue:[
-        orientation := #topLeft
-    ] ifFalse:[
-        (flags bitAnd:2r00110000) == 16r30 ifTrue:[
-            orientation := #topRight
-        ] ifFalse:[
-            (flags bitAnd:2r00110000) == 16r10 ifTrue:[
-                orientation := #bottomRight
-            ] ifFalse:[
-                (flags bitAnd:2r00110000) == 0 ifTrue:[
-                    orientation := #bottomLeft
-                ]
-            ]
-        ]
-    ].
-
-    lenID ~~ 0 ifTrue:[
-        aStream skip:lenID
+    orientation == #topLeft ifTrue:[
+        ^ self.
     ].
 
-    hasColorMap ~~ 0 ifTrue:[
-        "/ read the colorMap
-        colorMap := Array new:cmapLength.
-        1 to:cmapLength do:[:index |
-            |r g b|
-
-            b := aStream nextByte.
-            g := aStream nextByte.
-            r := aStream nextByte.
-            (r isNil or:[g isNil or:[b isNil]]) ifTrue:[
-                ^ self fileFormatError:('short file - probably not targa format').
+    orientation == #topRight ifTrue:[
+        "/ flip horizontal
+        rowIdx := 1.
+        1 to:height do:[:row |
+            startIdx := rowIdx.
+            endIdx := rowIdx + bytesPerRow - bytesPerPixel.
+            1 to:width//2 do:[:x |
+                0 to:bytesPerPixel-1 do:[:c |
+                    t := data at:startIdx+c.
+                    data at:startIdx+c put:(data at:endIdx+c).
+                    data at:endIdx+c put:t.
+                ].
+                startIdx := startIdx + bytesPerPixel.
+                endIdx := endIdx - bytesPerPixel.
             ].
-            colorMap at:index put:(Color redByte:r greenByte:g blueByte:b).
+            rowIdx := rowIdx + width.
         ].
-        'TargaReader [info]: has colorMap' infoPrintCR.
+        ^ self.
     ].
 
-    depth == 32 ifTrue:[
-        imageType == 2 ifTrue:[
-"/            rle ifTrue:[self halt].
-            self read32.
-        ] ifFalse:[
-"/            rle ifFalse:[self halt].
-            self read32RLE.
+    orientation == #bottomLeft ifTrue:[
+        "/ flip vertical
+        startIdx := 1.
+        endIdx := 1 + ((height - 1) * bytesPerRow).
+        t := ByteArray new:bytesPerRow.
+        1 to:height//2 do:[:row |
+            t replaceFrom:1 to:bytesPerRow with:data startingAt:startIdx.
+            data replaceFrom:startIdx to:startIdx+bytesPerRow-1 with:data startingAt:endIdx.
+            data replaceFrom:endIdx to:endIdx+bytesPerRow-1 with:t startingAt:1.
+            startIdx := startIdx + bytesPerRow.
+            endIdx := endIdx - bytesPerRow
         ].
-        bytesPerRow := width*3.
-        bytesPerPixel := 3.
-    ].
-    depth == 24 ifTrue:[
-        imageType == 2 ifTrue:[
-"/            rle ifTrue:[self halt].
-            self read24.
-        ] ifFalse:[
-"/            rle ifFalse:[self halt].
-            self read24RLE.
-        ].
-        bytesPerRow := width*3.
-        bytesPerPixel := 3.
-    ].
-    depth == 8 ifTrue:[
-        imageType == 1 ifTrue:[
-"/            rle ifTrue:[self halt].
-            self read8.
-        ] ifFalse:[
-"/            rle ifFalse:[self halt].
-            self read8RLE
-        ].
-        bytesPerRow := width.
-        bytesPerPixel := 1.
+        ^ self.
     ].
 
-    orientation == #topLeft ifTrue:[
-    ] ifFalse:[
-        orientation == #topRight ifTrue:[
-            "/ flip horizontal
-            rowIdx := 1.
-            1 to:height do:[:row |
-                startIdx := rowIdx.
-                endIdx := rowIdx + bytesPerRow - bytesPerPixel.
-                1 to:width//2 do:[:x |
-                    0 to:bytesPerPixel-1 do:[:c |
-                        t := data at:startIdx+c.
-                        data at:startIdx+c put:(data at:endIdx+c).
-                        data at:endIdx+c put:t.
-                    ].
-                    startIdx := startIdx + bytesPerPixel.
-                    endIdx := endIdx - bytesPerPixel.
-                ].
-                rowIdx := rowIdx + width.
-            ].
-        ] ifFalse:[
-            orientation == #bottomLeft ifTrue:[
-                "/ flip vertical
-                startIdx := 1.
-                endIdx := 1 + ((height - 1) * bytesPerRow).
-                t := ByteArray new:bytesPerRow.
-                1 to:height//2 do:[:row |
-                    t replaceFrom:1 to:bytesPerRow with:data startingAt:startIdx.
-                    data replaceFrom:startIdx to:startIdx+bytesPerRow-1 with:data startingAt:endIdx.
-                    data replaceFrom:endIdx to:endIdx+bytesPerRow-1 with:t startingAt:1.
-                    startIdx := startIdx + bytesPerRow.
-                    endIdx := endIdx - bytesPerRow
-                ].
-            ] ifFalse:[
-                'TargaReader [warning]: unsupported orientation: ' errorPrint. orientation errorPrintCR.
-            ]
-        ]
-    ].
-    ^ self
-
-    "
-     TargaReader fromFile:'bitmaps/test.tga' 
-    "
-
-    "Modified: / 7.9.1998 / 21:12:12 / cg"
-    "Modified: / 13.10.1998 / 19:50:48 / ps"
+    'TargaReader [warning]: unsupported orientation: ' errorPrint. orientation errorPrintCR.
 !
 
 read24
     "read a 24 bit/pixel targa-image"
 
-    |nBytes ok dSize t|
+    |totalBytes|
 
-    data := ByteArray new:(width * height * 3).
-    inStream nextBytes:(dSize := data size) into:data.
+    totalBytes := width * height * 3.
+    data := ByteArray new:totalBytes.
+    inStream nextBytes:totalBytes into:data.
 
     "
      mhmh - pixel-byte order is blue-green-red
      swap blue & red bytes
     "
-    nBytes := data size.
-    ok := false.
-
-%{  /* OPTIONAL */
-    if (__isByteArray(_INST(data))) {
-        int __lastIndex = __intVal(nBytes) - 2;
-        unsigned char *__cp = __ByteArrayInstPtr(_INST(data))->ba_element;
-        int __i;
-        unsigned char __t;
-
-        for (__i=0; __i<__lastIndex; __i+=3, __cp+=3) {
-            __t = __cp[0];
-            __cp[0] = __cp[2];
-            __cp[2] = __t;
-        }
-        ok = true;
-    }
-%}.
-    ok ifFalse:[
-        1 to:(dSize - 2) by:3 do:[:i |
-            t := data at:i.
-            data at:i put:(data at:i+2).
-            data at:i+2 put:t
-        ]
-    ].
+    self class swap:totalBytes bytesFromRGB_to_BGR_in:data.
 
     photometric := #rgb.
     samplesPerPixel := 3.
@@ -397,30 +272,34 @@
 read32
     "read a 32 bit/pixel targa-image; skip alpha channel (for now)"
 
-    |total dstIndex a r g b|
+    |totalBytes remainingBytes dstIndex a r g b|
 
-    data := ByteArray new:((total := width * height * 3)).
+    totalBytes := width * height * 3.
+    data := ByteArray new:totalBytes.
 
     dstIndex := 1.
-    [total > 0] whileTrue:[
-        inStream nextByte.
-        a := inStream nextByte.
+    remainingBytes := totalBytes.
+    [remainingBytes > 0] whileTrue:[
         b := inStream nextByte.
         g := inStream nextByte.
         r := inStream nextByte.
-        data at:dstIndex put:r.
+        a := inStream nextByte.   "/ alpha - skipped
+        data at:dstIndex   put:r.
         data at:dstIndex+1 put:g.
         data at:dstIndex+2 put:b.
         dstIndex := dstIndex + 3.
-        total := total - 3.
+        remainingBytes := remainingBytes - 3.
     ].
 
     photometric := #rgb.
     samplesPerPixel := 3.
     bitsPerSample := #(8 8 8).
 
-    "Modified: 21.4.1997 / 20:21:12 / cg"
-    "Created: 21.4.1997 / 20:45:35 / cg"
+    "
+     TargaReader fromFile:'/phys/exept//unsaved1/pd_stuff/graphic/3d_engines/crystal_space/CS/plugins/video/canvas/sdl/img/move.tga'
+     TargaReader fromFile:'/phys/exept/unsaved2/smalltalk/Squeak/croquet/Croquet/Content/Cisco/2520/Textures/2520caseback.tga'
+     TargaReader fromFile:'/phys/exept/unsaved2/smalltalk/Squeak/croquet/Croquet/Content/Cisco/2520/Textures/2520dimm1front.tga'
+    "
 !
 
 read32RLE
@@ -435,10 +314,10 @@
         code := inStream nextByte.
         n := (code bitAnd:16r7F) + 1.
         (code bitAnd:16r80) ~~ 0 ifTrue:[
-            a := inStream nextByte.
             b := inStream nextByte.
             g := inStream nextByte.
             r := inStream nextByte.
+            a := inStream nextByte.             "/ alpha - skipped
             n timesRepeat:[
                 data at:dstIndex put:r.
                 data at:dstIndex+1 put:g.
@@ -447,10 +326,10 @@
             ].
         ] ifFalse:[
             n timesRepeat:[
-                a := inStream nextByte.
                 b := inStream nextByte.
                 g := inStream nextByte.
                 r := inStream nextByte.
+                a := inStream nextByte.         "/ alpha - skipped
                 data at:dstIndex put:r.
                 data at:dstIndex+1 put:g.
                 data at:dstIndex+2 put:b.
@@ -513,11 +392,163 @@
 
     "Created: 21.4.1997 / 20:19:46 / cg"
     "Modified: 21.4.1997 / 20:21:12 / cg"
+!
+
+readColorMap:cmapLength
+    colorMap := Array new:cmapLength.
+    1 to:cmapLength do:[:index |
+        |r g b|
+
+        b := inStream nextByte.
+        g := inStream nextByte.
+        r := inStream nextByte.
+        (r isNil or:[g isNil or:[b isNil]]) ifTrue:[
+            ^ self fileFormatError:('short file - probably not targa format').
+        ].
+        colorMap at:index put:(Color redByte:r greenByte:g blueByte:b).
+    ].
+    ^ colorMap
+!
+
+readImage
+    "read a targa-image from aFileName. return the receiver (with all
+     relevant instance variables set for the image) or nil on error"
+
+    |depth flags lenID hasColorMap imageType 
+     cmapOffset cmapLength cmapEntrySize xOrg yOrg rle|
+
+    inStream binary.
+
+    lenID := inStream next.
+    hasColorMap := inStream next.
+    imageType := inStream next.
+    cmapOffset := inStream nextShortMSB:false.
+    cmapLength := inStream nextShortMSB:false.
+    cmapEntrySize := inStream next.
+    xOrg := inStream nextShortMSB:false.
+    yOrg := inStream nextShortMSB:false.
+
+    width := inStream nextShortMSB:false.
+    height := inStream nextShortMSB:false.
+    depth := inStream next.
+    (#(8 "16" 24 32) includes:depth) ifFalse:[
+        ^ self fileFormatError:('unsupported depth: ', depth printString).
+    ].
+    depth == 32 ifTrue:[
+        'TargaReader [info]: alpha channel ignored' infoPrintCR.
+    ] ifFalse:[
+        'TargaReader [info]: depth: ' infoPrint. depth infoPrintCR.
+    ].
+
+    "/ MapRGB == 1
+    "/ RawRGB == 2
+    "/ RawMono == 3
+    "/ MapEnCode == 9
+    "/ RawEnCode == 10
+
+    (#(1 2 9 10) includes:imageType) ifFalse:[
+        "/ 'TargaReader [warning]: unsupported imageType: ' errorPrint. imageType errorPrintCR.
+        ^ self fileFormatError:('unsupported imageType: ', imageType printString).
+    ].
+    'TargaReader [info]: imageType: ' infoPrint. imageType infoPrintCR.
+
+    "/ flags:
+    "/    0000 xxxx  attribute-bits-per-pixel
+    "/    0000 0001  greysc
+    "/    0000 0010  colour
+    "/    0000 0011  mapped
+    "/    0000 0100  rleEncoded
+    "/    0000 1000  interlaced
+    "/    00xx 0000  origin (0 -> lower-left / 1 -> l-r / 2 -> u-l / 3 -> u-r)
+    "/    xx00 0000  interleave (0 -> none / 1 -> odd/even / 2 ->4-fould / 3 reserved)
+    "/
+    flags := inStream next.
+
+    (flags bitAnd:2r11000000) ~~ 0 ifTrue:[
+        ^ self fileFormatError:('unsupported interlace: ' , flags printString).
+    ].
+
+    rle := flags bitTest:2r000001000.
+    flags := flags bitAnd:2r111110111.
+
+    (flags bitAnd:2r00001111) ~~ 0 ifTrue:[
+        ^ self fileFormatError:('unsupported flags: ' , flags printString).
+    ].
+
+    (flags bitAnd:2r00110000) == 16r20 ifTrue:[
+        orientation := #topLeft
+    ] ifFalse:[
+        (flags bitAnd:2r00110000) == 16r30 ifTrue:[
+            orientation := #topRight
+        ] ifFalse:[
+            (flags bitAnd:2r00110000) == 16r10 ifTrue:[
+                orientation := #bottomRight
+            ] ifFalse:[
+                (flags bitAnd:2r00110000) == 0 ifTrue:[
+                    orientation := #bottomLeft
+                ]
+            ]
+        ]
+    ].
+
+    lenID ~~ 0 ifTrue:[
+        inStream skip:lenID
+    ].
+
+    hasColorMap ~~ 0 ifTrue:[
+        "/ read the colorMap
+        colorMap := self readColorMap:cmapLength.
+        'TargaReader [info]: has colorMap' infoPrintCR.
+    ].
+
+    depth == 32 ifTrue:[
+        imageType == 2 ifTrue:[
+"/            rle ifTrue:[self halt:'oops - should not happen'].
+            self read32.
+        ] ifFalse:[
+"/            rle ifFalse:[self halt:'oops - should not happen'].
+            self read32RLE.
+        ].
+        bytesPerRow := width*3.
+        bytesPerPixel := 3.
+    ].
+    depth == 24 ifTrue:[
+        imageType == 2 ifTrue:[
+"/            rle ifTrue:[self halt:'oops - should not happen'].
+            self read24.
+        ] ifFalse:[
+"/            rle ifFalse:[self halt:'oops - should not happen'].
+            self read24RLE.
+        ].
+        bytesPerRow := width*3.
+        bytesPerPixel := 3.
+    ].
+    depth == 8 ifTrue:[
+        imageType == 1 ifTrue:[
+"/            rle ifTrue:[self halt:'oops - should not happen'].
+            self read8.
+        ] ifFalse:[
+"/            rle ifFalse:[self halt:'oops - should not happen'].
+            self read8RLE
+        ].
+        bytesPerRow := width.
+        bytesPerPixel := 1.
+    ].
+
+    self handleImageOrientation.
+
+    "
+     TargaReader fromFile:'bitmaps/test.tga' 
+    "
+
+    "Modified: / 7.9.1998 / 21:12:12 / cg"
+    "Modified: / 13.10.1998 / 19:50:48 / ps"
 ! !
 
 !TargaReader class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/TargaReader.st,v 1.20 2002-07-17 10:56:36 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/TargaReader.st,v 1.21 2003-04-04 17:18:18 cg Exp $'
 ! !
+
 TargaReader initialize!