GIFReader.st
changeset 3392 8bb003c31c63
parent 3385 6843cb82e01d
child 3468 d0a6fa0e6b5f
--- a/GIFReader.st	Tue Nov 18 15:29:43 2014 +0100
+++ b/GIFReader.st	Tue Nov 18 18:39:15 2014 +0100
@@ -49,27 +49,27 @@
     license for the use of the Graphics Interchange Format(sm) in computer
     software; computer software utilizing GIF(sm) must acknowledge ownership of the
     Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in
-    User and Technical Documentation. 
+    User and Technical Documentation.
 
       The Graphics Interchange Format(c) is the Copyright property of
       CompuServe Incorporated. GIF(sm) is a Service Mark property of
       CompuServe Incorporated.
 
     Notice:
-        there has been some annoyance regarding a patent on the compression algorithm
-        used in gif. This patent is now obsolete. However, there is no warranty from
-        exept, regarding any legal problems, when using GIF.
-        We therefore highly recommend to use newer (and especially: royalty-free) formats,
-        such as PNG.
+	there has been some annoyance regarding a patent on the compression algorithm
+	used in gif. This patent is now obsolete. However, there is no warranty from
+	exept, regarding any legal problems, when using GIF.
+	We therefore highly recommend to use newer (and especially: royalty-free) formats,
+	such as PNG.
 
     [See also:]
-        Image Form Icon
-        BlitImageReader FaceReader JPEGReader PBMReader PCXReader 
-        ST80FormReader SunRasterReader TargaReader TIFFReader WindowsIconReader 
-        XBMReader XPMReader XWDReader 
+	Image Form Icon
+	BlitImageReader FaceReader JPEGReader PBMReader PCXReader
+	ST80FormReader SunRasterReader TargaReader TIFFReader WindowsIconReader
+	XBMReader XPMReader XWDReader
 
     [author:]
-        Claus Gittinger
+	Claus Gittinger
 "
 !
 
@@ -78,7 +78,7 @@
     saving an animated gif sequence:
 
      a view showing rainfall:
-                                                                                [exBegin] 
+										[exBegin]
     |BG CLR N1 H W v WIND drops gen newDrops draw remove move buffer|
 
     BG := Color black.
@@ -98,20 +98,20 @@
     buffer := Form extent:(v extent) depth:24 onDevice:v device.
 
     [
-        [v shown] whileTrue:[
-            draw value.
-            v displayForm:buffer.
-            move value:WIND.
-            remove value.
-            newDrops value.
-            WIND := (WIND+(Random nextBetween:-1 and:1)) clampBetween:-5 and:5.
-            Delay waitForSeconds:0.1.
-        ]
+	[v shown] whileTrue:[
+	    draw value.
+	    v displayForm:buffer.
+	    move value:WIND.
+	    remove value.
+	    newDrops value.
+	    WIND := (WIND+(Random nextBetween:-1 and:1)) clampBetween:-5 and:5.
+	    Delay waitForSeconds:0.1.
+	]
     ] fork.
-                                                                                [exEnd]
+										[exEnd]
 
    saving those images:
-                                                                                [exBegin] 
+										[exBegin]
     |seq img BG CLR N1 H W v drops gen gen1 buffer|
 
     BG := Color black.
@@ -131,19 +131,19 @@
 
     seq := OrderedCollection new.
     500 timesRepeat:[
-        move value:WIND.
-        remove value.
-        newDrops value.
-        draw value.
-        seq add:(ImageFrame new delay:100; image:(Depth8Image fromForm:buffer)).
-        WIND := (WIND+(Random nextBetween:-1 and:1)) clampBetween:-5 and:5.
+	move value:WIND.
+	remove value.
+	newDrops value.
+	draw value.
+	seq add:(ImageFrame new delay:100; image:(Depth8Image fromForm:buffer)).
+	WIND := (WIND+(Random nextBetween:-1 and:1)) clampBetween:-5 and:5.
     ].
 
     img := seq first image.
     img imageSequence:(seq copyFrom:2).
     img imageSequence do:[:each | each image colorMap:img colorMap].
     GIFReader save:img onFile:'/tmp/img.gif'
-                                                                                [exEnd]
+										[exEnd]
 "
 ! !
 
@@ -192,7 +192,7 @@
     (id = 'GIF87a') ifFalse:[
 	(id startsWith:'GIF') ifFalse:[^ false].
 
-	id ~= 'GIF89a' ifTrue:[ 
+	id ~= 'GIF89a' ifTrue:[
 	    'GIFReader [info]: not a GIF87a/GIF89a file - hope that works' infoPrintCR.
 	]
     ].
@@ -207,13 +207,10 @@
     "read a stream containing a GIF image (or an image sequence).
      Leave image description in instance variables."
 
-    |byte index flag count fileColorMap
+    |byte flag fileColorMap
      colorMapSize bitsPerPixel scrWidth scrHeight
-     hasColorMap hasLocalColorMap interlaced id
-     codeLen
-     compressedData compressedSize
-     tmp srcOffset dstOffset isGif89 atEnd
-     h "{ Class: SmallInteger }" 
+     hasColorMap interlaced id
+     isGif89 atEnd
      img firstImage firstOffset firstFrameDelay frame imageCount|
 
     inStream := aStream.
@@ -224,7 +221,7 @@
 
     id := ByteArray new:6.
     (aStream nextBytes:6 into:id startingAt:1) ~~ 6 ifTrue:[
-        ^ self fileFormatError:'not a gif file (short read)'.
+	^ self fileFormatError:'not a gif file (short read)'.
     ].
     id := id asString.
 
@@ -233,12 +230,12 @@
 
     isGif89 := false.
     (id ~= 'GIF87a') ifTrue:[
-        (id startsWith:'GIF') ifFalse:[
-            ^ self fileFormatError:('not a gif file (id=''' , id , ''')').
-        ].
-        id ~= 'GIF89a' ifTrue:[ 
-            'GIFReader [info]: not a GIF87a/GIF89a file - hope that works' infoPrintCR.
-        ]
+	(id startsWith:'GIF') ifFalse:[
+	    ^ self fileFormatError:('not a gif file (id=''' , id , ''')').
+	].
+	id ~= 'GIF89a' ifTrue:[
+	    'GIFReader [info]: not a GIF87a/GIF89a file - hope that works' infoPrintCR.
+	]
     ].
 
     "get screen dimensions (not used)"
@@ -261,7 +258,7 @@
 
     "get colorMap"
     hasColorMap ifTrue:[
-        fileColorMap := self readColorMap:colorMapSize.
+	fileColorMap := self readColorMap:colorMapSize.
     ].
     colorMap := fileColorMap.
 
@@ -272,91 +269,91 @@
     imageCount := 0.
     atEnd := false.
     [atEnd] whileFalse:[
-        "gif89a extensions"
+	"gif89a extensions"
 
-        byte := aStream nextByte.
-        byte isNil ifTrue:[
-            "/ atEnd-Terminator missing
-            atEnd := true
-        ] ifFalse:[
-            byte == Extension ifTrue:[
+	byte := aStream nextByte.
+	byte isNil ifTrue:[
+	    "/ atEnd-Terminator missing
+	    atEnd := true
+	] ifFalse:[
+	    byte == Extension ifTrue:[
 "/ 'Ext' infoPrintCR.
-                self readExtension:aStream.
-            ] ifFalse:[
-                (byte == Terminator) ifTrue:[
-                    atEnd := true
-                ] ifFalse:[
-                    "must be image separator"
-                    (byte ~~ ImageSeparator) ifTrue:[
-                        ^ self fileFormatError:('corrupted gif file (no IMAGESEP): ' , (byte printStringRadix:16)).
-                    ].
+		self readExtension:aStream.
+	    ] ifFalse:[
+		(byte == Terminator) ifTrue:[
+		    atEnd := true
+		] ifFalse:[
+		    "must be image separator"
+		    (byte ~~ ImageSeparator) ifTrue:[
+			^ self fileFormatError:('corrupted gif file (no IMAGESEP): ' , (byte printStringRadix:16)).
+		    ].
 "/ 'Img' infoPrintCR.
 
-                    fileColorMap notNil ifTrue:[
-                        colorMap := fileColorMap.
-                    ].
-                    Object primitiveFailureSignal handle:[:ex |
-                        ^ self fileFormatError:('corrupted gif file').
-                    ] do:[
-                        self readImage:aStream.
-                    ].
+		    fileColorMap notNil ifTrue:[
+			colorMap := fileColorMap.
+		    ].
+		    Object primitiveFailureSignal handle:[:ex |
+			^ self fileFormatError:('corrupted gif file').
+		    ] do:[
+			self readImage:aStream.
+		    ].
 
-                    maskPixel notNil ifTrue:[
-                        "/
-                        "/ ok, there is a maskValue
-                        "/ build a Depth1Image for it.
-                        "/
-                        self buildMaskFromColor:maskPixel
-                    ].
+		    maskPixel notNil ifTrue:[
+			"/
+			"/ ok, there is a maskValue
+			"/ build a Depth1Image for it.
+			"/
+			self buildMaskFromColor:maskPixel
+		    ].
 
-                    imageCount == 0 ifTrue:[
-                        img := self makeImage.
-                        "/ remember first image in case more come later.
-                        firstImage := img.
-                        firstFrameDelay := frameDelay.
-                        firstOffset := (leftOffs @ topOffs).
-                    ] ifFalse:[
-                        imageCount == 1 ifTrue:[
-                            imageSequence := ImageSequence new.
-                            img imageSequence:imageSequence.
+		    imageCount == 0 ifTrue:[
+			img := self makeImage.
+			"/ remember first image in case more come later.
+			firstImage := img.
+			firstFrameDelay := frameDelay.
+			firstOffset := (leftOffs @ topOffs).
+		    ] ifFalse:[
+			imageCount == 1 ifTrue:[
+			    imageSequence := ImageSequence new.
+			    img imageSequence:imageSequence.
 
-                            "/ add frame for first image.
-                            frame := ImageFrame new image:firstImage.
-                            frame delay:firstFrameDelay.
-                            frame offset:firstOffset.
-                            imageSequence add:frame.
-                        ].  
-                        img := self makeImage.
-                        img imageSequence:imageSequence.
+			    "/ add frame for first image.
+			    frame := ImageFrame new image:firstImage.
+			    frame delay:firstFrameDelay.
+			    frame offset:firstOffset.
+			    imageSequence add:frame.
+			].
+			img := self makeImage.
+			img imageSequence:imageSequence.
 
-                        "/ add frame for this image.
-                        frame := ImageFrame new image:img.
-                        frame delay:frameDelay.
-                        frame offset:(leftOffs @ topOffs).
-                        imageSequence add:frame.
-                    ].
+			"/ add frame for this image.
+			frame := ImageFrame new image:img.
+			frame delay:frameDelay.
+			frame offset:(leftOffs @ topOffs).
+			imageSequence add:frame.
+		    ].
 
-                    imageCount := imageCount + 1.
+		    imageCount := imageCount + 1.
 
-                    frameDelay := nil.
+		    frameDelay := nil.
 
-                    aStream atEnd ifTrue:[
-                        atEnd := true.
-                    ]
-                ]
-            ].
-        ].
+		    aStream atEnd ifTrue:[
+			atEnd := true.
+		    ]
+		]
+	    ].
+	].
     ].
 
     imageSequence notNil ifTrue:[
-        iterationCount notNil ifTrue:[
-            iterationCount == 0 ifTrue:[
-                imageSequence loop:true.
-            ] ifFalse:[
-                imageSequence loop:false.
-                imageSequence iterationCount:iterationCount.
-            ]
-        ]
+	iterationCount notNil ifTrue:[
+	    iterationCount == 0 ifTrue:[
+		imageSequence loop:true.
+	    ] ifFalse:[
+		imageSequence loop:false.
+		imageSequence iterationCount:iterationCount.
+	    ]
+	]
     ].
 
     "
@@ -380,7 +377,7 @@
     |rgbVector|
 
     rgbVector := inStream nextBytes:colorMapSize*3.
-    ^ MappedPalette rgbBytesVector:rgbVector 
+    ^ MappedPalette rgbBytesVector:rgbVector
 !
 
 readExtension:aStream
@@ -394,136 +391,136 @@
 
     type := aStream nextByte.
     type == $R codePoint ifTrue:[
-        "/
-        "/ Ratio extension
-        "/
-        "/ 'GIFREADER [info]: ratio extension ignored' infoPrintCR.
-        blockSize := aStream nextByte.
-        (blockSize == 2) ifTrue:[
-            aspNum := aStream nextByte.
-            aspDen := aStream nextByte
-        ] ifFalse:[
-            aStream skip:blockSize
-        ].
+	"/
+	"/ Ratio extension
+	"/
+	"/ 'GIFREADER [info]: ratio extension ignored' infoPrintCR.
+	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
-        ].
-        ^ self
+	"/ eat subblocks
+	[(subBlockSize := aStream nextByte) > 0] whileTrue:[
+	    aStream skip:subBlockSize
+	].
+	^ self
     ].
 
     type == 16r01 ifTrue:[
-        "/
-        "/ plaintext extension
-        "/
-        "/ 'GIFREADER [info]: plaintext extension ignored' infoPrintCR.
-        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.
-        "/ eat subblocks
-        [(subBlockSize := aStream nextByte) > 0] whileTrue:[
-            aStream skip:subBlockSize
-        ].
-        ^ self
+	"/
+	"/ plaintext extension
+	"/
+	"/ 'GIFREADER [info]: plaintext extension ignored' infoPrintCR.
+	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.
+	"/ eat subblocks
+	[(subBlockSize := aStream nextByte) > 0] whileTrue:[
+	    aStream skip:subBlockSize
+	].
+	^ self
     ].
 
     type == 16rF9 ifTrue:[
-        "/
-        "/ graphic control extension
-        "/
-        "/ 'GIFREADER [info]: graphic control extension' infoPrintCR.
+	"/
+	"/ graphic control extension
+	"/
+	"/ 'GIFREADER [info]: graphic control extension' infoPrintCR.
 
-        [(subBlockSize := aStream nextByte) ~~ 0 and:[subBlockSize notNil]] whileTrue:[
-            "/ type bitAnd:1 means: animationMask is transparent pixel
-            "/ to be implemented in Image ...
+	[(subBlockSize := aStream nextByte) ~~ 0 and:[subBlockSize notNil]] whileTrue:[
+	    "/ type bitAnd:1 means: animationMask is transparent pixel
+	    "/ to be implemented in Image ...
 
-            animationType := aStream nextByte.
-            animationTime := aStream nextShortMSB:false.
-            animationMask := aStream nextByte.
+	    animationType := aStream nextByte.
+	    animationTime := aStream nextShortMSB:false.
+	    animationMask := aStream nextByte.
 
-            subBlockSize := subBlockSize - 4.
+	    subBlockSize := subBlockSize - 4.
 
-           (animationType bitTest: 1) ifTrue:[
-                maskPixel := animationMask.
+	   (animationType bitTest: 1) ifTrue:[
+		maskPixel := animationMask.
 "/                'GIFREADER [info]: mask: ' infoPrint. (maskPixel printStringRadix:16) infoPrintCR.
-            ].
+	    ].
 "/            'GIFREADER [info]: animationTime: ' infoPrint. (animationTime * (1/100)) infoPrintCR.
 "/            'GIFREADER [info]: animationType: ' infoPrint. (animationType) infoPrintCR.
 "/            'GIFREADER [info]: animationMask: ' infoPrint. (animationMask) infoPrintCR.
 
-            frameDelay := (animationTime * (1/100)) * 1000.
+	    frameDelay := (animationTime * (1/100)) * 1000.
 
-            subBlockSize ~~ 0 ifTrue:[
-                aStream skip:subBlockSize
-            ].
-        ].
-        ^ self
+	    subBlockSize ~~ 0 ifTrue:[
+		aStream skip:subBlockSize
+	    ].
+	].
+	^ self
     ].
 
     type == 16rFE ifTrue:[
-        "/
-        "/ comment extension
-        "/
-        "/ 'GIFREADER [info]: comment extension' infoPrintCR.
-        [(blockSize := aStream nextByte) ~~ 0] whileTrue:[
-            aStream skip:blockSize
-        ].
-        ^ self
+	"/
+	"/ comment extension
+	"/
+	"/ 'GIFREADER [info]: comment extension' infoPrintCR.
+	[(blockSize := aStream nextByte) ~~ 0] whileTrue:[
+	    aStream skip:blockSize
+	].
+	^ self
     ].
 
     type == 16rFF ifTrue:[
-        "/
-        "/  application extension
-        "/
-        "/ 'GIFREADER [info]: application extension' infoPrintCR.
-        subBlockSize := aStream nextByte.
-        appID := (aStream nextBytes:8 ) asString.
-        appAUTH := aStream nextBytes:3.
+	"/
+	"/  application extension
+	"/
+	"/ 'GIFREADER [info]: application extension' infoPrintCR.
+	subBlockSize := aStream nextByte.
+	appID := (aStream nextBytes:8 ) asString.
+	appAUTH := aStream nextBytes:3.
 
-        subBlockSize := aStream nextByte.
+	subBlockSize := aStream nextByte.
 
-        ok := false.
-        appID = 'NETSCAPE' ifTrue:[
-            appAUTH asString = '2.0' ifTrue:[
-                subBlockSize == 3 ifTrue:[
-                    b := aStream nextByte.
-                    iterationCount := aStream nextShortMSB:false.
-                    subBlockSize := aStream nextByte.
-                    ok := true.
+	ok := false.
+	appID = 'NETSCAPE' ifTrue:[
+	    appAUTH asString = '2.0' ifTrue:[
+		subBlockSize == 3 ifTrue:[
+		    b := aStream nextByte.
+		    iterationCount := aStream nextShortMSB:false.
+		    subBlockSize := aStream nextByte.
+		    ok := true.
 "/                    ('GIFREADER [info]: NETSCAPE application extension - iterationCount = ') infoPrint.
 "/                    iterationCount infoPrintCR.
-                ]
-            ]
-        ].
+		]
+	    ]
+	].
 
-        ok ifFalse:[
-            ('GIFREADER [info]: application extension (' , appID , ') ignored') infoPrintCR.
-        ].
+	ok ifFalse:[
+	    ('GIFREADER [info]: application extension (' , appID , ') ignored') infoPrintCR.
+	].
 
-        [subBlockSize > 0] whileTrue:[
-            aStream skip:subBlockSize.
-            subBlockSize := aStream nextByte.
-        ].
-        ^ self
+	[subBlockSize > 0] whileTrue:[
+	    aStream skip:subBlockSize.
+	    subBlockSize := aStream nextByte.
+	].
+	^ self
     ].
 
     type == 16r2C ifTrue:[
-        "/
-        "/  image descriptor extension
-        "/
-        "/ 'GIFREADER [info]: image descriptor extension ignored' infoPrintCR.
-        [(subBlockSize := aStream nextByte) > 0] whileTrue:[
-            aStream skip:subBlockSize
-        ].
-        ^ self
+	"/
+	"/  image descriptor extension
+	"/
+	"/ 'GIFREADER [info]: image descriptor extension ignored' infoPrintCR.
+	[(subBlockSize := aStream nextByte) > 0] whileTrue:[
+	    aStream skip:subBlockSize
+	].
+	^ self
     ].
 
     "/
@@ -531,7 +528,7 @@
     "/
     'GIFREADER [info]: unknown extension ignored' infoPrintCR.
     [(subBlockSize := aStream nextByte) > 0] whileTrue:[
-        aStream skip:subBlockSize
+	aStream skip:subBlockSize
     ]
 
     "Modified: / 02-06-2010 / 12:21:53 / cg"
@@ -568,20 +565,20 @@
     "if image has a local colormap, this one is used"
 
     hasLocalColorMap ifTrue:[
-        "local descr. overwrites"
-        bitsPerPixel := (flag bitAnd:2r00000111) + 1.
-        colorMapSize := 1 bitShift:bitsPerPixel.
-        "overwrite colormap"
-        colorMap := self readColorMap:colorMapSize.
+	"local descr. overwrites"
+	bitsPerPixel := (flag bitAnd:2r00000111) + 1.
+	colorMapSize := 1 bitShift:bitsPerPixel.
+	"overwrite colormap"
+	colorMap := self readColorMap:colorMapSize.
     ].
 
 
     "get codelen for decompression"
     codeLen := aStream nextByte.
     (aStream respondsTo:#fileSize) ifTrue:[
-        initialBuffSize := aStream fileSize.
+	initialBuffSize := aStream fileSize.
     ] ifFalse:[
-        initialBuffSize := 512.
+	initialBuffSize := 512.
     ].
     compressedData := ByteArray uninitializedNew:initialBuffSize.
 
@@ -589,17 +586,17 @@
     index := 1.
     count := aStream nextByte.
     [count notNil and:[count ~~ 0]] whileTrue:[
-        (compressedData size < (index+count)) ifTrue:[
-            |t|
+	(compressedData size < (index+count)) ifTrue:[
+	    |t|
 
-            t := ByteArray uninitializedNew:(index+count*3//2).
-            t replaceBytesFrom:1 to:index-1 with:compressedData startingAt:1.
-            compressedData := t.
-        ].
+	    t := ByteArray uninitializedNew:(index+count*3//2).
+	    t replaceBytesFrom:1 to:index-1 with:compressedData startingAt:1.
+	    compressedData := t.
+	].
 
-        aStream nextBytes:count into:compressedData startingAt:index blockSize:4096.
-        index := index + count.
-        count := aStream nextByte
+	aStream nextBytes:count into:compressedData startingAt:index blockSize:4096.
+	index := index + count.
+	count := aStream nextByte
     ].
     compressedSize := index - 1.
 
@@ -608,54 +605,54 @@
 "/    'GIFReader: decompressing ...' infoPrintCR.
 
     self class decompressGIFFrom:compressedData
-                           count:compressedSize
-                            into:data
-                      startingAt:1
-                         codeLen:(codeLen + 1).
+			   count:compressedSize
+			    into:data
+		      startingAt:1
+			 codeLen:(codeLen + 1).
 
     interlaced ifTrue:[
 "/    'GIFREADER: deinterlacing ...' infoPrintCR.
-        tmp := ByteArray new:(data size).
+	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.
     ].
 
     "Created: / 13.1.1998 / 10:44:05 / cg"
@@ -670,17 +667,17 @@
     |cmap usedPixelValues unusedValues|
 
     (cmap := image colorMap) size > 0 ifTrue:[
-        cmap size < 256 ifTrue:[
-            maskPixel := cmap size.
-            ^ self
-        ]
+	cmap size < 256 ifTrue:[
+	    maskPixel := cmap size.
+	    ^ self
+	]
     ].
     image compressColorMap.
     usedPixelValues := image usedValues.
     usedPixelValues size < (1 bitShift:image depth) ifFalse:[
-        Image informationLostQuerySignal
-            raiseRequestWith:image
-            errorString:('GIF writer cannot assign a transparent pixel - all pixelValues used by image').
+	Image informationLostQuerySignal
+	    raiseRequestWith:image
+	    errorString:('GIF writer cannot assign a transparent pixel - all pixelValues used by image').
     ].
 
     "/ there must be an unused pixelValue
@@ -694,7 +691,7 @@
 
 checkCodeSize
     (freeCode > maxCode and: [codeSize < 12])
-	    ifTrue: 
+	    ifTrue:
 		    [codeSize := codeSize + 1.
 		    maxCode := (1 bitShift: codeSize) - 1]
 
@@ -703,7 +700,7 @@
 
 flushBits
 	remainBitCount = 0
-		ifFalse: 
+		ifFalse:
 			[self nextBytePut: bufByte.
 			remainBitCount := 0].
 	self flushBuffer
@@ -727,24 +724,24 @@
 !
 
 nextBitsPut: anInteger
-        | integer writeBitCount shiftCount |
-        shiftCount := 0.
-        remainBitCount = 0
-                ifTrue:
-                        [writeBitCount := 8.
-                        integer := anInteger]
-                ifFalse:
-                        [writeBitCount := remainBitCount.
-                        integer := bufByte + (anInteger bitShift: 8 - remainBitCount)].
-        [writeBitCount < codeSize]
-                whileTrue:
-                        [self nextBytePut: ((integer bitShift: shiftCount) bitAnd: 255).
-                        shiftCount := shiftCount - 8.
-                        writeBitCount := writeBitCount + 8].
-        (remainBitCount := writeBitCount - codeSize) = 0
-                ifTrue: [self nextBytePut: (integer bitShift: shiftCount)]
-                ifFalse: [bufByte := integer bitShift: shiftCount].
-        ^anInteger
+	| integer writeBitCount shiftCount |
+	shiftCount := 0.
+	remainBitCount = 0
+		ifTrue:
+			[writeBitCount := 8.
+			integer := anInteger]
+		ifFalse:
+			[writeBitCount := remainBitCount.
+			integer := bufByte + (anInteger bitShift: 8 - remainBitCount)].
+	[writeBitCount < codeSize]
+		whileTrue:
+			[self nextBytePut: ((integer bitShift: shiftCount) bitAnd: 255).
+			shiftCount := shiftCount - 8.
+			writeBitCount := writeBitCount + 8].
+	(remainBitCount := writeBitCount - codeSize) = 0
+		ifTrue: [self nextBytePut: (integer bitShift: shiftCount)]
+		ifFalse: [bufByte := integer bitShift: shiftCount].
+	^anInteger
 
     "Modified: 15.10.1997 / 16:50:30 / cg"
 !
@@ -756,10 +753,10 @@
     "Modified: 15.10.1997 / 16:50:52 / cg"
 !
 
-readPixelFrom: bits 
+readPixelFrom: bits
     | pixel |
     ypos >= height ifTrue: [^ nil].
-    (maskPixel notNil 
+    (maskPixel notNil
     and:[(mask pixelAtX:xpos y:ypos) == 0]) ifTrue:[
 	pixel := maskPixel
     ] ifFalse:[
@@ -772,7 +769,7 @@
     "Modified: 15.10.1997 / 16:46:43 / cg"
 !
 
-setParameters:bitsPerPixel 
+setParameters:bitsPerPixel
     clearCode := 1 bitShift:bitsPerPixel.
     eoiCode := clearCode + 1.
     freeCode := clearCode + 2.
@@ -787,34 +784,34 @@
 
     xpos := 0.
     interlace == true ifFalse:[
-        ypos := ypos + 1.
-        ^ self
+	ypos := ypos + 1.
+	^ self
     ].
 
     pass == 0 ifTrue:[
-        (ypos := ypos + 8) >= height ifTrue:[
-            pass := pass + 1.
-            ypos := 4
-        ].
-        ^ self
+	(ypos := ypos + 8) >= height ifTrue:[
+	    pass := pass + 1.
+	    ypos := 4
+	].
+	^ self
     ].
     pass == 1 ifTrue:[
-        (ypos := ypos + 8) >= height ifTrue:[
-            pass := pass + 1.
-            ypos := 2
-        ].
-        ^ self
+	(ypos := ypos + 8) >= height ifTrue:[
+	    pass := pass + 1.
+	    ypos := 2
+	].
+	^ self
     ].
     pass == 2 ifTrue:[
-        (ypos := ypos + 4) >= height ifTrue:[
-            pass := pass + 1.
-            ypos := 1
-        ].
-        ^ self
+	(ypos := ypos + 4) >= height ifTrue:[
+	    pass := pass + 1.
+	    ypos := 1
+	].
+	^ self
     ].
     pass == 3 ifTrue:[
-        ypos := ypos + 2.
-        ^ self
+	ypos := ypos + 2.
+	^ self
     ].
     ^ self error: 'can''t happen'
 
@@ -834,9 +831,9 @@
     self writeShort:height.
 
     interlace == true ifTrue:[
-        t1 := 64
+	t1 := 64
     ] ifFalse:[
-        t1 := 0  "/ no local colormap
+	t1 := 0  "/ no local colormap
     ].
     outStream nextPut:t1.       "/ another flag
 
@@ -864,8 +861,8 @@
     tShift := 0.
     fCode := tSize.
     [fCode < 65536] whileTrue:[
-        tShift := tShift + 1.
-        fCode := fCode * 2
+	tShift := tShift + 1.
+	fCode := fCode * 2
     ].
     tShift := 8 - tShift.
     "/ 1 to: tSize do: [:i | suffixTable at: i put: -1]. - cg changed initialization above
@@ -873,38 +870,38 @@
     self writeCodeAndCheckCodeSize: clearCode.
     ent := self readPixelFrom: bits.
     [(pixel := self readPixelFrom: bits) == nil] whileFalse:[
-        fCode := (pixel bitShift: maxBits) + ent.
-        index := ((pixel bitShift: tShift) bitXor: ent) + 1.
-        (suffixTable at: index) = fCode
-            ifTrue: [ent := prefixTable at: index]
-            ifFalse:[
-                nomatch := true.
-                (suffixTable at: index) >= 0
-                    ifTrue:[
-                        disp := tSize - index + 1.
-                        index = 1 ifTrue: [disp := 1].
-                        "probe"
-                        [(index := index - disp) < 1 ifTrue: [index := index + tSize].
-                        (suffixTable at: index) = fCode
-                            ifTrue:[
-                                    ent := prefixTable at: index.
-                                    nomatch := false.
-                                    "continue whileFalse:"].
-                        nomatch and: [(suffixTable at: index) > 0]]
-                            whileTrue: ["probe"]].
-                "nomatch"
-                nomatch ifTrue:[
-                    self writeCodeAndCheckCodeSize: ent.
-                    ent := pixel.
-                    freeCode < maxMaxCode
-                        ifTrue:[
-                            prefixTable at: index put: freeCode.
-                            suffixTable at: index put: fCode.
-                            freeCode := freeCode + 1]
-                        ifFalse:[
-                            self writeCodeAndCheckCodeSize: clearCode.
-                            suffixTable from:1 to:tSize put:-1.
-                            self setParameters: initCodeSize]]]].
+	fCode := (pixel bitShift: maxBits) + ent.
+	index := ((pixel bitShift: tShift) bitXor: ent) + 1.
+	(suffixTable at: index) = fCode
+	    ifTrue: [ent := prefixTable at: index]
+	    ifFalse:[
+		nomatch := true.
+		(suffixTable at: index) >= 0
+		    ifTrue:[
+			disp := tSize - index + 1.
+			index = 1 ifTrue: [disp := 1].
+			"probe"
+			[(index := index - disp) < 1 ifTrue: [index := index + tSize].
+			(suffixTable at: index) = fCode
+			    ifTrue:[
+				    ent := prefixTable at: index.
+				    nomatch := false.
+				    "continue whileFalse:"].
+			nomatch and: [(suffixTable at: index) > 0]]
+			    whileTrue: ["probe"]].
+		"nomatch"
+		nomatch ifTrue:[
+		    self writeCodeAndCheckCodeSize: ent.
+		    ent := pixel.
+		    freeCode < maxMaxCode
+			ifTrue:[
+			    prefixTable at: index put: freeCode.
+			    suffixTable at: index put: fCode.
+			    freeCode := freeCode + 1]
+			ifFalse:[
+			    self writeCodeAndCheckCodeSize: clearCode.
+			    suffixTable from:1 to:tSize put:-1.
+			    self setParameters: initCodeSize]]]].
     prefixTable := suffixTable := nil.
     self writeCodeAndCheckCodeSize: ent.
     self writeCodeAndCheckCodeSize: eoiCode.
@@ -914,14 +911,14 @@
     "Modified: / 02-06-2010 / 12:24:20 / cg"
 !
 
-writeCode: aCode 
+writeCode: aCode
     self nextBitsPut: aCode
 
     "Created: 14.10.1997 / 18:38:35 / cg"
     "Modified: 15.10.1997 / 17:01:47 / cg"
 !
 
-writeCodeAndCheckCodeSize: t1 
+writeCodeAndCheckCodeSize: t1
     self writeCode: t1.
     self checkCodeSize
 
@@ -938,7 +935,7 @@
 
     outStream nextPutAll: 'GIF89a' asByteArray.
     self writeShort:width. "/ screen size
-    self writeShort:height.    
+    self writeShort:height.
     t1 := 128.
     t1 := t1 bitOr:(bitsPerPixel - 1 bitShift:5).
     t1 := t1 bitOr:(bitsPerPixel - 1).
@@ -947,20 +944,20 @@
     outStream nextPut:0.   "/ aspect ratio
 
     0 to:(1 bitShift:bitsPerPixel)-1 do:[:pixel |
-        |clr red green blue|
+	|clr red green blue|
 
-        clr := image colorFromValue:pixel.
-        clr isNil ifTrue:[
-            "/ unused colorMap slot
-            red := green := blue := 0.
-        ] ifFalse:[
-            red := (clr redByte).
-            green := (clr greenByte).
-            blue := (clr blueByte).
-        ].
-        outStream
-            nextPut:red; nextPut:green; nextPut:blue.
-    ].    
+	clr := image colorFromValue:pixel.
+	clr isNil ifTrue:[
+	    "/ unused colorMap slot
+	    red := green := blue := 0.
+	] ifFalse:[
+	    red := (clr redByte).
+	    green := (clr greenByte).
+	    blue := (clr blueByte).
+	].
+	outStream
+	    nextPut:red; nextPut:green; nextPut:blue.
+    ].
 
     "Created: / 14.10.1997 / 17:41:28 / cg"
     "Modified: / 31.10.1997 / 16:12:13 / cg"
@@ -988,21 +985,21 @@
     |convertedImage|
 
     image depth ~~ 8 ifTrue:[
-        Error handle:[:ex |
-            ^ Image cannotRepresentImageSignal 
-                raiseWith:image
-                errorString:('GIF failed to convert image to depth8: ', ex description).
-            "/ ex return.
-        ] do:[
-            convertedImage := Image newForDepth:8.
-            convertedImage fromImage:image photometric:#palette.
-        ].
-        convertedImage notNil ifTrue:[
-            ^ self save:convertedImage onFile:aFileName
-        ].
-        ^ Image cannotRepresentImageSignal 
-            raiseWith:image
-            errorString:('GIF (currently) only supports depth8 images (cannot convert)').
+	Error handle:[:ex |
+	    ^ Image cannotRepresentImageSignal
+		raiseWith:image
+		errorString:('GIF failed to convert image to depth8: ', ex description).
+	    "/ ex return.
+	] do:[
+	    convertedImage := Image newForDepth:8.
+	    convertedImage fromImage:image photometric:#palette.
+	].
+	convertedImage notNil ifTrue:[
+	    ^ self save:convertedImage onFile:aFileName
+	].
+	^ Image cannotRepresentImageSignal
+	    raiseWith:image
+	    errorString:('GIF (currently) only supports depth8 images (cannot convert)').
     ].
 
     super save:image onFile:aFileName.
@@ -1023,9 +1020,9 @@
     "save image in GIF-file-format onto aStream"
 
     image depth ~~ 8 ifTrue:[
-        ^ Image cannotRepresentImageSignal 
-            raiseWith:image
-            errorString:('GIF (currently) only supports depth8 images').
+	^ Image cannotRepresentImageSignal
+	    raiseWith:image
+	    errorString:('GIF (currently) only supports depth8 images').
     ].
 
     outStream := aStream.
@@ -1033,7 +1030,7 @@
 
     mask := image mask.
     mask notNil ifTrue:[
-        self assignTransparentPixelIn:image
+	self assignTransparentPixelIn:image
     ].
 
     byteOrder := #lsb.
@@ -1047,24 +1044,24 @@
 
     self writeHeaderFor:image.
     maskPixel notNil ifTrue:[
-        self writeMaskExtensionHeaderFor:image.
+	self writeMaskExtensionHeaderFor:image.
     ].
 
     self writeBitDataFor:image.
 
     image imageSequence notEmptyOrNil ifTrue:[
-        image imageSequence do:[:eachFrame |
-            outStream nextPut:Extension.
-            outStream nextPut:16rF9.    "/ graphic control extension
-            outStream nextPut:4.        "/ sub block size
-            outStream nextPut:0.        "/ animation type 0
-            outStream nextPutShort:(eachFrame delay / 10) rounded asInteger MSB:false.
-            outStream nextPut:0.        "/ animation mask
-            outStream nextPut:0.        "/ subblock size
+	image imageSequence do:[:eachFrame |
+	    outStream nextPut:Extension.
+	    outStream nextPut:16rF9.    "/ graphic control extension
+	    outStream nextPut:4.        "/ sub block size
+	    outStream nextPut:0.        "/ animation type 0
+	    outStream nextPutShort:(eachFrame delay / 10) rounded asInteger MSB:false.
+	    outStream nextPut:0.        "/ animation mask
+	    outStream nextPut:0.        "/ subblock size
 
-            self writeBitDataFor:eachFrame image.
-            
-        ].
+	    self writeBitDataFor:eachFrame image.
+
+	].
     ].
 
     outStream nextPut: Terminator.
@@ -1084,11 +1081,11 @@
 !GIFReader class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/GIFReader.st,v 1.106 2014-11-15 16:36:59 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/GIFReader.st,v 1.107 2014-11-18 17:39:15 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview2/GIFReader.st,v 1.106 2014-11-15 16:36:59 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/GIFReader.st,v 1.107 2014-11-18 17:39:15 cg Exp $'
 ! !