diff -r a1ed08195ee7 -r 9c85e9d8326b TargaReader.st --- 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!