ImageReader.st
changeset 6902 6357c181c178
parent 6761 7307a75477f4
child 7142 439177d49d77
equal deleted inserted replaced
6900:ad20df4aec7a 6902:6357c181c178
   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 
  1021      Calls primitive c function for speed"
  1024      Calls primitive c function for speed"
  1022 %{
  1025 %{
  1023     if (__isByteArrayLike(srcBytes)
  1026     if (__isByteArrayLike(srcBytes)
  1024      && __isByteArray(dstBytes)
  1027      && __isByteArray(dstBytes)
  1025      && __bothSmallInteger(offset, count)) {
  1028      && __bothSmallInteger(offset, count)) {
  1026         if (__decodeCCITTgroup3__(__ByteArrayInstPtr(srcBytes)->ba_element,
  1029 	if (__decodeCCITTgroup3__(__ByteArrayInstPtr(srcBytes)->ba_element,
  1027                                   __ByteArrayInstPtr(dstBytes)->ba_element
  1030 				  __ByteArrayInstPtr(dstBytes)->ba_element
  1028                                   + __intVal(offset) - 1,
  1031 				  + __intVal(offset) - 1,
  1029                                   __intVal(count))) {
  1032 				  __intVal(count))) {
  1030             RETURN ( self );
  1033 	    RETURN ( self );
  1031         }
  1034 	}
  1032     }
  1035     }
  1033 %}
  1036 %}
  1034 .
  1037 .
  1035     self primitiveFailed
  1038     self primitiveFailed
  1036 !
  1039 !
  1042 %{
  1045 %{
  1043     if (__isByteArrayLike(srcBytes)
  1046     if (__isByteArrayLike(srcBytes)
  1044      && __isByteArray(dstBytes)
  1047      && __isByteArray(dstBytes)
  1045      && __bothSmallInteger(codeLen, offset)
  1048      && __bothSmallInteger(codeLen, offset)
  1046      && __isSmallInteger(count)) {
  1049      && __isSmallInteger(count)) {
  1047         if (__decodeGIF__(__ByteArrayInstPtr(srcBytes)->ba_element,
  1050 	if (__decodeGIF__(__ByteArrayInstPtr(srcBytes)->ba_element,
  1048                           __ByteArrayInstPtr(dstBytes)->ba_element
  1051 			  __ByteArrayInstPtr(dstBytes)->ba_element
  1049                                                 +__intVal(offset) - 1,
  1052 						+__intVal(offset) - 1,
  1050                           __intVal(count),
  1053 			  __intVal(count),
  1051                           __intVal(codeLen),
  1054 			  __intVal(codeLen),
  1052                           __byteArraySize(srcBytes),
  1055 			  __byteArraySize(srcBytes),
  1053                           __byteArraySize(dstBytes)
  1056 			  __byteArraySize(dstBytes)
  1054                          )) {
  1057 			 )) {
  1055             RETURN ( self );
  1058 	    RETURN ( self );
  1056         }
  1059 	}
  1057     }
  1060     }
  1058 %}
  1061 %}
  1059 .
  1062 .
  1060     self primitiveFailed
  1063     self primitiveFailed
  1061 !
  1064 !
  1066      Calls primitive c function for speed"
  1069      Calls primitive c function for speed"
  1067 %{
  1070 %{
  1068     if (__isByteArrayLike(srcBytes)
  1071     if (__isByteArrayLike(srcBytes)
  1069      && __isByteArray(dstBytes)
  1072      && __isByteArray(dstBytes)
  1070      && __bothSmallInteger(offset, count)) {
  1073      && __bothSmallInteger(offset, count)) {
  1071         if (__decodeLZW__(__ByteArrayInstPtr(srcBytes)->ba_element,
  1074 	if (__decodeLZW__(__ByteArrayInstPtr(srcBytes)->ba_element,
  1072                           __ByteArrayInstPtr(dstBytes)->ba_element
  1075 			  __ByteArrayInstPtr(dstBytes)->ba_element
  1073                                               + __intVal(offset) - 1,
  1076 					      + __intVal(offset) - 1,
  1074                           __intVal(count),
  1077 			  __intVal(count),
  1075                           __byteArraySize(srcBytes),
  1078 			  __byteArraySize(srcBytes),
  1076                           __byteArraySize(dstBytes)
  1079 			  __byteArraySize(dstBytes)
  1077                         )) {
  1080 			)) {
  1078             RETURN ( self );
  1081 	    RETURN ( self );
  1079         }
  1082 	}
  1080     }
  1083     }
  1081 %}
  1084 %}
  1082 .
  1085 .
  1083     self primitiveFailed
  1086     self primitiveFailed
  1084 !
  1087 !
  1092 
  1095 
  1093     dstOffs := dstOffset.
  1096     dstOffs := dstOffset.
  1094     i := 1.
  1097     i := 1.
  1095 
  1098 
  1096     [i <= nIn] whileTrue:[
  1099     [i <= nIn] whileTrue:[
  1097         b := srcBytes at:i.
  1100 	b := srcBytes at:i.
  1098         i := i + 1.
  1101 	i := i + 1.
  1099 
  1102 
  1100         b ~~ 16rFF ifTrue:[   "/ not a NOP
  1103 	b ~~ 16rFF ifTrue:[   "/ not a NOP
  1101             b <= 127 ifTrue:[
  1104 	    b <= 127 ifTrue:[
  1102                 "/ 0..127 literal bytes
  1105 		"/ 0..127 literal bytes
  1103                 n := b + 1.
  1106 		n := b + 1.
  1104                 dstBytes replaceFrom:dstOffs to:dstOffs+n-1 with:srcBytes startingAt:i.
  1107 		dstBytes replaceFrom:dstOffs to:dstOffs+n-1 with:srcBytes startingAt:i.
  1105                 i := i + n.
  1108 		i := i + n.
  1106             ] ifFalse:[                  
  1109 	    ] ifFalse:[
  1107                 "/ 128..254 a run        
  1110 		"/ 128..254 a run
  1108                 n := b - 125.
  1111 		n := b - 125.
  1109 
  1112 
  1110                 v := srcBytes at:i.
  1113 		v := srcBytes at:i.
  1111                 i := i + 1.
  1114 		i := i + 1.
  1112 
  1115 
  1113                 dstBytes from:dstOffs to:dstOffs+n put:v.
  1116 		dstBytes from:dstOffs to:dstOffs+n put:v.
  1114             ].
  1117 	    ].
  1115             dstOffs := dstOffs + n.
  1118 	    dstOffs := dstOffs + n.
  1116         ]
  1119 	]
  1117     ].
  1120     ].
  1118     ^ dstOffs - dstOffset
  1121     ^ dstOffs - dstOffset
  1119 
  1122 
  1120     "Created: / 1.12.1997 / 18:39:23 / cg"
  1123     "Created: / 1.12.1997 / 18:39:23 / cg"
  1121     "Modified: / 1.12.1997 / 18:49:58 / cg"
  1124     "Modified: / 1.12.1997 / 18:49:58 / cg"
  1130 
  1133 
  1131     dstOffs := dstStart.
  1134     dstOffs := dstStart.
  1132     i := srcStart.
  1135     i := srcStart.
  1133     nRemaining := outCount.
  1136     nRemaining := outCount.
  1134     [nRemaining > 0] whileTrue:[
  1137     [nRemaining > 0] whileTrue:[
  1135         b := srcBytes at:i.
  1138 	b := srcBytes at:i.
  1136         i := i + 1.
  1139 	i := i + 1.
  1137 
  1140 
  1138         b ~~ 16rFF ifTrue:[   "/ not a NOP
  1141 	b ~~ 16rFF ifTrue:[   "/ not a NOP
  1139             b <= 127 ifTrue:[
  1142 	    b <= 127 ifTrue:[
  1140                 "/ 0..127 literal bytes
  1143 		"/ 0..127 literal bytes
  1141                 n := b + 1.
  1144 		n := b + 1.
  1142                 dstBytes replaceFrom:dstOffs to:dstOffs+n-1 with:srcBytes startingAt:i.
  1145 		dstBytes replaceFrom:dstOffs to:dstOffs+n-1 with:srcBytes startingAt:i.
  1143                 nRemaining := nRemaining - n.
  1146 		nRemaining := nRemaining - n.
  1144                 i := i + n.
  1147 		i := i + n.
  1145             ] ifFalse:[                  
  1148 	    ] ifFalse:[
  1146                 "/ 128..254 a run        
  1149 		"/ 128..254 a run
  1147                 n := b - 125.
  1150 		n := b - 125.
  1148 
  1151 
  1149                 v := srcBytes at:i.
  1152 		v := srcBytes at:i.
  1150                 i := i + 1.
  1153 		i := i + 1.
  1151 
  1154 
  1152                 dstBytes from:dstOffs to:dstOffs+n-1 put:v.
  1155 		dstBytes from:dstOffs to:dstOffs+n-1 put:v.
  1153                 nRemaining := nRemaining - n.
  1156 		nRemaining := nRemaining - n.
  1154             ].
  1157 	    ].
  1155             dstOffs := dstOffs + n.
  1158 	    dstOffs := dstOffs + n.
  1156         ]
  1159 	]
  1157     ].
  1160     ].
  1158     ^ i-srcStart
  1161     ^ i-srcStart
  1159 !
  1162 !
  1160 
  1163 
  1161 decompressRLEFrom:srcBytes at:srcStartIndex into:dstBytes at:dstStartIndex increment:dstIncrement
  1164 decompressRLEFrom:srcBytes at:srcStartIndex into:dstBytes at:dstStartIndex increment:dstIncrement
  1234      |bytes|
  1237      |bytes|
  1235 
  1238 
  1236      bytes := ByteArray new:1000000.
  1239      bytes := ByteArray new:1000000.
  1237      bytes replaceFrom:1 with:#[ 0 1 2 3 4 5 6 7 8 9 10 11 12].
  1240      bytes replaceFrom:1 with:#[ 0 1 2 3 4 5 6 7 8 9 10 11 12].
  1238      Time millisecondsToRun:[
  1241      Time millisecondsToRun:[
  1239         self swap:1000000 bytesFromRGB_to_BGR_in:bytes.
  1242 	self swap:1000000 bytesFromRGB_to_BGR_in:bytes.
  1240      ].
  1243      ].
  1241      bytes copyTo:10.
  1244      bytes copyTo:10.
  1242     "
  1245     "
  1243 !
  1246 !
  1244 
  1247 
  1247      The argument is a pixel data buffer (byteArray)"
  1250      The argument is a pixel data buffer (byteArray)"
  1248 
  1251 
  1249     |t|
  1252     |t|
  1250 
  1253 
  1251 %{  /* OPTIONAL */
  1254 %{  /* OPTIONAL */
  1252     if (__isByteArray(data) 
  1255     if (__isByteArray(data)
  1253      && __isSmallInteger(nBytes)
  1256      && __isSmallInteger(nBytes)
  1254      && __isSmallInteger(startIndex)) {
  1257      && __isSmallInteger(startIndex)) {
  1255         int __nBytes = __intVal(nBytes);
  1258 	int __nBytes = __intVal(nBytes);
  1256         int __startOffset = __intVal(startIndex) - 1;
  1259 	int __startOffset = __intVal(startIndex) - 1;
  1257         int __dataSize = __byteArraySize(data);
  1260 	int __dataSize = __byteArraySize(data);
  1258 
  1261 
  1259         if ((__startOffset + __nBytes) <= __dataSize) {
  1262 	if ((__startOffset + __nBytes) <= __dataSize) {
  1260             int __lastIndex = __startOffset + __nBytes - 2;
  1263 	    int __lastIndex = __startOffset + __nBytes - 2;
  1261             unsigned char *__cp = __ByteArrayInstPtr(data)->ba_element + __startOffset;
  1264 	    unsigned char *__cp = __ByteArrayInstPtr(data)->ba_element + __startOffset;
  1262             int __i;
  1265 	    int __i;
  1263             unsigned char __t;
  1266 	    unsigned char __t;
  1264 
  1267 
  1265             for (__i=__startOffset; __i<__lastIndex; __i+=3, __cp+=3) {
  1268 	    for (__i=__startOffset; __i<__lastIndex; __i+=3, __cp+=3) {
  1266                 __t = __cp[0];
  1269 		__t = __cp[0];
  1267                 __cp[0] = __cp[2];
  1270 		__cp[0] = __cp[2];
  1268                 __cp[2] = __t;
  1271 		__cp[2] = __t;
  1269             }
  1272 	    }
  1270             RETURN (true);
  1273 	    RETURN (true);
  1271         }
  1274 	}
  1272     }
  1275     }
  1273 %}.
  1276 %}.
  1274     1 to:(nBytes - 2) by:3 do:[:i |
  1277     1 to:(nBytes - 2) by:3 do:[:i |
  1275         |ii|
  1278 	|ii|
  1276 
  1279 
  1277         ii := i + startIndex - 1.
  1280 	ii := i + startIndex - 1.
  1278         t := data at:ii.
  1281 	t := data at:ii.
  1279         data at:i put:(data at:ii+2).
  1282 	data at:i put:(data at:ii+2).
  1280         data at:ii+2 put:t
  1283 	data at:ii+2 put:t
  1281     ].
  1284     ].
  1282 
  1285 
  1283     "
  1286     "
  1284      |bytes|
  1287      |bytes|
  1285 
  1288 
  1291      |bytes|
  1294      |bytes|
  1292 
  1295 
  1293      bytes := ByteArray new:1000000.
  1296      bytes := ByteArray new:1000000.
  1294      bytes replaceFrom:1 with:#[ 0 1 2 3 4 5 6 7 8 9 10 11 12].
  1297      bytes replaceFrom:1 with:#[ 0 1 2 3 4 5 6 7 8 9 10 11 12].
  1295      Time millisecondsToRun:[
  1298      Time millisecondsToRun:[
  1296         self swap:1000000 bytesFromRGB_to_BGR_in:bytes.
  1299 	self swap:1000000 bytesFromRGB_to_BGR_in:bytes.
  1297      ].
  1300      ].
  1298      bytes copyTo:10.
  1301      bytes copyTo:10.
  1299     "
  1302     "
  1300 ! !
  1303 ! !
  1301 
  1304 
  1376      Return the image or nil (if unrecognized format or error)"
  1379      Return the image or nil (if unrecognized format or error)"
  1377 
  1380 
  1378     |readerClass response|
  1381     |readerClass response|
  1379 
  1382 
  1380     self == ImageReader ifTrue:[
  1383     self == ImageReader ifTrue:[
  1381         "select a reader supporting this file format"
  1384 	"select a reader supporting this file format"
  1382         readerClass := self readerClassForFilename:url asURL path.
  1385 	readerClass := self readerClassForFilename:url asURL path.
  1383         readerClass ~~ self ifTrue:[
  1386 	readerClass ~~ self ifTrue:[
  1384             ^ readerClass fromURL:url.
  1387 	    ^ readerClass fromURL:url.
  1385         ].
  1388 	].
  1386     ].
  1389     ].
  1387 
  1390 
  1388     response := HTTPInterface get:url.
  1391     response := HTTPInterface get:url.
  1389     response isErrorResponse ifTrue:[
  1392     response isErrorResponse ifTrue:[
  1390         self error:'failed to read url' mayProceed:true.
  1393 	self error:'failed to read url' mayProceed:true.
  1391         ^ nil
  1394 	^ nil
  1392     ].
  1395     ].
  1393     ^ self fromBytes:(response data).
  1396     ^ self fromBytes:(response data).
  1394 
  1397 
  1395     "
  1398     "
  1396      self fromURL:'http://www.lutece.paris.fr/tech/images/helloworld.png'
  1399      self fromURL:'http://www.lutece.paris.fr/tech/images/helloworld.png'
  1435      so it can be asked with 'reader image')."
  1438      so it can be asked with 'reader image')."
  1436 
  1439 
  1437     |readerClass reader inStream|
  1440     |readerClass reader inStream|
  1438 
  1441 
  1439     self == ImageReader ifTrue:[
  1442     self == ImageReader ifTrue:[
  1440         "select a reader supporting this file format"
  1443 	"select a reader supporting this file format"
  1441         readerClass := self readerClassForFilename:aFilename.
  1444 	readerClass := self readerClassForFilename:aFilename.
  1442         readerClass ~~ self ifTrue:[
  1445 	readerClass ~~ self ifTrue:[
  1443             ^ readerClass readFile:aFilename.
  1446 	    ^ readerClass readFile:aFilename.
  1444         ].
  1447 	].
  1445     ].
  1448     ].
  1446 
  1449 
  1447     inStream := self streamReadingFile:aFilename.
  1450     inStream := self streamReadingFile:aFilename.
  1448     inStream isNil ifTrue:[
  1451     inStream isNil ifTrue:[
  1449         'ImageReader [warning]: file open error' errorPrintCR.
  1452 	'ImageReader [warning]: file open error' errorPrintCR.
  1450         ^ nil
  1453 	^ nil
  1451     ].
  1454     ].
  1452     reader := self new.
  1455     reader := self new.
  1453     reader inStream:inStream.
  1456     reader inStream:inStream.
  1454     [
  1457     [
  1455         reader fromStream:inStream.
  1458 	reader fromStream:inStream.
  1456     ] ensure:[
  1459     ] ensure:[
  1457         inStream close.
  1460 	inStream close.
  1458     ].
  1461     ].
  1459     ^ reader
  1462     ^ reader
  1460 
  1463 
  1461     "
  1464     "
  1462      XPMReader readFile:'../../goodies/bitmaps/xpmBitmaps/misc_icons/BOOK.xpm'
  1465      XPMReader readFile:'../../goodies/bitmaps/xpmBitmaps/misc_icons/BOOK.xpm'
  1486 
  1489 
  1487     |mime reader|
  1490     |mime reader|
  1488 
  1491 
  1489     mime := aStringOrFilename asFilename mimeTypeFromName.
  1492     mime := aStringOrFilename asFilename mimeTypeFromName.
  1490     mime isNil ifTrue:[
  1493     mime isNil ifTrue:[
  1491         mime := aStringOrFilename asFilename mimeTypeOfContents.
  1494 	mime := aStringOrFilename asFilename mimeTypeOfContents.
  1492     ].
  1495     ].
  1493 
  1496 
  1494     mime notNil ifTrue:[
  1497     mime notNil ifTrue:[
  1495         reader := MIMETypes imageReaderForType:mime.
  1498 	reader := MIMETypes imageReaderForType:mime.
  1496     ].
  1499     ].
  1497     reader isNil ifTrue:[
  1500     reader isNil ifTrue:[
  1498         "answer the reader when proceeding form this error"
  1501 	"answer the reader when proceeding form this error"
  1499         reader := ConversionError raiseRequestErrorString:(' - unsupported image type: ''%1''' bindWith:(mime ? aStringOrFilename asFilename suffix)).
  1502 	reader := ConversionError raiseRequestErrorString:(' - unsupported image type: ''%1''' bindWith:(mime ? aStringOrFilename asFilename suffix)).
  1500     ].
  1503     ].
  1501     ^ reader
  1504     ^ reader
  1502 
  1505 
  1503     "
  1506     "
  1504      self readerClassForFilename:('http://www.foo.bar/helloworld.png' asURL path)
  1507      self readerClassForFilename:('http://www.foo.bar/helloworld.png' asURL path)
  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
  1830 
  1833 
  1831 photometric
  1834 photometric
  1832     "return the photometric interpretation of the image data.
  1835     "return the photometric interpretation of the image data.
  1833      This may be a somewhat old leftover from times, when tiff was the first image file type to be read.
  1836      This may be a somewhat old leftover from times, when tiff was the first image file type to be read.
  1834      Much better would be to always have some (possibly fake and virtual) colormap around, and ask that one.
  1837      Much better would be to always have some (possibly fake and virtual) colormap around, and ask that one.
  1835      However, in the meantime, many other classes depend on that, so that it should be kept as an API 
  1838      However, in the meantime, many other classes depend on that, so that it should be kept as an API
  1836      - even when the internal representation will be replaced by something better in the future."
  1839      - even when the internal representation will be replaced by something better in the future."
  1837 
  1840 
  1838     ^ photometric
  1841     ^ photometric
  1839 
  1842 
  1840     "Modified: 22.4.1996 / 19:15:57 / cg"
  1843     "Modified: 22.4.1996 / 19:15:57 / cg"
  1885 
  1888 
  1886     |errorString|
  1889     |errorString|
  1887 
  1890 
  1888     errorString := self class name , ' [info]: ' , aMessage.
  1891     errorString := self class name , ' [info]: ' , aMessage.
  1889     inStream isFileStream ifTrue:[
  1892     inStream isFileStream ifTrue:[
  1890         errorString := errorString , ' [in ' , inStream pathName , ']'
  1893 	errorString := errorString , ' [in ' , inStream pathName , ']'
  1891     ].
  1894     ].
  1892 
  1895 
  1893     Image badImageFormatQuerySignal raiseRequestErrorString:errorString.
  1896     Image badImageFormatQuerySignal raiseRequestErrorString:errorString.
  1894     ^ nil
  1897     ^ nil
  1895 
  1898 
  1984 
  1987 
  1985 save:image onFile:aFileName
  1988 save:image onFile:aFileName
  1986     "save image in my format on aFile"
  1989     "save image in my format on aFile"
  1987 
  1990 
  1988     self writingFile:aFileName for:image do:[:stream |
  1991     self writingFile:aFileName for:image do:[:stream |
  1989         self save:image onStream:stream.
  1992 	self save:image onStream:stream.
  1990     ].
  1993     ].
  1991 
  1994 
  1992     "Modified: / 01-06-2010 / 19:02:17 / cg"
  1995     "Modified: / 01-06-2010 / 19:02:17 / cg"
  1993 !
  1996 !
  1994 
  1997 
  1995 save:image onStream:aStream
  1998 save:image onStream:aStream
  1996     "save image in my format on a Stream"
  1999     "save image in my format on a Stream"
  1997 
  2000 
  1998     ^ Image cannotRepresentImageSignal
  2001     ^ Image cannotRepresentImageSignal
  1999         raiseWith:image
  2002 	raiseWith:image
  2000         errorString:('image save not implemented/supported for this format').
  2003 	errorString:('image save not implemented/supported for this format').
  2001 !
  2004 !
  2002 
  2005 
  2003 saveAll:aCollectionOfImages onFile:aFileName
  2006 saveAll:aCollectionOfImages onFile:aFileName
  2004     "save a collection of images in my format on aFile.
  2007     "save a collection of images in my format on aFile.
  2005      Not all file formats support multiple images, so be prepared
  2008      Not all file formats support multiple images, so be prepared
  2006      for an exception to be raised."
  2009      for an exception to be raised."
  2007 
  2010 
  2008     self writingFile:aFileName for:aCollectionOfImages do:[:stream |
  2011     self writingFile:aFileName for:aCollectionOfImages do:[:stream |
  2009         self saveAll:aCollectionOfImages onStream:stream.
  2012 	self saveAll:aCollectionOfImages onStream:stream.
  2010     ].
  2013     ].
  2011 
  2014 
  2012     "Modified: / 01-06-2010 / 19:02:17 / cg"
  2015     "Modified: / 01-06-2010 / 19:02:17 / cg"
  2013 !
  2016 !
  2014 
  2017 
  2016     "save an image collection in my format on a Stream.
  2019     "save an image collection in my format on a Stream.
  2017      Not all file formats support multiple images, so be prepared
  2020      Not all file formats support multiple images, so be prepared
  2018      for an exception to be raised."
  2021      for an exception to be raised."
  2019 
  2022 
  2020     ^ Image cannotRepresentImageSignal
  2023     ^ Image cannotRepresentImageSignal
  2021         raiseWith:aCollectionOfImages
  2024 	raiseWith:aCollectionOfImages
  2022         errorString:('save of imageSequence not implemented/supported for this format').
  2025 	errorString:('save of imageSequence not implemented/supported for this format').
  2023 !
  2026 !
  2024 
  2027 
  2025 writingFile:aFileName for:something do:aBlock
  2028 writingFile:aFileName for:something do:aBlock
  2026     "helper for save image"
  2029     "helper for save image"
  2027 
  2030 
  2028     |stream|
  2031     |stream|
  2029 
  2032 
  2030     [
  2033     [
  2031         stream := aFileName asFilename newReadWriteStream.
  2034 	stream := aFileName asFilename newReadWriteStream.
  2032     ] on:FileStream openErrorSignal do:[:ex|
  2035     ] on:FileStream openErrorSignal do:[:ex|
  2033         ^ Image fileCreationErrorSignal
  2036 	^ Image fileCreationErrorSignal
  2034             raiseWith:something
  2037 	    raiseWith:something
  2035             errorString:('file creation error: ' , aFileName asString).
  2038 	    errorString:('file creation error: ' , aFileName asString).
  2036     ].
  2039     ].
  2037 
  2040 
  2038     [
  2041     [
  2039         [
  2042 	[
  2040             aBlock value: stream
  2043 	    aBlock value: stream
  2041         ] ensure:[
  2044 	] ensure:[
  2042             stream close.
  2045 	    stream close.
  2043         ].
  2046 	].
  2044     ] ifCurtailed:[
  2047     ] ifCurtailed:[
  2045         OperatingSystem accessDeniedErrorSignal 
  2048 	OperatingSystem accessDeniedErrorSignal
  2046             handle:[:ex |] 
  2049 	    handle:[:ex |]
  2047             do:[
  2050 	    do:[
  2048                 aFileName asFilename delete.
  2051 		aFileName asFilename delete.
  2049             ]
  2052 	    ]
  2050     ].
  2053     ].
  2051 ! !
  2054 ! !
  2052 
  2055 
  2053 !ImageReader methodsFor:'initialization'!
  2056 !ImageReader methodsFor:'initialization'!
  2054 
  2057 
  2106 ! !
  2109 ! !
  2107 
  2110 
  2108 !ImageReader class methodsFor:'documentation'!
  2111 !ImageReader class methodsFor:'documentation'!
  2109 
  2112 
  2110 version
  2113 version
  2111     ^ '$Header: /cvs/stx/stx/libview/ImageReader.st,v 1.114 2015-02-09 16:58:13 cg Exp $'
  2114     ^ '$Header$'
  2112 !
  2115 !
  2113 
  2116 
  2114 version_CVS
  2117 version_CVS
  2115     ^ '$Header: /cvs/stx/stx/libview/ImageReader.st,v 1.114 2015-02-09 16:58:13 cg Exp $'
  2118     ^ '$Header$'
  2116 ! !
  2119 ! !
  2117