GIFReader.st
changeset 154 40bbc62e8d78
parent 136 69c9d2368352
child 174 7fafcc56378d
--- a/GIFReader.st	Mon Jan 15 18:37:08 1996 +0100
+++ b/GIFReader.st	Thu Jan 18 22:14:07 1996 +0100
@@ -11,10 +11,10 @@
 "
 
 ImageReader subclass:#GIFReader
-	 instanceVariableNames:'redMap greenMap blueMap'
-	 classVariableNames:''
-	 poolDictionaries:''
-	 category:'Graphics-Images support'
+	instanceVariableNames:'redMap greenMap blueMap'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Graphics-Images support'
 !
 
 !GIFReader class methodsFor:'documentation'!
@@ -111,7 +111,7 @@
      hasColorMap hasLocalColorMap interlaced id
      leftOffs topOffs codeLen
      compressedData compressedSize
-     tmp srcOffset dstOffset
+     tmp srcOffset dstOffset isGif89
      h "{ Class: SmallInteger }"|
 
     inStream := aStream.
@@ -126,12 +126,15 @@
     "all I had for testing where GIF87a files;
      I hope later versions work too ..."
 
+    isGif89 := false.
     (id ~= 'GIF87a') ifTrue:[
-	(id startsWith:'GIF') ifFalse:[
-	    'GIFReader: not a gif file' errorPrintNL.
-	    ^ nil
-	].
-	'GIFReader: not a GIF87a file - hope that works' errorPrintNL.
+        (id startsWith:'GIF') ifFalse:[
+            'GIFReader: not a gif file' errorPrintNL.
+            ^ nil
+        ].
+        id ~= 'GIF89a' ifTrue:[ 
+            'GIFReader: not a GIF87a/GIF89a file - hope that works' errorPrintNL.
+        ]
     ].
 
     "get screen dimensions (not used)"
@@ -155,14 +158,21 @@
 
     "get colorMap"
     hasColorMap ifTrue:[
-	self readColorMap:colorMapSize
+        self readColorMap:colorMapSize
     ].
 
-    "image separator"
+    "skip gif89a extensions "
     byte := aStream nextByte.
+    [byte == 16r21] whileTrue:[
+        "/ extension
+        self readExtension:aStream.
+        byte := aStream nextByte.
+    ].
+
+    "must now be image separator"
     (byte ~~ 16r2C) ifTrue:[
-	'GIFReader: corrupted gif file (no imgSep)' errorPrintNL.
-	^ nil
+        ('GIFReader: corrupted gif file (no IMAGESEP): ' , (byte printStringRadix:16)) errorPrintNL.
+        ^ nil
     ].
 
     "get image data"
@@ -185,12 +195,12 @@
     "if image has a local colormap, this one is used"
 
     hasLocalColorMap ifTrue:[
-	"local descr. overwrites"
-	bitsPerPixel := (flag bitAnd:2r00000111) + 1.
-	colorMapSize := 1 bitShift:bitsPerPixel.
+        "local descr. overwrites"
+        bitsPerPixel := (flag bitAnd:2r00000111) + 1.
+        colorMapSize := 1 bitShift:bitsPerPixel.
 " 'local colormap' printNewline. "
-	"overwrite colormap"
-	self readColorMap:colorMapSize
+        "overwrite colormap"
+        self readColorMap:colorMapSize
     ].
 
     "get codelen for decompression"
@@ -202,9 +212,9 @@
     index := 1.
     count := aStream nextByte.
     [count notNil and:[count ~~ 0]] whileTrue:[
-	aStream nextBytes:count into:compressedData startingAt:index.
-	index := index + count.
-	count := aStream nextByte
+        aStream nextBytes:count into:compressedData startingAt:index.
+        index := index + count.
+        count := aStream nextByte
     ].
     compressedSize := index - 1.
 
@@ -213,54 +223,54 @@
 "/    'GIFReader: decompressing ...' infoPrintNL.
 
     self class decompressGIFFrom:compressedData
-			   count:compressedSize
-			    into:data
-		      startingAt:1
-			 codeLen:(codeLen + 1).
+                           count:compressedSize
+                            into:data
+                      startingAt:1
+                         codeLen:(codeLen + 1).
 
     interlaced ifTrue:[
-	Transcript showCr:'deinterlacing'.
-	tmp := ByteArray new:(data size).
+        Transcript showCr:'deinterlacing'.
+        tmp := ByteArray new:(data size).
 
-	"phase 1: 0, 8, 16, 24, ..."
+        "phase 1: 0, 8, 16, 24, ..."
 
-	srcOffset := 1.
-	0 to:(h - 1) by:8 do:[:dstRow |
-	    dstOffset := dstRow * width + 1.
-	    tmp replaceFrom:dstOffset to:(dstOffset + width - 1)
-		       with:data startingAt:srcOffset.
-	    srcOffset := srcOffset + width.
-	].
+        srcOffset := 1.
+        0 to:(h - 1) by:8 do:[:dstRow |
+            dstOffset := dstRow * width + 1.
+            tmp replaceFrom:dstOffset to:(dstOffset + width - 1)
+                       with:data startingAt:srcOffset.
+            srcOffset := srcOffset + width.
+        ].
 
-	"phase 2: 4, 12, 20, 28, ..."
+        "phase 2: 4, 12, 20, 28, ..."
 
-	4 to:(h - 1) by:8 do:[:dstRow |
-	    dstOffset := dstRow * width + 1.
-	    tmp replaceFrom:dstOffset to:(dstOffset + width - 1)
-		       with:data startingAt:srcOffset.
-	    srcOffset := srcOffset + width.
-	].
+        4 to:(h - 1) by:8 do:[:dstRow |
+            dstOffset := dstRow * width + 1.
+            tmp replaceFrom:dstOffset to:(dstOffset + width - 1)
+                       with:data startingAt:srcOffset.
+            srcOffset := srcOffset + width.
+        ].
 
-	"phase 3: 2, 6, 10, 14, ..."
+        "phase 3: 2, 6, 10, 14, ..."
 
-	2 to:(h - 1) by:4 do:[:dstRow |
-	    dstOffset := dstRow * width + 1.
-	    tmp replaceFrom:dstOffset to:(dstOffset + width - 1)
-		       with:data startingAt:srcOffset.
-	    srcOffset := srcOffset + width.
-	].
+        2 to:(h - 1) by:4 do:[:dstRow |
+            dstOffset := dstRow * width + 1.
+            tmp replaceFrom:dstOffset to:(dstOffset + width - 1)
+                       with:data startingAt:srcOffset.
+            srcOffset := srcOffset + width.
+        ].
 
-	"phase 4: 1, 3, 5, 7, ..."
+        "phase 4: 1, 3, 5, 7, ..."
 
-	1 to:(h - 1) by:2 do:[:dstRow |
-	    dstOffset := dstRow * width + 1.
-	    tmp replaceFrom:dstOffset to:(dstOffset + width - 1)
-		       with:data startingAt:srcOffset.
-	    srcOffset := srcOffset + width.
-	].
+        1 to:(h - 1) by:2 do:[:dstRow |
+            dstOffset := dstRow * width + 1.
+            tmp replaceFrom:dstOffset to:(dstOffset + width - 1)
+                       with:data startingAt:srcOffset.
+            srcOffset := srcOffset + width.
+        ].
 
-	data := tmp.
-	tmp := nil
+        data := tmp.
+        tmp := nil
     ].
 
     photometric := #palette.
@@ -280,6 +290,8 @@
      GIFReader fromFile:'../fileIn/bitmaps/claus.gif
      GIFReader fromFile:'../fileIn/bitmaps/garfield.gif'
     "
+
+    "Modified: 18.1.1996 / 22:13:38 / cg"
 !
 
 makeGreyscale
@@ -303,11 +315,87 @@
 	greenMap at:i put:(inStream nextByte).
 	blueMap at:i put:(inStream nextByte)
     ]
+!
+
+readExtension:aStream
+    "get gif89 extension"
+
+    |type blockSize subBlockSize
+     aspNum aspDen left top width height cWidth cHeight fg bg|
+
+    type := aStream nextByte.
+    type == $R asciiValue ifTrue:[
+        "/ Ratio extension
+        'GIFREADER: ratio extension ignored' infoPrintNL.
+        blockSize := aStream nextByte.
+        (blockSize == 2) ifTrue:[
+            aspNum := aStream nextByte.
+            aspDen := aStream nextByte
+        ] ifFalse:[
+            aStream skip:blockSize
+        ].
+        "/ eat subblocks
+        
+        [(subBlockSize := aStream nextByte) > 0] whileTrue:[
+            aStream skip:subBlockSize
+        ]
+    ] ifFalse:[
+        type == 16rFE ifTrue:[
+            "/ comment extension
+            'GIFREADER: comment extension ignored' infoPrintNL.
+            [(blockSize := aStream nextByte) ~~ 0] whileTrue:[
+                aStream skip:blockSize
+            ].
+        ] ifFalse:[
+            type == 16r01 ifTrue:[
+                "/ plaintext extension
+                'GIFREADER: plaintext extension ignored' infoPrintNL.
+                subBlockSize := aStream nextByte.
+                left := aStream nextShortMSB:false.
+                top := aStream nextShortMSB:false.
+                width := aStream nextShortMSB:false.
+                height := aStream nextShortMSB:false.
+                cWidth := aStream nextByte.
+                cHeight := aStream nextByte.
+                fg := aStream nextByte.
+                bg := aStream nextByte.
+                aStream skip:12.
+                [(subBlockSize := aStream nextByte) > 0] whileTrue:[
+                    aStream skip:subBlockSize
+                ]
+            ] ifFalse:[
+                type == 16rF9 ifTrue:[
+                    "/ graphic control extension
+                    'GIFREADER: plaintext extension ignored' infoPrintNL.
+                    [(subBlockSize := aStream nextByte) > 0] whileTrue:[
+                        aStream skip:subBlockSize
+                    ]
+                ] ifFalse:[
+                    type == 16rFF ifTrue:[
+                        "/  application extension
+                        'GIFREADER: application extension ignored' infoPrintNL.
+                        [(subBlockSize := aStream nextByte) > 0] whileTrue:[
+                            aStream skip:subBlockSize
+                        ]
+                    ] ifFalse:[
+                        "/ unknown extension
+                        'GIFREADER: unknown extension ignored' infoPrintNL.
+                        [(subBlockSize := aStream nextByte) > 0] whileTrue:[
+                            aStream skip:subBlockSize
+                        ]
+                    ]
+                ]
+            ]
+        ]
+    ]
+
+    "Created: 18.1.1996 / 22:00:51 / cg"
+    "Modified: 18.1.1996 / 22:12:07 / cg"
 ! !
 
 !GIFReader class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/GIFReader.st,v 1.21 1995-12-07 16:48:43 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/GIFReader.st,v 1.22 1996-01-18 21:14:07 cg Exp $'
 ! !
 GIFReader initialize!