16 "{ NameSpace: Smalltalk }" |
14 "{ NameSpace: Smalltalk }" |
17 |
15 |
18 ImageReader subclass:#PNGReader |
16 ImageReader subclass:#PNGReader |
19 instanceVariableNames:'colorType bitsPerChannel depth compressionMethod filterMethod |
17 instanceVariableNames:'colorType bitsPerChannel depth compressionMethod filterMethod |
20 interlaceMode bytesPerScanline globalDataChunk thisScanline |
18 interlaceMode bytesPerScanline globalDataChunk thisScanline |
21 prevScanline' |
19 prevScanline processTextChunks' |
22 classVariableNames:'Verbose' |
20 classVariableNames:'Verbose' |
23 poolDictionaries:'' |
21 poolDictionaries:'' |
24 category:'Graphics-Images-Readers' |
22 category:'Graphics-Images-Readers' |
25 ! |
23 ! |
26 |
24 |
213 type = 'pHYs' ifTrue:[^ self processPHYSChunkLen:len]. |
211 type = 'pHYs' ifTrue:[^ self processPHYSChunkLen:len]. |
214 type = 'cHRM' ifTrue:[^ self processCHRMChunkLen:len]. |
212 type = 'cHRM' ifTrue:[^ self processCHRMChunkLen:len]. |
215 type = 'tRNS' ifTrue:[^ self processTRNSChunkLen:len]. |
213 type = 'tRNS' ifTrue:[^ self processTRNSChunkLen:len]. |
216 type = 'IHDR' ifTrue:[^ self processIHDRChunkLen:len]. |
214 type = 'IHDR' ifTrue:[^ self processIHDRChunkLen:len]. |
217 |
215 |
|
216 type = 'iTXt' ifTrue:[^ self processITXTChunkLen:len]. |
|
217 type = 'iCCP' ifTrue:[^ self processICCPChunkLen:len]. |
|
218 |
218 ('PNGReader: unrecognized chunk: ' , type , ' ignored.') infoPrintCR. |
219 ('PNGReader: unrecognized chunk: ' , type , ' ignored.') infoPrintCR. |
219 |
220 |
220 inStream skip:len. |
221 inStream skip:len. |
221 ^ true. |
222 ^ true. |
222 |
223 |
236 ^ self processNonInterlacedGlobalDATA |
237 ^ self processNonInterlacedGlobalDATA |
237 ]. |
238 ]. |
238 ^ self processInterlacedGlobalDATA |
239 ^ self processInterlacedGlobalDATA |
239 ! |
240 ! |
240 |
241 |
|
242 processICCPChunkLen:len |
|
243 "/ ignored |
|
244 "/ inStream nextBytes:len. |
|
245 |
|
246 inStream skip:len. |
|
247 ^ true |
|
248 |
|
249 "Created: 21.6.1996 / 21:15:58 / cg" |
|
250 ! |
|
251 |
241 processIDATChunkLen:len |
252 processIDATChunkLen:len |
242 interlaceMode == 0 ifTrue: [ |
253 interlaceMode == 0 ifTrue: [ |
243 ^ self processNonInterlacedDATA:len |
254 ^ self processNonInterlacedDATA:len |
244 ]. |
255 ]. |
245 ^ self processInterlacedDATA:len |
256 ^ self processInterlacedDATA:len |
|
257 ! |
|
258 |
|
259 processIHDRChunkLen:len |
|
260 "/ ignored |
|
261 |
|
262 inStream skip:len. |
|
263 ^ true |
|
264 |
|
265 "Created: 21.6.1996 / 21:15:58 / cg" |
|
266 ! |
|
267 |
|
268 processITXTChunkLen:len |
|
269 "/ international (i.e.utf8) textual data. |
|
270 |
|
271 "/ currently ignored - not needed to display png images |
|
272 "/ |
|
273 "/ Keyword: 1-79 bytes (character string) |
|
274 "/ Null separator: 1 byte |
|
275 "/ Compression flag: 1 byte |
|
276 "/ Compression method: 1 byte |
|
277 "/ Language tag: 0 or more bytes (character string) |
|
278 "/ Null separator: 1 byte |
|
279 "/ Translated keyword: 0 or more bytes |
|
280 "/ Null separator: 1 byte |
|
281 "/ Text: 0 or more bytes |
|
282 |
|
283 "/ if needed, set processTextChunks to true somewhere... |
|
284 processTextChunks == true ifTrue:[ |
|
285 |chunkData keyword text i1 i2 i3 |
|
286 compressionFlag compressionMethod languageTag |
|
287 xlatedKeyword textBytes| |
|
288 |
|
289 chunkData := inStream nextBytes:len. |
|
290 i1 := chunkData indexOf:0. |
|
291 keyword := (chunkData copyTo:i1-1) asString. |
|
292 compressionFlag := chunkData at:i1+1. |
|
293 compressionMethod := chunkData at:i1+2. |
|
294 i2 := chunkData indexOf:0 startingAt:i1+3. |
|
295 languageTag := (chunkData copyFrom:i1+3 to:i2-1) asString. |
|
296 i3 := chunkData indexOf:0 startingAt:i2+1. |
|
297 xlatedKeyword := (chunkData copyFrom:i2+1 to:i3-1) asString. |
|
298 textBytes := chunkData copyFrom:i3+1. |
|
299 compressionFlag == 0 ifTrue:[ |
|
300 text := textBytes |
|
301 ] ifFalse:[ |
|
302 compressionFlag == 1 ifTrue:[ |
|
303 "/ for now, only zlib compression is supported... |
|
304 'zlib compression currently unsupported' infoPrintCR. |
|
305 ] ifFalse:[ |
|
306 'unsupported compression method' infoPrintCR. |
|
307 ]. |
|
308 ]. |
|
309 text := text utf8Decoded. |
|
310 self handleText:text keyword:keyword. |
|
311 ] ifFalse:[ |
|
312 inStream skip:len. |
|
313 ]. |
|
314 ^ true |
|
315 |
|
316 "Created: 21.6.1996 / 21:15:58 / cg" |
246 ! |
317 ! |
247 |
318 |
248 processInterlacedDATA:len |
319 processInterlacedDATA:len |
249 inStream skip:len. |
320 inStream skip:len. |
250 ^ true |
321 ^ true |
423 ^ true |
494 ^ true |
424 |
495 |
425 "Created: 21.6.1996 / 21:13:09 / cg" |
496 "Created: 21.6.1996 / 21:13:09 / cg" |
426 ! |
497 ! |
427 |
498 |
428 processTEXTChunkLen:len |
499 processTEXTChunkLen:len |
429 inStream skip:len. |
500 "/ textual data in iso8859 coding. |
|
501 |
|
502 "/ currently ignored - not needed to display png images |
|
503 "/ Keyword: 1-79 bytes (character string) |
|
504 "/ Null separator: 1 byte |
|
505 "/ Text: n bytes (character string) |
|
506 |
|
507 "/ if needed, set processTextChunks to true somewhere... |
|
508 processTextChunks == true ifTrue:[ |
|
509 |chunkData keyword text i| |
|
510 |
|
511 chunkData := inStream nextBytes:len. |
|
512 i := chunkData indexOf:0. |
|
513 keyword := (chunkData copyTo:i-1) asString. |
|
514 text := (chunkData copyFrom:i+1) asString. |
|
515 self handleText:text keyword:keyword. |
|
516 ] ifFalse:[ |
|
517 inStream skip:len. |
|
518 ]. |
430 ^ true |
519 ^ true |
431 |
520 |
432 "Modified: 21.6.1996 / 21:15:27 / cg" |
521 "Modified: 21.6.1996 / 21:15:27 / cg" |
433 ! |
522 ! |
434 |
523 |
919 ^ true |
1011 ^ true |
920 |
1012 |
921 "Modified: 21.6.1996 / 21:38:35 / cg" |
1013 "Modified: 21.6.1996 / 21:38:35 / cg" |
922 ! |
1014 ! |
923 |
1015 |
|
1016 handleText:text keyword:keyword |
|
1017 "/ things like exif data etc. |
|
1018 "/ self halt. |
|
1019 |
|
1020 "/Standard keywords for text chunks: |
|
1021 "/ |
|
1022 "/ Title Short (one line) title or caption for image |
|
1023 "/ Author Name of image's creator |
|
1024 "/ Description Description of image (possibly long) |
|
1025 "/ Copyright Copyright notice |
|
1026 "/ Creation Time Time of original image creation |
|
1027 "/ Software Software used to create the image |
|
1028 "/ Disclaimer Legal disclaimer |
|
1029 "/ Warning Warning of nature of content |
|
1030 "/ Source Device used to create the image |
|
1031 "/ Comment Miscellaneous comment; conversion from |
|
1032 "/ GIF comment |
|
1033 ! |
|
1034 |
924 setColorType:colorType |
1035 setColorType:colorType |
925 colorType == 0 ifTrue:[ |
1036 colorType == 0 ifTrue:[ |
926 photometric := #blackIs0. |
1037 photometric := #blackIs0. |
927 samplesPerPixel := 1. |
1038 samplesPerPixel := 1. |
928 bitsPerSample := Array with:bitsPerChannel. |
1039 bitsPerSample := Array with:bitsPerChannel. |