GIFReader.st
changeset 714 c89f5c12538c
parent 713 548898fdd1dc
child 718 41ade132da98
--- a/GIFReader.st	Tue Oct 21 20:27:06 1997 +0200
+++ b/GIFReader.st	Wed Oct 22 17:19:46 1997 +0200
@@ -10,8 +10,6 @@
  hereby transferred.
 "
 
-'From Smalltalk/X, Version:3.2.1 on 21-oct-1997 at 5:07:17 pm'                  !
-
 ImageReader subclass:#GIFReader
 	instanceVariableNames:'redMap greenMap blueMap pass xpos ypos rowByteSize remainBitCount
 		bufByte bufStream prefixTable suffixTable clearCode eoiCode
@@ -123,6 +121,29 @@
 
 !GIFReader methodsFor:'private - writing'!
 
+assignTransparentPixelIn:image
+    "find an usused pixelValue in the colorMap (or image)."
+
+    |cmap usedPixelValues|
+
+    (cmap := image colorMap) size > 0 ifTrue:[
+        cmap size < 256 ifTrue:[
+            maskPixel := cmap size.
+            ^ self
+        ]
+    ].
+
+    usedPixelValues := image usedValues.
+    usedPixelValues size < (1 bitShift:image depth) ifTrue:[
+        "/ there must be an unused pixelValue
+        maskPixel := ((0 to:(1 bitShift:image depth)-1) asSet removeAll:(usedPixelValues)) first.
+    ] ifFalse:[
+        Image informationLostQuerySignal
+            raiseWith:image
+            errorString:('GIF writer cannot assign a transparent pixel - all pixelValues used by image').
+    ]
+!
+
 checkCodeSize
     (freeCode > maxCode and: [codeSize < 12])
             ifTrue: 
@@ -190,7 +211,12 @@
 readPixelFrom: bits 
     | pixel |
     ypos >= height ifTrue: [^ nil].
-    pixel := bits at: ypos * rowByteSize + xpos + 1.
+    (maskPixel notNil 
+    and:[(mask pixelAtX:xpos y:ypos) == 0]) ifTrue:[
+        pixel := maskPixel
+    ] ifFalse:[
+        pixel := bits at: ypos * rowByteSize + xpos + 1.
+    ].
     self updatePixelPosition.
     ^ pixel
 
@@ -685,10 +711,9 @@
     ].
     outStream binary.
 
-    image mask notNil ifTrue:[
-        Image informationLostQuerySignal
-            raiseWith:image
-            errorString:('GFF writer does not (yet) support an imageMask').
+    mask := image mask.
+    mask notNil ifTrue:[
+        self assignTransparentPixelIn:image
     ].
 
     byteOrder := #lsb.
@@ -701,7 +726,13 @@
     data := image bits.
 
     self writeHeaderFor:image.
+    maskPixel notNil ifTrue:[
+        self writeMaskExtensionHeaderFor:image.
+    ].
+
     self writeBitDataFor:image.
+
+    outStream nextPut: Terminator.
     outStream close.
 
     "
@@ -719,9 +750,22 @@
 writeBitDataFor: image
         "using modified Lempel-Ziv Welch algorithm."
 
-        | bits bitsPerPixel
+        | bits bitsPerPixel t1
           maxBits maxMaxCode tSize initCodeSize ent tShift fCode pixel index disp nomatch |
 
+        outStream nextPut:ImageSeparator.
+        self writeShort:0.       "/
+        self writeShort:0.       "/
+        self writeShort:width.   "/ image size
+        self writeShort:height.
+
+        interlace == true ifTrue:[
+            t1 := 64
+        ] ifFalse:[
+            t1 := 0
+        ].
+        outStream nextPut:t1.       "/ another flag
+
         bitsPerPixel := image bitsPerPixel.
         bits := image bits.
 
@@ -791,15 +835,13 @@
         self writeCodeAndCheckCodeSize: ent.
         self writeCodeAndCheckCodeSize: eoiCode.
         self flushCode.
-
         outStream nextPut: 0.        "zero-length packet"
-        outStream nextPut: Terminator.
 
     "Modified: 15.10.1997 / 19:56:28 / cg"
 !
 
 writeHeaderFor:image
-    "save image as GIF file on aFileName"
+    "write the gif header"
 
     |bitsPerPixel t1 n|
 
@@ -851,26 +893,29 @@
 "/    n+1 to:(1 bitShift:bitsPerPixel) do:[:i |
 "/        outStream nextPut:0; nextPut:0; nextPut:0
 "/    ].
-    outStream nextPut:ImageSeparator.
-    self writeShort:0.       "/
-    self writeShort:0.       "/
-    self writeShort:width.   "/ image size
-    self writeShort:height.
 
-    interlace == true ifTrue:[
-        t1 := 64
-    ] ifFalse:[
-        t1 := 0
-    ].
-    outStream nextPut:t1       "/ another flag
 
     "Created: 14.10.1997 / 17:41:28 / cg"
     "Modified: 21.10.1997 / 04:52:18 / cg"
+!
+
+writeMaskExtensionHeaderFor:image
+    "write an extension header for the transparent pixel"
+
+    outStream nextPut:Extension.
+    outStream nextPut:16rF9.       "/ graphic control extension
+    outStream nextPut:4.           "/ subBlockSize
+
+    outStream nextPut:1.                "/ animationType
+    outStream nextPutShort:1 MSB:false. "/ animationTime
+    outStream nextPut:maskPixel.        "/ animationMask
+
+    outStream nextPut:0.
 ! !
 
 !GIFReader class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/GIFReader.st,v 1.60 1997-10-21 18:26:40 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/GIFReader.st,v 1.61 1997-10-22 15:19:46 ca Exp $'
 ! !
 GIFReader initialize!