8 be provided or otherwise made available to, or used by, any |
8 be provided or otherwise made available to, or used by, any |
9 other person. No title to or ownership of the software is |
9 other person. No title to or ownership of the software is |
10 hereby transferred. |
10 hereby transferred. |
11 " |
11 " |
12 |
12 |
13 'From Smalltalk/X, Version:3.2.1 on 14-oct-1997 at 11:13:24 pm' ! |
|
14 |
|
15 ImageReader subclass:#GIFReader |
13 ImageReader subclass:#GIFReader |
16 instanceVariableNames:'redMap greenMap blueMap pass xpos ypos rowByteSize remainBitCount |
14 instanceVariableNames:'redMap greenMap blueMap pass xpos ypos rowByteSize remainBitCount |
17 bufByte bufStream prefixTable suffixTable clearCode eoiCode |
15 bufByte bufStream prefixTable suffixTable clearCode eoiCode |
18 freeCode codeSize maxCode interlace' |
16 freeCode codeSize maxCode interlace' |
19 classVariableNames:'ImageSeparator Extension Terminator' |
17 classVariableNames:'ImageSeparator Extension Terminator' |
146 self flushBits |
144 self flushBits |
147 |
145 |
148 "Created: 14.10.1997 / 18:57:33 / cg" |
146 "Created: 14.10.1997 / 18:57:33 / cg" |
149 ! |
147 ! |
150 |
148 |
151 nextBitsPut: t1 |
149 nextBitsPut: anInteger |
152 | t2 t3 t4 | |
150 | integer writeBitCount shiftCount | |
153 t4 := 0. |
151 shiftCount _ 0. |
154 remainBitCount = 0 |
152 remainBitCount = 0 |
155 ifTrue: |
153 ifTrue: |
156 [t3 := 8. |
154 [writeBitCount _ 8. |
157 t2 := t1] |
155 integer _ anInteger] |
158 ifFalse: |
156 ifFalse: |
159 [t3 := remainBitCount. |
157 [writeBitCount _ remainBitCount. |
160 t2 := bufByte + (t1 bitShift: 8 - remainBitCount)]. |
158 integer _ bufByte + (anInteger bitShift: 8 - remainBitCount)]. |
161 [t3 < codeSize] |
159 [writeBitCount < codeSize] |
162 whileTrue: |
160 whileTrue: |
163 [self nextBytePut: ((t2 bitShift: t4) bitAnd: 255). |
161 [self nextBytePut: ((integer bitShift: shiftCount) bitAnd: 255). |
164 t4 := t4 - 8. |
162 shiftCount _ shiftCount - 8. |
165 t3 := t3 + 8]. |
163 writeBitCount _ writeBitCount + 8]. |
166 (remainBitCount := t3 - codeSize) = 0 |
164 (remainBitCount _ writeBitCount - codeSize) = 0 |
167 ifTrue: [self nextBytePut: (t2 bitShift: t4)] |
165 ifTrue: [self nextBytePut: (integer bitShift: shiftCount)] |
168 ifFalse: [bufByte := t2 bitShift: t4]. |
166 ifFalse: [bufByte _ integer bitShift: shiftCount]. |
169 ^ t1 |
167 ^anInteger |
170 |
168 |
171 "Modified: 14.10.1997 / 19:20:24 / cg" |
169 "Modified: 15.10.1997 / 16:50:30 / cg" |
172 ! |
170 ! |
173 |
171 |
174 nextBytePut: t1 |
172 nextBytePut: aByte |
175 bufStream nextPut: t1. |
173 bufStream nextPut: aByte. |
176 bufStream size >= 254 ifTrue: [self flushBuffer] |
174 bufStream size >= 254 ifTrue: [self flushBuffer] |
177 |
175 |
178 "Created: 14.10.1997 / 18:40:01 / cg" |
176 "Modified: 15.10.1997 / 16:50:52 / cg" |
179 "Modified: 14.10.1997 / 18:40:36 / cg" |
177 ! |
180 ! |
178 |
181 |
179 readPixelFrom: bits |
182 readPixelFrom: t1 |
180 | pixel | |
183 | t2 | |
|
184 ypos >= height ifTrue: [^ nil]. |
181 ypos >= height ifTrue: [^ nil]. |
185 t2 := t1 at: ypos * rowByteSize + xpos + 1. |
182 pixel := bits at: ypos * rowByteSize + xpos + 1. |
186 self updatePixelPosition. |
183 self updatePixelPosition. |
187 ^ t2 |
184 ^ pixel |
188 |
185 |
189 "Created: 14.10.1997 / 18:43:50 / cg" |
186 "Created: 14.10.1997 / 18:43:50 / cg" |
|
187 "Modified: 15.10.1997 / 16:46:43 / cg" |
190 ! |
188 ! |
191 |
189 |
192 setParameters:bitsPerPixel |
190 setParameters:bitsPerPixel |
193 clearCode := 1 bitShift:bitsPerPixel. |
191 clearCode := 1 bitShift:bitsPerPixel. |
194 eoiCode := clearCode + 1. |
192 eoiCode := clearCode + 1. |
705 |
703 |
706 "Created: 14.10.1997 / 17:40:12 / cg" |
704 "Created: 14.10.1997 / 17:40:12 / cg" |
707 "Modified: 14.10.1997 / 18:59:22 / cg" |
705 "Modified: 14.10.1997 / 18:59:22 / cg" |
708 ! |
706 ! |
709 |
707 |
710 writeBitDataFor:image |
708 writeBitDataFor: image |
711 | t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 | |
709 "using modified Lempel-Ziv Welch algorithm." |
712 |
710 |
713 t1 := image bits. |
711 | bits bitsPerPixel |
714 pass := 0. |
712 maxBits maxMaxCode tSize initCodeSize ent tShift fCode pixel index disp nomatch | |
715 xpos := 0. |
713 |
716 ypos := 0. |
714 bitsPerPixel := image bitsPerPixel. |
717 rowByteSize := width * 8 + 31 // 32 * 4. |
715 bits := image bits. |
718 remainBitCount := 0. |
716 |
719 bufByte := 0. |
717 pass := 0. |
720 bufStream := WriteStream on: (ByteArray new: 256). |
718 xpos := 0. |
721 t2 := 12. |
719 ypos := 0. |
722 t3 := 1 bitShift: t2. |
720 rowByteSize := width * 8 + 31 // 32 * 4. |
723 t4 := 5003. |
721 remainBitCount := 0. |
724 prefixTable := Array new: t4. |
722 bufByte := 0. |
725 suffixTable := Array new: t4. |
723 bufStream := WriteStream on: (ByteArray new: 256). |
726 t5 := image bitsPerPixel <= 1 |
724 |
727 ifTrue: [2] |
725 maxBits := 12. |
728 ifFalse: [image bitsPerPixel]. |
726 maxMaxCode := 1 bitShift: maxBits. |
729 outStream nextPut: t5. "/ codeLen |
727 tSize := 5003. |
730 self setParameters: t5. |
728 prefixTable := Array new: tSize. |
731 t7 := 0. |
729 suffixTable := Array new: tSize. |
732 t8 := t4. |
730 |
733 [t8 < 65536] whileTrue:[ |
731 initCodeSize := bitsPerPixel <= 1 ifTrue: [2] ifFalse: [bitsPerPixel]. |
734 t7 := t7 + 1. |
732 outStream nextPut: initCodeSize. |
735 t8 := t8 * 2 |
733 self setParameters: initCodeSize. |
736 ]. |
734 |
737 t7 := 8 - t7. |
735 tShift := 0. |
738 1 to: t4 do: [:t13 | suffixTable at: t13 put: -1]. |
736 fCode := tSize. |
739 |
737 [fCode < 65536] whileTrue: |
740 self writeCodeAndCheckCodeSize: clearCode. |
738 [tShift := tShift + 1. |
741 t6 := self readPixelFrom: t1. |
739 fCode := fCode * 2]. |
742 [(t9 := self readPixelFrom: t1) == nil] whileFalse:[ |
740 tShift := 8 - tShift. |
743 t8 := (t9 bitShift: t2) + t6. |
741 1 to: tSize do: [:i | suffixTable at: i put: -1]. |
744 t10 := ((t9 bitShift: t7) bitXor: t6) + 1. |
742 |
745 (suffixTable at: t10) = t8 ifTrue: [ |
743 self writeCodeAndCheckCodeSize: clearCode. |
746 t6 := prefixTable at: t10 |
744 ent := self readPixelFrom: bits. |
747 ] ifFalse:[ |
745 [(pixel := self readPixelFrom: bits) == nil] whileFalse: |
748 t12 := true. |
|
749 (suffixTable at: t10) >= 0 ifTrue:[ |
|
750 t11 := t4 - t10 + 1. |
|
751 t10 = 1 ifTrue: [t11 := 1]. |
|
752 |
|
753 [ |
746 [ |
754 (t10 := t10 - t11) < 1 ifTrue: [t10 := t10 + t4]. |
747 fCode := (pixel bitShift: maxBits) + ent. |
755 (suffixTable at: t10) = t8 ifTrue:[ |
748 index := ((pixel bitShift: tShift) bitXor: ent) + 1. |
756 t6 := prefixTable at: t10. |
749 (suffixTable at: index) = fCode |
757 t12 := false |
750 ifTrue: [ent := prefixTable at: index] |
758 ]. |
751 ifFalse: |
759 t12 and: [(suffixTable at: t10) > 0] |
752 [nomatch := true. |
760 ] whileTrue |
753 (suffixTable at: index) >= 0 |
761 ]. |
754 ifTrue: |
762 t12 ifTrue:[ |
755 [disp := tSize - index + 1. |
763 self writeCodeAndCheckCodeSize: t6. |
756 index = 1 ifTrue: [disp := 1]. |
764 t6 := t9. |
757 "probe" |
765 freeCode < t3 ifTrue:[ |
758 [(index := index - disp) < 1 ifTrue: [index := index + tSize]. |
766 prefixTable at: t10 put: freeCode. |
759 (suffixTable at: index) = fCode |
767 suffixTable at: t10 put: t8. |
760 ifTrue: |
768 freeCode := freeCode + 1 |
761 [ent := prefixTable at: index. |
769 ] ifFalse:[ |
762 nomatch := false. |
770 self writeCodeAndCheckCodeSize: clearCode. |
763 "continue whileFalse:"]. |
771 1 to: t4 do: [:t13 | suffixTable at: t13 put: -1]. |
764 nomatch and: [(suffixTable at: index) > 0]] |
772 self setParameters: t5 |
765 whileTrue: ["probe"]]. |
773 ] |
766 "nomatch" |
774 ] |
767 nomatch ifTrue: |
775 ] |
768 [self writeCodeAndCheckCodeSize: ent. |
776 ]. |
769 ent := pixel. |
777 prefixTable := suffixTable := nil. |
770 freeCode < maxMaxCode |
778 self writeCodeAndCheckCodeSize: t6. |
771 ifTrue: |
779 self writeCodeAndCheckCodeSize: eoiCode. |
772 [prefixTable at: index put: freeCode. |
780 self flushCode. |
773 suffixTable at: index put: fCode. |
781 outStream nextPut: 0. |
774 freeCode := freeCode + 1] |
782 outStream nextPut: Terminator |
775 ifFalse: |
783 |
776 [self writeCodeAndCheckCodeSize: clearCode. |
784 "Created: 14.10.1997 / 18:33:54 / cg" |
777 1 to: tSize do: [:i | suffixTable at: i put: -1]. |
785 "Modified: 14.10.1997 / 20:31:11 / cg" |
778 self setParameters: initCodeSize]]]]. |
|
779 prefixTable := suffixTable := nil. |
|
780 self writeCodeAndCheckCodeSize: ent. |
|
781 self writeCodeAndCheckCodeSize: eoiCode. |
|
782 self flushCode. |
|
783 |
|
784 outStream nextPut: 0. "zero-length packet" |
|
785 outStream nextPut: Terminator. |
|
786 |
|
787 "Modified: 15.10.1997 / 16:49:20 / cg" |
786 ! |
788 ! |
787 |
789 |
788 writeHeaderFor:image |
790 writeHeaderFor:image |
789 "save image as GIF file on aFileName" |
791 "save image as GIF file on aFileName" |
790 |
792 |