Initial revision
authorclaus
Mon, 10 Oct 1994 03:32:51 +0100
changeset 27 93da277c5ddd
parent 26 2fe6294ca833
child 28 8daff0234d2e
Initial revision
PCXReader.st
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCXReader.st	Mon Oct 10 03:32:51 1994 +0100
@@ -0,0 +1,275 @@
+"
+ COPYRIGHT (c) 1994 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.
+"
+
+'From Smalltalk/X, Version:2.10.3 on 22-sep-1994 at 7:31:01 pm'!
+
+ImageReader subclass:#PCXReader
+	 instanceVariableNames:''
+	 classVariableNames:''
+	 poolDictionaries:''
+	 category:'Graphics-Support'
+!
+
+PCXReader comment:'
+COPYRIGHT (c) 1994 by Claus Gittinger
+	      All Rights Reserved
+
+$Header: /cvs/stx/stx/libview2/PCXReader.st,v 1.1 1994-10-10 02:32:51 claus Exp $
+'!
+
+!PCXReader class methodsFor:'testing'!
+
+isValidPCXHeader:aHeader
+    "return true, if aHeader looks like a PCX image header"
+
+    "check id"
+    ((aHeader at:1) ~~ 16r0A) ifTrue:[
+	^ false
+    ].
+
+    "check version"
+    (#(0 2 3 5) includes:(aHeader at:2)) ifFalse:[
+	^ false
+    ].
+
+    ^ true
+!
+
+isValidImageFile:aFilename
+    "return true, if aFilename contains a PCX image"
+
+    |fileSize header inStream|
+
+    inStream := self streamReadingFile:aFilename.
+    inStream isNil ifTrue:[^ false].
+
+    inStream binary.
+    fileSize := inStream size.
+
+    fileSize < 128 ifTrue:[
+	inStream close.
+	^ false
+    ].
+
+    header := ByteArray uninitializedNew:128.
+    inStream nextBytes:128 into:header.
+    inStream close.
+
+    (self isValidPCXHeader:header) ifFalse:[
+	^ false
+    ].
+    ^ true
+! !
+
+!PCXReader class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 1994 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.
+"
+!
+
+version
+"
+$Header: /cvs/stx/stx/libview2/PCXReader.st,v 1.1 1994-10-10 02:32:51 claus Exp $
+"
+!
+
+documentation
+"
+    this class provides methods for loading PCX bitmap files..
+"
+! !
+
+!PCXReader class methodsFor:'initialization'!
+
+initialize
+    "tell Image-class, that a new fileReader is present"
+
+    Image fileFormats at:'.pcx'  put:self.
+! !
+
+!PCXReader methodsFor:'reading from file'!
+
+fromStreamWithHeader:header 
+    | inDepth version compression nPlanes xmin ymin xmax ymax
+      paletteType rawMap rMap gMap bMap 
+      endIndex "{Class: SmallInteger }"
+      srcIndex "{Class: SmallInteger }"
+      dstIndex "{Class: SmallInteger }"
+      rowIndex "{Class: SmallInteger }"
+      h        "{Class: SmallInteger }"
+      byte     "{Class: SmallInteger }"
+      nByte    "{Class: SmallInteger }"
+      idx2
+      dataBytes bytesPerRow value|
+
+    version := header at:2.
+"/    'version=' print. version printNL.
+    compression := header at:3.
+"/    'compression=' print. compression printNL.
+    (#(0 1) includes:compression) ifFalse:[
+	self error:'PCXREADER: unknown compression'.
+	^ nil
+    ].
+    inDepth := header at:4.
+"/    'depth=' print. inDepth printNL.
+    nPlanes := header at:66.
+"/    'planes=' print. nPlanes printNL.
+    bytesPerRow := header wordAt:67.
+"/    'bytesPerRow=' print. bytesPerRow printNL.
+    paletteType := header at:69.
+
+    "
+     although it would be easy to implement ...
+     I have no test pictures for other formats.
+     So its not (yet) implemented
+    "
+    ((inDepth ~~ 8) or:[nPlanes ~~ 1]) ifTrue:[
+	'PCXReader: can only handle 1-plane 256 color images' errorPrintNL.
+	^ nil
+    ].
+
+    xmin := header wordAt:5.
+    ymin := header wordAt:7.
+    xmax := header wordAt:9.
+    ymax := header wordAt:11.
+
+    width := (xmax - xmin + 1).
+    height := (ymax - ymin + 1).
+"/    'width=' print. width printNL.
+"/    'height=' print. width printNL.
+
+    (version == 2) ifTrue:[
+	"read the 16-entry colormap"
+
+	rawMap := ByteArray uninitializedNew:(16*3).
+	rawMap replaceFrom:1 to:(16*3) with:header startingAt:17.
+	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.
+	].
+    ].
+
+    data := dataBytes := ByteArray new:(height * bytesPerRow).
+
+    compression == 1 ifTrue:[
+	rowIndex := 1.
+	h := height.
+	1 to:h do:[:row |
+	    dstIndex := rowIndex.
+	    endIndex := dstIndex + bytesPerRow.
+	    [dstIndex <= endIndex] whileTrue:[
+		byte := inStream nextByte.
+		((byte bitAnd:16rC0) ~~ 16rC0) ifTrue:[
+		    dataBytes at:dstIndex put:byte.
+		    dstIndex := dstIndex + 1.
+		] ifFalse:[
+		    nByte := byte bitAnd:2r00111111.
+		    value := inStream nextByte.
+		    value notNil ifTrue:[
+			idx2 := endIndex min:(dstIndex + nByte - 1).
+			dataBytes from:dstIndex to:idx2 put:value.
+			dstIndex := dstIndex + nByte.
+		    ]
+		].
+	    ].
+	    rowIndex := rowIndex + bytesPerRow
+	]
+    ] ifFalse:[
+	"
+	 actually untested ...
+	"
+	inStream nextBytes:(height * bytesPerRow) into:data
+    ].
+
+    (version == 5) ifTrue:[
+	"read the 256-entry colormap"
+
+	(byte := inStream next) == 16rC0 ifFalse:[
+	   'PCXREADER: no valid 256-entry palette' printNL.
+	].
+	rawMap := ByteArray uninitializedNew:(256*3).
+	inStream nextBytes:(256*3) into:rawMap.
+	rMap := Array new:256.
+	gMap := Array new:256.
+	bMap := Array new:256.
+	srcIndex := 1.
+	1 to:256 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.
+	].
+    ].
+
+    photometric := #palette.
+    samplesPerPixel := 1.
+    bitsPerSample := #(8).
+    colorMap := Array with:rMap with:gMap with:bMap.
+
+    "
+     |i f|
+     i := Image fromFile:'/LocalLibrary/Images/OS2/dos3.ico'.
+     f := i asFormOn:Display.
+     v displayOpaqueForm:(f magnifyBy:2@2) x:5 y:5
+    "
+!
+
+fromFile:aFilename 
+    | fileSize header img |
+
+    inStream := self class streamReadingFile:aFilename.
+    inStream isNil ifTrue:[^ nil].
+
+    inStream binary.
+    fileSize := inStream size.
+
+    fileSize < 128 ifTrue:[
+	inStream close.
+	self error:'PCXREADER: short file'.
+	^ nil
+    ].
+
+    header := ByteArray uninitializedNew:128.
+    inStream nextBytes:128 into:header.
+
+    (self class isValidPCXHeader:header) ifFalse:[
+	inStream close.
+	self error:'PCXREADER: wrong header'.
+	^ nil
+    ].
+
+    img := self fromStreamWithHeader:header.
+    inStream close.
+    ^ img
+! !
+
+PCXReader initialize!