279 |
279 |
280 whiteCountTable = (short *) malloc(sizeof(short) * 8192); |
280 whiteCountTable = (short *) malloc(sizeof(short) * 8192); |
281 if (! whiteCountTable) return; |
281 if (! whiteCountTable) return; |
282 whiteShiftTable = (char *) malloc(sizeof(char) * 8192); |
282 whiteShiftTable = (char *) malloc(sizeof(char) * 8192); |
283 if (! whiteShiftTable) { |
283 if (! whiteShiftTable) { |
284 goto fail1; |
284 goto fail1; |
285 } |
285 } |
286 blackCountTable = (short *) malloc(sizeof(short) * 8192); |
286 blackCountTable = (short *) malloc(sizeof(short) * 8192); |
287 if (! blackCountTable) { |
287 if (! blackCountTable) { |
288 goto fail2; |
288 goto fail2; |
289 } |
289 } |
290 blackShiftTable = (char *) malloc(sizeof(char) * 8192); |
290 blackShiftTable = (char *) malloc(sizeof(char) * 8192); |
291 if (! blackShiftTable) { |
291 if (! blackShiftTable) { |
292 free(blackCountTable); blackCountTable = (short *)0; |
292 free(blackCountTable); blackCountTable = (short *)0; |
293 fail2: |
293 fail2: |
294 free(whiteShiftTable); whiteShiftTable = (char *)0; |
294 free(whiteShiftTable); whiteShiftTable = (char *)0; |
295 fail1: |
295 fail1: |
296 free(whiteCountTable); whiteCountTable = (short *)0; |
296 free(whiteCountTable); whiteCountTable = (short *)0; |
297 return; |
297 return; |
298 } |
298 } |
299 |
299 |
300 for (index = 0; index < 8192; index++) { |
300 for (index = 0; index < 8192; index++) { |
301 whiteCountTable[index] = -1; |
301 whiteCountTable[index] = -1; |
302 blackCountTable[index] = -1; |
302 blackCountTable[index] = -1; |
303 } |
303 } |
304 |
304 |
305 for (value = 0; value <= 63; value++) { |
305 for (value = 0; value <= 63; value++) { |
306 nBits = whiteDef[value].nBits; |
306 nBits = whiteDef[value].nBits; |
307 bits = whiteDef[value].bits >> 3; |
307 bits = whiteDef[value].bits >> 3; |
308 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
308 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
309 whiteCountTable[bits] = value; |
309 whiteCountTable[bits] = value; |
310 whiteShiftTable[bits] = nBits; |
310 whiteShiftTable[bits] = nBits; |
311 } |
311 } |
312 nBits = blackDef[value].nBits; |
312 nBits = blackDef[value].nBits; |
313 bits = blackDef[value].bits >> 3; |
313 bits = blackDef[value].bits >> 3; |
314 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
314 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
315 blackCountTable[bits] = value; |
315 blackCountTable[bits] = value; |
316 blackShiftTable[bits] = nBits; |
316 blackShiftTable[bits] = nBits; |
317 } |
317 } |
318 } |
318 } |
319 index = value; |
319 index = value; |
320 |
320 |
321 for (; value <= 1728; value += 64) { |
321 for (; value <= 1728; value += 64) { |
322 nBits = whiteDef[index].nBits; |
322 nBits = whiteDef[index].nBits; |
323 bits = whiteDef[index].bits >> 3; |
323 bits = whiteDef[index].bits >> 3; |
324 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
324 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
325 whiteCountTable[bits] = value; |
325 whiteCountTable[bits] = value; |
326 whiteShiftTable[bits] = nBits; |
326 whiteShiftTable[bits] = nBits; |
327 } |
327 } |
328 nBits = blackDef[index].nBits; |
328 nBits = blackDef[index].nBits; |
329 bits = blackDef[index].bits >> 3; |
329 bits = blackDef[index].bits >> 3; |
330 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
330 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
331 blackCountTable[bits] = value; |
331 blackCountTable[bits] = value; |
332 blackShiftTable[bits] = nBits; |
332 blackShiftTable[bits] = nBits; |
333 } |
333 } |
334 index++; |
334 index++; |
335 } |
335 } |
336 |
336 |
337 for (; value <= 2560; value += 64) { |
337 for (; value <= 2560; value += 64) { |
338 nBits = whiteDef[index].nBits; |
338 nBits = whiteDef[index].nBits; |
339 bits = whiteDef[index].bits >> 3; |
339 bits = whiteDef[index].bits >> 3; |
340 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
340 for (cnt = 1 << (13 - nBits); cnt; cnt--, bits++) { |
341 whiteCountTable[bits] = value; |
341 whiteCountTable[bits] = value; |
342 whiteShiftTable[bits] = nBits; |
342 whiteShiftTable[bits] = nBits; |
343 blackCountTable[bits] = value; |
343 blackCountTable[bits] = value; |
344 blackShiftTable[bits] = nBits; |
344 blackShiftTable[bits] = nBits; |
345 } |
345 } |
346 index++; |
346 index++; |
347 } |
347 } |
348 } |
348 } |
349 |
349 |
350 static short |
350 static short |
351 leftBits[] = { |
351 leftBits[] = { |
374 outBitOffset = 0; |
374 outBitOffset = 0; |
375 bits = *from++; |
375 bits = *from++; |
376 bits = (bits << 8) | *from++; |
376 bits = (bits << 8) | *from++; |
377 nBitsLess13 = 3; |
377 nBitsLess13 = 3; |
378 for (;;) { |
378 for (;;) { |
379 bits13 = (bits >> nBitsLess13) & 0x1FFF; |
379 bits13 = (bits >> nBitsLess13) & 0x1FFF; |
380 cnt = countPtr[bits13]; |
380 cnt = countPtr[bits13]; |
381 if (cnt < 0) return 1; |
381 if (cnt < 0) return 1; |
382 shift = shiftPtr[bits13]; |
382 shift = shiftPtr[bits13]; |
383 outCount += cnt; |
383 outCount += cnt; |
384 if (countPtr == blackCountTable) { |
384 if (countPtr == blackCountTable) { |
385 /* toggle if it was a terminating code */ |
385 /* toggle if it was a terminating code */ |
386 if (cnt < 64) { |
386 if (cnt < 64) { |
387 countPtr = whiteCountTable; |
387 countPtr = whiteCountTable; |
388 shiftPtr = whiteShiftTable; |
388 shiftPtr = whiteShiftTable; |
389 } |
389 } |
390 |
390 |
391 /* draw cnt black bits */ |
391 /* draw cnt black bits */ |
392 if (cnt) { |
392 if (cnt) { |
393 if (outBitOffset) { |
393 if (outBitOffset) { |
394 nLeft = 8 - outBitOffset; |
394 nLeft = 8 - outBitOffset; |
395 if (cnt < nLeft) nLeft = cnt; |
395 if (cnt < nLeft) nLeft = cnt; |
396 t = leftBits[nLeft] >> outBitOffset; |
396 t = leftBits[nLeft] >> outBitOffset; |
397 *to |= t; |
397 *to |= t; |
398 cnt -= nLeft; |
398 cnt -= nLeft; |
399 outBitOffset += nLeft; |
399 outBitOffset += nLeft; |
400 if (outBitOffset >= 8) { |
400 if (outBitOffset >= 8) { |
401 to++; |
401 to++; |
402 outBitOffset -= 8; |
402 outBitOffset -= 8; |
403 } |
403 } |
404 } |
404 } |
405 if (cnt > 256) { |
405 if (cnt > 256) { |
406 while ((INT)to & 3) { |
406 while ((INT)to & 3) { |
407 *to++ = 0xFF; |
407 *to++ = 0xFF; |
408 cnt -= 8; |
408 cnt -= 8; |
409 } |
409 } |
410 #if __POINTER_SIZE__ == 8 |
410 #if __POINTER_SIZE__ == 8 |
411 while ((INT)to & 7) { |
411 while ((INT)to & 7) { |
412 *to++ = 0xFF; |
412 *to++ = 0xFF; |
413 cnt -= 8; |
413 cnt -= 8; |
414 } |
414 } |
415 while (cnt >= 64) { |
415 while (cnt >= 64) { |
416 (*(INT *)to) = 0xFFFFFFFFFFFFFFFF; |
416 (*(INT *)to) = 0xFFFFFFFFFFFFFFFF; |
417 to += 8; |
417 to += 8; |
418 cnt -= 64; |
418 cnt -= 64; |
419 } |
419 } |
420 if (cnt >= 32) { |
420 if (cnt >= 32) { |
421 (*(long *)to) = 0xFFFFFFFF; |
421 (*(long *)to) = 0xFFFFFFFF; |
422 to += 4; |
422 to += 4; |
423 cnt -= 32; |
423 cnt -= 32; |
424 } |
424 } |
425 #else |
425 #else |
426 while ((INT)to & 3) { |
426 while ((INT)to & 3) { |
427 *to++ = 0xFF; |
427 *to++ = 0xFF; |
428 cnt -= 8; |
428 cnt -= 8; |
429 } |
429 } |
430 while (cnt >= 32) { |
430 while (cnt >= 32) { |
431 (*(long *)to) = 0xFFFFFFFF; |
431 (*(long *)to) = 0xFFFFFFFF; |
432 to += 4; |
432 to += 4; |
433 cnt -= 32; |
433 cnt -= 32; |
434 } |
434 } |
435 #endif |
435 #endif |
436 } |
436 } |
437 while (cnt >= 8) { |
437 while (cnt >= 8) { |
438 *to++ = 0xFF; |
438 *to++ = 0xFF; |
439 cnt -= 8; |
439 cnt -= 8; |
440 } |
440 } |
441 *to |= leftBits[cnt]; |
441 *to |= leftBits[cnt]; |
442 outBitOffset += cnt; |
442 outBitOffset += cnt; |
443 } |
443 } |
444 } else { |
444 } else { |
445 /* toggle if it was a terminating code */ |
445 /* toggle if it was a terminating code */ |
446 if (cnt < 64) { |
446 if (cnt < 64) { |
447 countPtr = blackCountTable; |
447 countPtr = blackCountTable; |
448 shiftPtr = blackShiftTable; |
448 shiftPtr = blackShiftTable; |
449 } |
449 } |
450 |
450 |
451 /* skip cnt bits */ |
451 /* skip cnt bits */ |
452 to += cnt >> 3; |
452 to += cnt >> 3; |
453 outBitOffset += cnt & 7; |
453 outBitOffset += cnt & 7; |
454 if (outBitOffset >= 8) { |
454 if (outBitOffset >= 8) { |
455 to++; |
455 to++; |
456 outBitOffset -= 8; |
456 outBitOffset -= 8; |
457 } |
457 } |
458 } |
458 } |
459 if (outCount >= len) return 1; |
459 if (outCount >= len) return 1; |
460 |
460 |
461 nBitsLess13 -= shift; |
461 nBitsLess13 -= shift; |
462 while (nBitsLess13 < 0) { |
462 while (nBitsLess13 < 0) { |
463 bits = (bits << 8) | *from++; |
463 bits = (bits << 8) | *from++; |
464 nBitsLess13 += 8; |
464 nBitsLess13 += 8; |
465 } |
465 } |
466 } |
466 } |
467 } |
467 } |
468 |
468 |
469 /* |
469 /* |
470 * LZW decompression |
470 * LZW decompression |
471 */ |
471 */ |
472 struct buffer { |
472 struct buffer { |
473 struct buffer *prev; |
473 struct buffer *prev; |
474 unsigned char chars[8192 - 4]; |
474 unsigned char chars[8192 - 4]; |
475 }; |
475 }; |
476 |
476 |
477 static int |
477 static int |
478 __decodeLZW__(from, to, inCount, fromSize, toSize) |
478 __decodeLZW__(from, to, inCount, fromSize, toSize) |
479 unsigned char *from; |
479 unsigned char *from; |
502 scratchBuffer = (struct buffer *)malloc(sizeof(struct buffer)); |
502 scratchBuffer = (struct buffer *)malloc(sizeof(struct buffer)); |
503 if (! scratchBuffer) return 0; |
503 if (! scratchBuffer) return 0; |
504 |
504 |
505 strings = (unsigned char **)malloc(sizeof(unsigned char *) * 4096); |
505 strings = (unsigned char **)malloc(sizeof(unsigned char *) * 4096); |
506 if (! strings) { |
506 if (! strings) { |
507 free(scratchBuffer); |
507 free(scratchBuffer); |
508 return 0; |
508 return 0; |
509 } |
509 } |
510 stringLen = (short *)malloc(sizeof(short) * 4096); |
510 stringLen = (short *)malloc(sizeof(short) * 4096); |
511 if (! stringLen) { |
511 if (! stringLen) { |
512 free(strings); |
512 free(strings); |
513 free(scratchBuffer); |
513 free(scratchBuffer); |
514 return 0; |
514 return 0; |
515 } |
515 } |
516 |
516 |
517 scratchBuffer->prev = (struct buffer *)0; |
517 scratchBuffer->prev = (struct buffer *)0; |
518 scratchPtr = scratchBuffer->chars; |
518 scratchPtr = scratchBuffer->chars; |
519 nScratch = sizeof(scratchBuffer->chars); |
519 nScratch = sizeof(scratchBuffer->chars); |
520 |
520 |
521 for (i = 0; i < 256; i++) { |
521 for (i = 0; i < 256; i++) { |
522 *scratchPtr = i; |
522 *scratchPtr = i; |
523 strings[i] = scratchPtr++; |
523 strings[i] = scratchPtr++; |
524 stringLen[i] = 1; |
524 stringLen[i] = 1; |
525 } |
525 } |
526 |
526 |
527 nextCode = 258; |
527 nextCode = 258; |
528 nScratch -= 256; |
528 nScratch -= 256; |
529 mask = 0x1FF; |
529 mask = 0x1FF; |
530 nBits = 0; |
530 nBits = 0; |
531 bits = 0; |
531 bits = 0; |
532 while (inCount) { |
532 while (inCount) { |
533 /* fetch code */ |
533 /* fetch code */ |
534 while (nBits < codeLen) { |
534 while (nBits < codeLen) { |
535 bits = (bits<<8) | *from++; |
535 bits = (bits<<8) | *from++; |
536 inCount--; |
536 inCount--; |
537 nBits += 8; |
537 nBits += 8; |
538 } |
538 } |
539 shift = nBits - codeLen; |
539 shift = nBits - codeLen; |
540 code = (bits >> shift) & mask; |
540 code = (bits >> shift) & mask; |
541 bits &= ~(mask << shift); |
541 bits &= ~(mask << shift); |
542 nBits -= codeLen; |
542 nBits -= codeLen; |
543 |
543 |
544 if (code == 257) break; |
544 if (code == 257) break; |
545 if (code == 256) { |
545 if (code == 256) { |
546 if (! inCount) |
546 if (! inCount) |
547 break; |
547 break; |
548 |
548 |
549 /* free stuff */ |
549 /* free stuff */ |
550 while (scratchBuffer->prev) { |
550 while (scratchBuffer->prev) { |
551 newBuffer = scratchBuffer; |
551 newBuffer = scratchBuffer; |
552 scratchBuffer = scratchBuffer->prev; |
552 scratchBuffer = scratchBuffer->prev; |
553 free(newBuffer); |
553 free(newBuffer); |
554 } |
554 } |
555 /* reset everything */ |
555 /* reset everything */ |
556 scratchPtr = scratchBuffer->chars + 256; |
556 scratchPtr = scratchBuffer->chars + 256; |
557 nScratch = sizeof(scratchBuffer->chars) - 256; |
557 nScratch = sizeof(scratchBuffer->chars) - 256; |
558 codeLen = 9; |
558 codeLen = 9; |
559 nextCode = 258; |
559 nextCode = 258; |
560 mask = 0x1FF; |
560 mask = 0x1FF; |
561 /* fetch code */ |
561 /* fetch code */ |
562 while (nBits < codeLen) { |
562 while (nBits < codeLen) { |
563 bits = (bits<<8) | *from++; |
563 bits = (bits<<8) | *from++; |
564 inCount--; |
564 inCount--; |
565 nBits += 8; |
565 nBits += 8; |
566 } |
566 } |
567 shift = nBits - codeLen; |
567 shift = nBits - codeLen; |
568 code = (bits >> shift) & mask; |
568 code = (bits >> shift) & mask; |
569 bits &= ~(mask << shift); |
569 bits &= ~(mask << shift); |
570 nBits -= codeLen; |
570 nBits -= codeLen; |
571 if (code == 257) break; |
571 if (code == 257) break; |
572 /* add to output */ |
572 /* add to output */ |
573 if (to >= toEnd) { |
573 if (to >= toEnd) { |
574 if (@global(InfoPrinting) == true) { |
574 if (@global(InfoPrinting) == true) { |
575 console_fprintf(stderr, "ImageReader [warning]: LZW outBuffer overrun\n"); |
575 console_fprintf(stderr, "ImageReader [warning]: LZW outBuffer overrun\n"); |
576 } |
576 } |
577 ret = 0; |
577 ret = 0; |
578 break; |
578 break; |
579 } |
579 } |
580 *to++ = code; |
580 *to++ = code; |
581 oldCode = code; |
581 oldCode = code; |
582 } else { |
582 } else { |
583 if (code < nextCode) { |
583 if (code < nextCode) { |
584 /* writeString(string[code]) */ |
584 /* writeString(string[code]) */ |
585 len = stringLen[code]; |
585 len = stringLen[code]; |
586 bcopy(strings[code], to, len); |
586 bcopy(strings[code], to, len); |
587 to += len; |
587 to += len; |
588 |
588 |
589 if (oldCode != -1) { |
589 if (oldCode != -1) { |
590 /* add( string[oldcode] + first(string[code]) ) */ |
590 /* add( string[oldcode] + first(string[code]) ) */ |
591 len = stringLen[oldCode] + 1; |
591 len = stringLen[oldCode] + 1; |
592 if (nScratch < len) { |
592 if (nScratch < len) { |
593 newBuffer = (struct buffer *)malloc(sizeof(struct buffer)); |
593 newBuffer = (struct buffer *)malloc(sizeof(struct buffer)); |
594 if (! newBuffer) goto out; |
594 if (! newBuffer) goto out; |
595 newBuffer->prev = scratchBuffer; |
595 newBuffer->prev = scratchBuffer; |
596 scratchBuffer = newBuffer; |
596 scratchBuffer = newBuffer; |
597 scratchPtr = scratchBuffer->chars; |
597 scratchPtr = scratchBuffer->chars; |
598 nScratch = sizeof(scratchBuffer->chars); |
598 nScratch = sizeof(scratchBuffer->chars); |
599 } |
599 } |
600 stringLen[nextCode] = len; |
600 stringLen[nextCode] = len; |
601 strings[nextCode] = scratchPtr; |
601 strings[nextCode] = scratchPtr; |
602 bcopy(strings[oldCode], scratchPtr, len-1); |
602 bcopy(strings[oldCode], scratchPtr, len-1); |
603 scratchPtr += len-1; |
603 scratchPtr += len-1; |
604 *scratchPtr++ = strings[code][0]; |
604 *scratchPtr++ = strings[code][0]; |
605 nScratch -= len; |
605 nScratch -= len; |
606 nextCode++; |
606 nextCode++; |
607 } |
607 } |
608 } else { |
608 } else { |
609 if (oldCode == -1) { |
609 if (oldCode == -1) { |
610 /* bad input */ |
610 /* bad input */ |
611 ret = 0; |
611 ret = 0; |
612 goto out; |
612 goto out; |
613 } |
613 } |
614 |
614 |
615 /* writeString(string[oldCode] + first(string[oldCode]) ) */ |
615 /* writeString(string[oldCode] + first(string[oldCode]) ) */ |
616 len = stringLen[oldCode]; |
616 len = stringLen[oldCode]; |
617 if ((to+len) >= toEnd) { |
617 if ((to+len) >= toEnd) { |
618 if (@global(InfoPrinting) == true) { |
618 if (@global(InfoPrinting) == true) { |
619 console_fprintf(stderr, "ImageReader [warning]: LZW outBuffer overrun\n"); |
619 console_fprintf(stderr, "ImageReader [warning]: LZW outBuffer overrun\n"); |
620 } |
620 } |
621 ret = 0; |
621 ret = 0; |
622 goto out; |
622 goto out; |
623 } |
623 } |
624 bcopy(strings[oldCode], to, len); |
624 bcopy(strings[oldCode], to, len); |
625 to += len; |
625 to += len; |
626 *to++ = strings[oldCode][0]; |
626 *to++ = strings[oldCode][0]; |
627 |
627 |
628 /* add( string[oldcode] + first(string[oldCode]) ) */ |
628 /* add( string[oldcode] + first(string[oldCode]) ) */ |
629 len++; |
629 len++; |
630 if (nScratch < len) { |
630 if (nScratch < len) { |
631 newBuffer = (struct buffer *)malloc(sizeof(struct buffer)); |
631 newBuffer = (struct buffer *)malloc(sizeof(struct buffer)); |
632 if (! newBuffer) goto out; |
632 if (! newBuffer) goto out; |
633 newBuffer->prev = scratchBuffer; |
633 newBuffer->prev = scratchBuffer; |
634 scratchBuffer = newBuffer; |
634 scratchBuffer = newBuffer; |
635 scratchPtr = scratchBuffer->chars; |
635 scratchPtr = scratchBuffer->chars; |
636 nScratch = sizeof(scratchBuffer->chars); |
636 nScratch = sizeof(scratchBuffer->chars); |
637 } |
637 } |
638 stringLen[nextCode] = len; |
638 stringLen[nextCode] = len; |
639 strings[nextCode] = scratchPtr; |
639 strings[nextCode] = scratchPtr; |
640 bcopy(strings[oldCode], scratchPtr, len-1); |
640 bcopy(strings[oldCode], scratchPtr, len-1); |
641 scratchPtr += len-1; |
641 scratchPtr += len-1; |
642 *scratchPtr++ = strings[oldCode][0]; |
642 *scratchPtr++ = strings[oldCode][0]; |
643 nScratch -= len; |
643 nScratch -= len; |
644 nextCode++; |
644 nextCode++; |
645 } |
645 } |
646 oldCode = code; |
646 oldCode = code; |
647 if (nextCode >= 511) |
647 if (nextCode >= 511) { |
648 if (nextCode == 511) { |
648 if (nextCode == 511) { |
649 codeLen = 10; |
649 codeLen = 10; |
650 mask = 0x3FF; |
650 mask = 0x3FF; |
651 } else if (nextCode >= 1023) |
651 } else if (nextCode >= 1023) { |
652 if (nextCode == 1023) { |
652 if (nextCode == 1023) { |
653 codeLen = 11; |
653 codeLen = 11; |
654 mask = 0x7FF; |
654 mask = 0x7FF; |
655 } else |
655 } else { |
656 if (nextCode == 2047) { |
656 if (nextCode == 2047) { |
657 codeLen = 12; |
657 codeLen = 12; |
658 mask = 0xFFF; |
658 mask = 0xFFF; |
659 } |
659 } |
660 } |
660 } |
|
661 } |
|
662 } |
|
663 } |
661 } |
664 } |
662 out: ; |
665 out: ; |
663 /* free stuff */ |
666 /* free stuff */ |
664 while (scratchBuffer) { |
667 while (scratchBuffer) { |
665 newBuffer = scratchBuffer; |
668 newBuffer = scratchBuffer; |
666 scratchBuffer = scratchBuffer->prev; |
669 scratchBuffer = scratchBuffer->prev; |
667 free(newBuffer); |
670 free(newBuffer); |
668 } |
671 } |
669 |
672 |
670 free(strings); |
673 free(strings); |
671 free(stringLen); |
674 free(stringLen); |
672 |
675 |
673 if (from > fromEnd) { |
676 if (from > fromEnd) { |
674 if (@global(InfoPrinting) == true) { |
677 if (@global(InfoPrinting) == true) { |
675 console_fprintf(stderr, "ImageReader [warning]: LZW inBuffer overrun\n"); |
678 console_fprintf(stderr, "ImageReader [warning]: LZW inBuffer overrun\n"); |
676 } |
679 } |
677 ret = 0; |
680 ret = 0; |
678 } |
681 } |
679 return ret; |
682 return ret; |
680 } |
683 } |
681 |
684 |
682 /* |
685 /* |
683 * delta decoding (TIFF predictor = 2) |
686 * delta decoding (TIFF predictor = 2) |
684 */ |
687 */ |
685 static |
688 static void |
686 __decodeDelta__(bytes, width, height) |
689 __decodeDelta__(bytes, width, height) |
687 register unsigned char *bytes; |
690 register unsigned char *bytes; |
688 { |
691 { |
689 register w; |
692 register w; |
690 unsigned char r, g, b; |
693 unsigned char r, g, b; |
691 |
694 |
692 while (height--) { |
695 while (height--) { |
693 r = g = b = 0; |
696 r = g = b = 0; |
694 for (w = width; w; w--) { |
697 for (w = width; w; w--) { |
695 r += *bytes; |
698 r += *bytes; |
696 *bytes++ = r; |
699 *bytes++ = r; |
697 g += *bytes; |
700 g += *bytes; |
698 *bytes++ = g; |
701 *bytes++ = g; |
699 b += *bytes; |
702 b += *bytes; |
700 *bytes++ = b; |
703 *bytes++ = b; |
701 } |
704 } |
702 } |
705 } |
703 } |
706 } |
704 |
707 |
705 /* |
708 /* |
706 * GIF decompression |
709 * GIF decompression |
707 */ |
710 */ |
723 int len; |
726 int len; |
724 int endCode, clearCode, freeCode; |
727 int endCode, clearCode, freeCode; |
725 int codeLen = initialCodeLen; |
728 int codeLen = initialCodeLen; |
726 unsigned char *fromEnd, *toEnd; |
729 unsigned char *fromEnd, *toEnd; |
727 static int ranges[] = {0, 1, 2, 4, 8, 16, 32, 64, |
730 static int ranges[] = {0, 1, 2, 4, 8, 16, 32, 64, |
728 128, 256, 512, 1024, 2048 }; |
731 128, 256, 512, 1024, 2048 }; |
729 |
732 |
730 fromEnd = from + fromSize; |
733 fromEnd = from + fromSize; |
731 toEnd = to + toSize; |
734 toEnd = to + toSize; |
732 |
735 |
733 if ((unsigned)codeLen > 12) { |
736 if ((unsigned)codeLen > 12) { |
734 if (@global(InfoPrinting) == true) { |
737 if (@global(InfoPrinting) == true) { |
735 console_fprintf(stderr, "ImageReader [warning]: GIF bad codelen (>12)\n"); |
738 console_fprintf(stderr, "ImageReader [warning]: GIF bad codelen (>12)\n"); |
736 } |
739 } |
737 return 0; |
740 return 0; |
738 } |
741 } |
739 prefix = (unsigned short *)malloc(sizeof(short) * 4096); |
742 prefix = (unsigned short *)malloc(sizeof(short) * 4096); |
740 if (! prefix) return 0; |
743 if (! prefix) return 0; |
741 suffix = (unsigned short *)malloc(sizeof(short) * 4096); |
744 suffix = (unsigned short *)malloc(sizeof(short) * 4096); |
742 if (! suffix) { |
745 if (! suffix) { |
743 free(prefix); |
746 free(prefix); |
744 return 0; |
747 return 0; |
745 } |
748 } |
746 outCode = (unsigned short *)malloc(sizeof(short) * 4096); |
749 outCode = (unsigned short *)malloc(sizeof(short) * 4096); |
747 if (! outCode) { |
750 if (! outCode) { |
748 free(prefix); |
751 free(prefix); |
749 free(suffix); |
752 free(suffix); |
750 return 0; |
753 return 0; |
751 } |
754 } |
752 clearCode = ranges[codeLen]; /* 256 */ |
755 clearCode = ranges[codeLen]; /* 256 */ |
753 endCode = clearCode + 1; /* 257 */ |
756 endCode = clearCode + 1; /* 257 */ |
754 freeCode = clearCode + 2; /* 258 */ |
757 freeCode = clearCode + 2; /* 258 */ |
755 maxCode = clearCode << 1; /* 512 */ |
758 maxCode = clearCode << 1; /* 512 */ |
757 |
760 |
758 mask = maxCode - 1; /* 1FF */ |
761 mask = maxCode - 1; /* 1FF */ |
759 nBits = 0; |
762 nBits = 0; |
760 bits = 0; |
763 bits = 0; |
761 while (inCount) { |
764 while (inCount) { |
762 /* fetch code */ |
765 /* fetch code */ |
763 while (nBits < codeLen) { |
766 while (nBits < codeLen) { |
764 bits = bits | (*from++ << nBits); |
767 bits = bits | (*from++ << nBits); |
765 inCount--; |
768 inCount--; |
766 nBits += 8; |
769 nBits += 8; |
767 } |
770 } |
768 if (inCount <= 0) |
771 if (inCount <= 0) |
769 break; |
772 break; |
770 code = bits & mask; |
773 code = bits & mask; |
771 bits >>= codeLen; |
774 bits >>= codeLen; |
772 nBits -= codeLen; |
775 nBits -= codeLen; |
773 if (code == endCode) break; |
776 if (code == endCode) break; |
774 if (code == clearCode) { |
777 if (code == clearCode) { |
775 if (inCount <= 0) |
778 if (inCount <= 0) |
776 break; |
779 break; |
777 |
780 |
778 codeLen = initialCodeLen; |
781 codeLen = initialCodeLen; |
779 maxCode = clearCode<<1; |
782 maxCode = clearCode<<1; |
780 mask = maxCode - 1; |
783 mask = maxCode - 1; |
781 freeCode = clearCode + 2; |
784 freeCode = clearCode + 2; |
782 |
785 |
783 /* fetch code */ |
786 /* fetch code */ |
784 while (nBits < codeLen) { |
787 while (nBits < codeLen) { |
785 bits = bits | (*from++ << nBits); |
788 bits = bits | (*from++ << nBits); |
786 inCount--; |
789 inCount--; |
787 nBits += 8; |
790 nBits += 8; |
788 } |
791 } |
789 if (inCount <= 0) |
792 if (inCount <= 0) |
790 break; |
793 break; |
791 code = bits & mask; |
794 code = bits & mask; |
792 bits >>= codeLen; |
795 bits >>= codeLen; |
793 nBits -= codeLen; |
796 nBits -= codeLen; |
794 if (code == endCode) break; |
797 if (code == endCode) break; |
795 /* add to output */ |
798 /* add to output */ |
796 if (to >= toEnd) { |
799 if (to >= toEnd) { |
797 if (@global(InfoPrinting) == true) { |
800 if (@global(InfoPrinting) == true) { |
798 console_fprintf(stderr, "ImageReader [warning]: GIF outBuffer overrun\n"); |
801 console_fprintf(stderr, "ImageReader [warning]: GIF outBuffer overrun\n"); |
799 } |
802 } |
800 ret = 0; |
803 ret = 0; |
801 break; |
804 break; |
802 } |
805 } |
803 *to++ = code; |
806 *to++ = code; |
804 oldCode = fin = curCode = code; |
807 oldCode = fin = curCode = code; |
805 } else { |
808 } else { |
806 curCode = inCode = code; |
809 curCode = inCode = code; |
807 if (curCode >= freeCode) { |
810 if (curCode >= freeCode) { |
808 curCode = oldCode; |
811 curCode = oldCode; |
809 outCode[outCount++] = fin; |
812 outCode[outCount++] = fin; |
810 } |
813 } |
811 |
814 |
812 while (curCode >= clearCode) { |
815 while (curCode >= clearCode) { |
813 if (outCount > 1024) { |
816 if (outCount > 1024) { |
814 goto out; |
817 goto out; |
815 } |
818 } |
816 |
819 |
817 /* debugging and protecting myself from overwrites */ |
820 /* debugging and protecting myself from overwrites */ |
818 if (curCode >= 4096) { |
821 if (curCode >= 4096) { |
819 if (@global(InfoPrinting) == true) { |
822 if (@global(InfoPrinting) == true) { |
820 console_fprintf(stderr, "ImageReader [warning]: GIF corrupted input (code > 4095)\n"); |
823 console_fprintf(stderr, "ImageReader [warning]: GIF corrupted input (code > 4095)\n"); |
821 } |
824 } |
822 ret = 0; |
825 ret = 0; |
823 break; |
826 break; |
824 } |
827 } |
825 outCode[outCount++] = suffix[curCode]; |
828 outCode[outCount++] = suffix[curCode]; |
826 curCode = prefix[curCode]; |
829 curCode = prefix[curCode]; |
827 } |
830 } |
828 |
831 |
829 fin = curCode; |
832 fin = curCode; |
830 outCode[outCount++] = fin; |
833 outCode[outCount++] = fin; |
831 |
834 |
832 #if 0 |
835 #if 0 |
833 if ((to+outCount) >= toEnd) { |
836 if ((to+outCount) >= toEnd) { |
834 if (@global(InfoPrinting) == true) { |
837 if (@global(InfoPrinting) == true) { |
835 console_fprintf(stderr, "ImageReader [warning]: GIF outBuffer overrun\n"); |
838 console_fprintf(stderr, "ImageReader [warning]: GIF outBuffer overrun\n"); |
836 } |
839 } |
837 ret = 0; |
840 ret = 0; |
838 break; |
841 break; |
839 } |
842 } |
840 #endif |
843 #endif |
841 for (i = outCount - 1; i >= 0; i--) { |
844 for (i = outCount - 1; i >= 0; i--) { |
842 if (to >= toEnd) { |
845 if (to >= toEnd) { |
843 if (@global(InfoPrinting) == true) { |
846 if (@global(InfoPrinting) == true) { |
844 console_fprintf(stderr, "ImageReader [warning]: GIF outBuffer overrun\n"); |
847 console_fprintf(stderr, "ImageReader [warning]: GIF outBuffer overrun\n"); |
845 } |
848 } |
846 ret = 0; |
849 ret = 0; |
847 break; |
850 break; |
848 } |
851 } |
849 *to++ = outCode[i]; |
852 *to++ = outCode[i]; |
850 } |
853 } |
851 outCount = 0; |
854 outCount = 0; |
852 |
855 |
853 /* debugging and protecting myself from overwrites */ |
856 /* debugging and protecting myself from overwrites */ |
854 if (freeCode >= 4096) { |
857 if (freeCode >= 4096) { |
855 if (@global(InfoPrinting) == true) { |
858 if (@global(InfoPrinting) == true) { |
856 console_fprintf(stderr, "ImageReader [warning]: GIF corrupted input (freeCode > 4095)\n"); |
859 console_fprintf(stderr, "ImageReader [warning]: GIF corrupted input (freeCode > 4095)\n"); |
857 } |
860 } |
858 ret = 0; |
861 ret = 0; |
859 break; |
862 break; |
860 } |
863 } |
861 |
864 |
862 prefix[freeCode] = oldCode; |
865 prefix[freeCode] = oldCode; |
863 suffix[freeCode] = fin; |
866 suffix[freeCode] = fin; |
864 oldCode = inCode; |
867 oldCode = inCode; |
865 |
868 |
866 freeCode++; |
869 freeCode++; |
867 if (freeCode >= maxCode) { |
870 if (freeCode >= maxCode) { |
868 if (codeLen < 12) { |
871 if (codeLen < 12) { |
869 codeLen++; |
872 codeLen++; |
870 maxCode *= 2; |
873 maxCode *= 2; |
871 mask = (1 << codeLen) - 1; |
874 mask = (1 << codeLen) - 1; |
872 } |
875 } |
873 } |
876 } |
874 } |
877 } |
875 } |
878 } |
876 out: ; |
879 out: ; |
877 free(prefix); |
880 free(prefix); |
878 free(suffix); |
881 free(suffix); |
879 free(outCode); |
882 free(outCode); |
880 |
883 |
881 if (from > fromEnd) { |
884 if (from > fromEnd) { |
882 if (@global(InfoPrinting) == true) { |
885 if (@global(InfoPrinting) == true) { |
883 console_fprintf(stderr, "ImageReader [warning]: GIF inBuffer overrun\n"); |
886 console_fprintf(stderr, "ImageReader [warning]: GIF inBuffer overrun\n"); |
884 } |
887 } |
885 ret = 0; |
888 ret = 0; |
886 } |
889 } |
887 return ret; |
890 return ret; |
888 } |
891 } |
889 |
892 |
890 %} |
893 %} |
916 ImageReaderWriter classes. |
919 ImageReaderWriter classes. |
917 |
920 |
918 ImageReaders are created temporary to read an image from a stream. |
921 ImageReaders are created temporary to read an image from a stream. |
919 Normally, they are not directly used - instead, the image class is |
922 Normally, they are not directly used - instead, the image class is |
920 asked to read some file, and return an instance for it: |
923 asked to read some file, and return an instance for it: |
921 Image fromFile:<someFileName> |
924 Image fromFile:<someFileName> |
922 The Image class will guess the images format and forward the task to |
925 The Image class will guess the images format and forward the task to |
923 some concrete ImageReaderClass. |
926 some concrete ImageReaderClass. |
924 If that class thinks, that the file's format is incorrect, |
927 If that class thinks, that the file's format is incorrect, |
925 other readers are tried until some reader class finds the file's format acceptable. |
928 other readers are tried until some reader class finds the file's format acceptable. |
926 |
929 |
927 Image readers read the stream and collect all relevant information internally. |
930 Image readers read the stream and collect all relevant information internally. |
928 Once done with reading, the actual image object is created and |
931 Once done with reading, the actual image object is created and |
929 data filled in from the imageReaders collected info. |
932 data filled in from the imageReaders collected info. |
930 |
933 |
931 See the implementation of #fromStream: in concrete subclasses. |
934 See the implementation of #fromStream: in concrete subclasses. |
932 The public interfaces are: |
935 The public interfaces are: |
933 <ConcreteReaderClass> fromFile:aFilename |
936 <ConcreteReaderClass> fromFile:aFilename |
934 or: |
937 or: |
935 <ConcreteReaderClass> fromStream:aStream |
938 <ConcreteReaderClass> fromStream:aStream |
936 |
939 |
937 If you add a new reader, don't forget to add the method #isValidImageFile: |
940 If you add a new reader, don't forget to add the method #isValidImageFile: |
938 which should return true, if this reader supports reading a given file. |
941 which should return true, if this reader supports reading a given file. |
939 |
942 |
940 If your new reader class supports writing files, don't forget to add |
943 If your new reader class supports writing files, don't forget to add |
941 #canRepresent:anImage and return true from this method. |
944 #canRepresent:anImage and return true from this method. |
942 |
945 |
943 [See also:] |
946 [See also:] |
944 Image Icon Form |
947 Image Icon Form |
945 |
948 |
946 [author:] |
949 [author:] |
947 Claus Gittinger |
950 Claus Gittinger |
948 " |
951 " |
949 ! ! |
952 ! ! |
950 |
953 |
951 !ImageReader class methodsFor:'instance creation'! |
954 !ImageReader class methodsFor:'instance creation'! |
952 |
955 |
1544 /* |
1547 /* |
1545 printf("outP: %x outEnd: %x sz: %d\n", __outP, outEnd, __byteArraySize(maskArray)); |
1548 printf("outP: %x outEnd: %x sz: %d\n", __outP, outEnd, __byteArraySize(maskArray)); |
1546 */ |
1549 */ |
1547 |
1550 |
1548 for (__y=__h; __y>0; __y--) { |
1551 for (__y=__h; __y>0; __y--) { |
1549 __outBits = 0; |
1552 __outBits = 0; |
1550 __nOut = 8; |
1553 __nOut = 8; |
1551 __nextOutRow = __outP + __bpr; |
1554 __nextOutRow = __outP + __bpr; |
1552 |
1555 |
1553 for (__x=__w; __x>=8; __x-=8) { |
1556 for (__x=__w; __x>=8; __x-=8) { |
1554 if (__inP[0] != __maskPixel) { __outBits |= 0x80; }; |
1557 if (__inP[0] != __maskPixel) { __outBits |= 0x80; }; |
1555 if (__inP[1] != __maskPixel) { __outBits |= 0x40; }; |
1558 if (__inP[1] != __maskPixel) { __outBits |= 0x40; }; |
1556 if (__inP[2] != __maskPixel) { __outBits |= 0x20; }; |
1559 if (__inP[2] != __maskPixel) { __outBits |= 0x20; }; |
1557 if (__inP[3] != __maskPixel) { __outBits |= 0x10; }; |
1560 if (__inP[3] != __maskPixel) { __outBits |= 0x10; }; |
1558 if (__inP[4] != __maskPixel) { __outBits |= 0x08; }; |
1561 if (__inP[4] != __maskPixel) { __outBits |= 0x08; }; |
1559 if (__inP[5] != __maskPixel) { __outBits |= 0x04; }; |
1562 if (__inP[5] != __maskPixel) { __outBits |= 0x04; }; |
1560 if (__inP[6] != __maskPixel) { __outBits |= 0x02; }; |
1563 if (__inP[6] != __maskPixel) { __outBits |= 0x02; }; |
1561 if (__inP[7] != __maskPixel) { __outBits |= 0x01; }; |
1564 if (__inP[7] != __maskPixel) { __outBits |= 0x01; }; |
1562 __inP += 8; |
1565 __inP += 8; |
1563 *__outP++ = __outBits; |
1566 *__outP++ = __outBits; |
1564 __outBits = 0; |
1567 __outBits = 0; |
1565 } |
1568 } |
1566 for (; __x>0; __x--) { |
1569 for (; __x>0; __x--) { |
1567 __outBits <<= 1; |
1570 __outBits <<= 1; |
1568 if (*__inP != __maskPixel) { |
1571 if (*__inP != __maskPixel) { |
1569 __outBits |= 1; |
1572 __outBits |= 1; |
1570 } |
1573 } |
1571 __inP++; |
1574 __inP++; |
1572 |
1575 |
1573 /* |
1576 /* |
1574 printf("x: %d bits: %x\n", __x, __outBits); |
1577 printf("x: %d bits: %x\n", __x, __outBits); |
1575 */ |
1578 */ |
1576 if (--__nOut == 0) { |
1579 if (--__nOut == 0) { |
1577 #ifdef DEBUG |
1580 #ifdef DEBUG |
1578 if (__outP >= outEnd) { |
1581 if (__outP >= outEnd) { |
1579 if (@global(InfoPrinting) == true) { |
1582 if (@global(InfoPrinting) == true) { |
1580 console_fprintf(stderr, "oops %d\n", __LINE__); |
1583 console_fprintf(stderr, "oops %d\n", __LINE__); |
1581 } |
1584 } |
1582 goto fail; |
1585 goto fail; |
1583 } |
1586 } |
1584 #endif |
1587 #endif |
1585 *__outP = __outBits; |
1588 *__outP = __outBits; |
1586 |
1589 |
1587 __outP++; |
1590 __outP++; |
1588 __nOut = 8; |
1591 __nOut = 8; |
1589 __outBits = 0; |
1592 __outBits = 0; |
1590 } |
1593 } |
1591 } |
1594 } |
1592 |
1595 |
1593 if (__nOut != 8) { |
1596 if (__nOut != 8) { |
1594 __outBits <<= __nOut; |
1597 __outBits <<= __nOut; |
1595 |
1598 |
1596 #ifdef DEBUG |
1599 #ifdef DEBUG |
1597 if (__outP >= outEnd) { |
1600 if (__outP >= outEnd) { |
1598 if (@global(InfoPrinting) == true) { |
1601 if (@global(InfoPrinting) == true) { |
1599 console_fprintf(stderr, "oops2 %d\n", __LINE__); |
1602 console_fprintf(stderr, "oops2 %d\n", __LINE__); |
1600 } |
1603 } |
1601 goto fail; |
1604 goto fail; |
1602 } |
1605 } |
1603 #endif |
1606 #endif |
1604 *__outP = __outBits; |
1607 *__outP = __outBits; |
1605 |
1608 |
1606 } |
1609 } |
1607 __outP = __nextOutRow; |
1610 __outP = __nextOutRow; |
1608 } |
1611 } |
1609 fail: ; |
1612 fail: ; |
1610 %}. |
1613 %}. |
1611 mask := ImageMask width:width height:height fromArray:maskArray. |
1614 mask := ImageMask width:width height:height fromArray:maskArray. |
1612 ^ mask |
1615 ^ mask |