50 CompuServe Incorporated. GIF(sm) is a Service Mark property of |
50 CompuServe Incorporated. GIF(sm) is a Service Mark property of |
51 CompuServe Incorporated. |
51 CompuServe Incorporated. |
52 " |
52 " |
53 ! ! |
53 ! ! |
54 |
54 |
|
55 !GIFReader class methodsFor:'testing'! |
|
56 |
|
57 isValidImageFile:aFileName |
|
58 "return true, if aFileName contains a GIF image" |
|
59 |
|
60 |id inStream| |
|
61 |
|
62 inStream := FileStream readonlyFileNamed:aFileName. |
|
63 inStream isNil ifTrue:[^ false]. |
|
64 |
|
65 id := String new:6. |
|
66 inStream nextBytes:6 into:id. |
|
67 inStream close. |
|
68 |
|
69 (id = 'GIF87a') ifFalse:[ |
|
70 (id startsWith:'GIF') ifFalse:[^ false]. |
|
71 |
|
72 'not GIF87a - untested' printNewline. |
|
73 ]. |
|
74 ^ true |
|
75 ! ! |
|
76 |
55 !GIFReader methodsFor:'reading from file'! |
77 !GIFReader methodsFor:'reading from file'! |
56 |
78 |
57 fromFile:aFileName |
79 fromFile:aFileName |
58 "read a GIF file" |
80 "read a GIF file" |
59 |
81 |
60 |byte index |
82 |byte index flag count |
61 colorMapSize bitsPerPixel scrWidth scrHeight |
83 colorMapSize bitsPerPixel scrWidth scrHeight |
62 hasColorMap hasLocalColorMap interlaced id |
84 hasColorMap hasLocalColorMap interlaced id |
63 leftOffs topOffs codeLen |
85 leftOffs topOffs codeLen |
64 compressedData compressedSize |
86 compressedData compressedSize |
65 tmp srcOffset dstOffset| |
87 tmp srcOffset dstOffset| |
87 'not a gif87a file - hope that works' printNewline. |
112 'not a gif87a file - hope that works' printNewline. |
88 ]. |
113 ]. |
89 |
114 |
90 "get screen dimensions (not used)" |
115 "get screen dimensions (not used)" |
91 |
116 |
92 scrWidth := self readShort. |
117 scrWidth := inStream nextShortMSB:false. |
93 scrHeight := self readShort. |
118 scrHeight := inStream nextShortMSB:false. |
94 |
119 |
95 "get flag byte" |
120 "get flag byte" |
96 byte := inStream nextByte. |
121 flag := inStream nextByte. |
97 hasColorMap := (byte bitAnd:2r10000000) ~~ 0. |
122 hasColorMap := (flag bitAnd:2r10000000) ~~ 0. |
98 "bitsPerRGB := ((byte bitAnd:2r01110000) bitShift:-4) + 1. " |
123 "bitsPerRGB := ((flag bitAnd:2r01110000) bitShift:-4) + 1. " |
99 "colorMapSorted := ((byte bitAnd:2r00001000) ~~ 0. " |
124 "colorMapSorted := ((flag bitAnd:2r00001000) ~~ 0. " |
100 bitsPerPixel := (byte bitAnd:2r00000111) + 1. |
125 bitsPerPixel := (flag bitAnd:2r00000111) + 1. |
101 colorMapSize := 1 bitShift:bitsPerPixel. |
126 colorMapSize := 1 bitShift:bitsPerPixel. |
102 |
127 |
103 "get background (not used)" |
128 "get background (not used)" |
104 byte := inStream nextByte. |
129 inStream nextByte. |
105 |
130 |
106 "aspect ratio" |
131 "aspect ratio (not used)" |
107 byte := inStream nextByte. |
132 inStream nextByte. |
108 |
133 |
109 "get colorMap" |
134 "get colorMap" |
110 hasColorMap ifTrue:[ |
135 hasColorMap ifTrue:[ |
111 self readColorMap:colorMapSize |
136 self readColorMap:colorMapSize |
112 ]. |
137 ]. |
117 'corrupted gif file (no imgSep)' printNewline. |
142 'corrupted gif file (no imgSep)' printNewline. |
118 ^ nil |
143 ^ nil |
119 ]. |
144 ]. |
120 |
145 |
121 "get image data" |
146 "get image data" |
122 leftOffs := self readShort. |
147 leftOffs := inStream nextShortMSB:false. |
123 topOffs := self readShort. |
148 topOffs := inStream nextShortMSB:false. |
124 width := self readShort. |
149 width := inStream nextShortMSB:false. |
125 height := self readShort. |
150 height := inStream nextShortMSB:false. |
126 |
151 |
127 'width ' print. width printNewline. |
152 'width ' print. width printNewline. |
128 'height ' print. height printNewline. |
153 'height ' print. height printNewline. |
129 |
154 |
130 byte := inStream nextByte. |
155 "another flag byte" |
131 interlaced := (byte bitAnd:2r01000000) ~~ 0. |
156 flag := inStream nextByte. |
132 hasLocalColorMap := (byte bitAnd:2r10000000) ~~ 0. |
157 interlaced := (flag bitAnd:2r01000000) ~~ 0. |
133 "localColorMapSorted := (byte bitAnd:2r00100000) ~~ 0. " |
158 hasLocalColorMap := (flag bitAnd:2r10000000) ~~ 0. |
|
159 "localColorMapSorted := (flag bitAnd:2r00100000) ~~ 0. " |
|
160 |
|
161 "if image has a local colormap, this one is used" |
134 |
162 |
135 hasLocalColorMap ifTrue:[ |
163 hasLocalColorMap ifTrue:[ |
136 "local descr. overwrites" |
164 "local descr. overwrites" |
137 bitsPerPixel := (byte bitAnd:2r00000111) + 1. |
165 bitsPerPixel := (flag bitAnd:2r00000111) + 1. |
138 colorMapSize := 1 bitShift:bitsPerPixel. |
166 colorMapSize := 1 bitShift:bitsPerPixel. |
139 " 'local colormap' printNewline. " |
167 " 'local colormap' printNewline. " |
140 "overwrite colormap" |
168 "overwrite colormap" |
141 self readColorMap:colorMapSize |
169 self readColorMap:colorMapSize |
142 ]. |
170 ]. |
143 |
171 |
|
172 "get codelen for decompression" |
144 codeLen := inStream nextByte. |
173 codeLen := inStream nextByte. |
145 |
174 |
146 compressedData := ByteArray uninitializedNew:(inStream size). |
175 compressedData := ByteArray uninitializedNew:(inStream size). |
147 |
176 |
|
177 "get compressed data" |
148 index := 1. |
178 index := 1. |
149 byte := inStream nextByte. |
179 count := inStream nextByte. |
150 [byte notNil and:[byte ~~ 0]] whileTrue:[ |
180 [count notNil and:[count ~~ 0]] whileTrue:[ |
151 inStream nextBytes:byte into:compressedData startingAt:index. |
181 inStream nextBytes:count into:compressedData startingAt:index. |
152 index := index + byte. |
182 index := index + count. |
153 byte := inStream nextByte |
183 count := inStream nextByte |
154 ]. |
184 ]. |
155 compressedSize := index - 1. |
185 compressedSize := index - 1. |
156 inStream close. |
186 inStream close. |
157 |
187 |
158 data := ByteArray uninitializedNew:((width + 1) * (height + 1)). |
188 data := ByteArray uninitializedNew:((width + 1) * (height + 1)). |
209 ]. |
240 ]. |
210 |
241 |
211 photometric := #palette. |
242 photometric := #palette. |
212 samplesPerPixel := 1. |
243 samplesPerPixel := 1. |
213 bitsPerSample := #(8). |
244 bitsPerSample := #(8). |
|
245 |
|
246 "check if only grey values are used, |
|
247 could make it a greyscale image if so (currently not done)" |
|
248 |
|
249 self checkGreyscaleColormap ifTrue:[ |
|
250 self makeGreyscale |
|
251 ]. |
|
252 |
214 colorMap := Array with:redMap with:greenMap with:blueMap. |
253 colorMap := Array with:redMap with:greenMap with:blueMap. |
215 |
254 |
216 "GIFReader fromFile:'../fileIn/bitmaps/claus.gif" |
255 "GIFReader fromFile:'../fileIn/bitmaps/claus.gif" |
217 "GIFReader fromFile:'../fileIn/bitmaps/garfield.gif'" |
256 "GIFReader fromFile:'../fileIn/bitmaps/garfield.gif'" |
218 ! |
257 ! |
219 |
258 |
220 readColorMap:colorMapSize |
259 readColorMap:colorMapSize |
221 redMap := Array new:colorMapSize. |
260 "get gif colormap consisting of colorMapSize entries" |
222 greenMap := Array new:colorMapSize. |
261 |
223 blueMap := Array new:colorMapSize. |
262 redMap := Array new:colorMapSize. |
224 1 to:colorMapSize do:[:i | |
263 greenMap := Array new:colorMapSize. |
225 redMap at:i put:(inStream nextByte). |
264 blueMap := Array new:colorMapSize. |
226 greenMap at:i put:(inStream nextByte). |
265 1 to:colorMapSize do:[:i | |
227 blueMap at:i put:(inStream nextByte) |
266 redMap at:i put:(inStream nextByte). |
228 ] |
267 greenMap at:i put:(inStream nextByte). |
|
268 blueMap at:i put:(inStream nextByte) |
|
269 ] |
|
270 ! |
|
271 |
|
272 checkGreyscaleColormap |
|
273 "return true, if colormap is really a greymap" |
|
274 |
|
275 1 to:redMap size do:[:i | |
|
276 (redMap at:i) ~~ (greenMap at:i) ifTrue:[^ false]. |
|
277 (redMap at:i) ~~ (blueMap at:i) ifTrue:[^ false]. |
|
278 ]. |
|
279 ^ true |
|
280 ! |
|
281 |
|
282 makeGreyscale |
|
283 "not yet implemented/needed" |
229 ! ! |
284 ! ! |