--- 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!