1/* 2 * bmp.c -- 3 * 4 * BMP photo image type, Tcl/Tk package 5 * 6 * Copyright (c) 1997-2003 Jan Nijtmans <nijtmans@users.sourceforge.net> 7 * Copyright (c) 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net> 8 * 9 * $Id: bmp.c 233 2010-04-01 09:28:00Z nijtmans $ 10 * 11 */ 12 13/* 14 * Generic initialization code, parameterized via CPACKAGE and PACKAGE. 15 */ 16 17#include <string.h> 18#include "init.c" 19 20/* Compression types */ 21#define BI_RGB 0 22#define BI_RLE8 1 23#define BI_RLE4 2 24#define BI_BITFIELDS 3 25 26/* Structure for reading bit masks for compression type BI_BITFIELDS */ 27typedef struct { 28 unsigned int mask; 29 unsigned int shiftin; 30 unsigned int shiftout; 31} BitmapChannel; 32 33/* 34 * Now the implementation 35 */ 36/* 37 * Prototypes for local procedures defined in this file: 38 */ 39 40static int CommonMatch(tkimg_MFile *handle, int *widthPtr, 41 int *heightPtr, unsigned char **colorMap, int *numBits, 42 int *numCols, int *comp, unsigned int *mask); 43 44static int CommonRead(Tcl_Interp *interp, tkimg_MFile *handle, 45 Tk_PhotoHandle imageHandle, int destX, int destY, int width, 46 int height, int srcX, int srcY); 47 48static int CommonWrite(Tcl_Interp *interp, tkimg_MFile *handle, 49 Tk_PhotoImageBlock *blockPtr); 50 51static void putint(tkimg_MFile *handle, int i); 52 53/* 54 * Entrypoints for the photo image type. 55 */ 56 57static int 58ChnMatch( 59 Tcl_Channel chan, 60 const char *fileName, 61 Tcl_Obj *format, 62 int *widthPtr, 63 int *heightPtr, 64 Tcl_Interp *interp 65) { 66 tkimg_MFile handle; 67 68 handle.data = (char *) chan; 69 handle.state = IMG_CHAN; 70 71 return CommonMatch(&handle, widthPtr, heightPtr, 72 NULL, NULL, NULL, NULL, NULL); 73} 74 75static int 76ObjMatch( 77 Tcl_Obj *data, 78 Tcl_Obj *format, 79 int *widthPtr, 80 int *heightPtr, 81 Tcl_Interp *interp 82) { 83 tkimg_MFile handle; 84 85 if (!tkimg_ReadInit(data, 'B', &handle)) { 86 return 0; 87 } 88 return CommonMatch(&handle, widthPtr, heightPtr, 89 NULL, NULL, NULL, NULL, NULL); 90} 91 92static int 93ChnRead(interp, chan, fileName, format, imageHandle, 94 destX, destY, width, height, srcX, srcY) 95 Tcl_Interp *interp; 96 Tcl_Channel chan; 97 const char *fileName; 98 Tcl_Obj *format; 99 Tk_PhotoHandle imageHandle; 100 int destX, destY; 101 int width, height; 102 int srcX, srcY; 103{ 104 tkimg_MFile handle; 105 106 handle.data = (char *) chan; 107 handle.state = IMG_CHAN; 108 109 return CommonRead(interp, &handle, imageHandle, destX, destY, 110 width, height, srcX, srcY); 111} 112 113static int 114ObjRead(interp, data, format, imageHandle, 115 destX, destY, width, height, srcX, srcY) 116 Tcl_Interp *interp; 117 Tcl_Obj *data; 118 Tcl_Obj *format; 119 Tk_PhotoHandle imageHandle; 120 int destX, destY; 121 int width, height; 122 int srcX, srcY; 123{ 124 tkimg_MFile handle; 125 126 tkimg_ReadInit(data,'B',&handle); 127 return CommonRead(interp, &handle, imageHandle, destX, destY, 128 width, height, srcX, srcY); 129} 130 131static int 132ChnWrite(interp, filename, format, blockPtr) 133 Tcl_Interp *interp; 134 const char *filename; 135 Tcl_Obj *format; 136 Tk_PhotoImageBlock *blockPtr; 137{ 138 Tcl_Channel chan; 139 tkimg_MFile handle; 140 int result; 141 142 chan = tkimg_OpenFileChannel(interp, filename, 0644); 143 if (!chan) { 144 return TCL_ERROR; 145 } 146 147 handle.data = (char *) chan; 148 handle.state = IMG_CHAN; 149 150 result = CommonWrite(interp, &handle, blockPtr); 151 if (Tcl_Close(interp, chan) == TCL_ERROR) { 152 return TCL_ERROR; 153 } 154 return result; 155} 156 157static int StringWrite( 158 Tcl_Interp *interp, 159 Tcl_Obj *format, 160 Tk_PhotoImageBlock *blockPtr 161) { 162 tkimg_MFile handle; 163 int result; 164 Tcl_DString data; 165 166 Tcl_DStringInit(&data); 167 tkimg_WriteInit(&data, &handle); 168 result = CommonWrite(interp, &handle, blockPtr); 169 tkimg_Putc(IMG_DONE, &handle); 170 171 if (result == TCL_OK) { 172 Tcl_DStringResult(interp, &data); 173 } else { 174 Tcl_DStringFree(&data); 175 } 176 return result; 177} 178 179static unsigned int 180getUInt32(buf) 181 unsigned char *buf; 182{ 183 return (buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24); 184} 185 186static unsigned int 187getUInt16(buf) 188 unsigned char *buf; 189{ 190 return (buf[0] | buf[1] << 8); 191} 192 193static void 194GetChannelMasks(intMask, masks) 195 unsigned int *intMask; 196 BitmapChannel *masks; 197{ 198 unsigned int mask; 199 int i, nbits, offset, bit; 200 201 for (i=0; i<3; i++) { 202 mask = getUInt32((unsigned char *) &intMask[i]); 203 masks[i].mask = mask; 204 nbits = 0; 205 offset = -1; 206 for (bit=0; bit<32; bit++) { 207 if (mask & 1) { 208 nbits++; 209 if (offset == -1) { 210 offset = bit; 211 } 212 } 213 mask = mask >> 1; 214 } 215 masks[i].shiftin = offset; 216 masks[i].shiftout = 8 - nbits; 217 } 218} 219 220/* 221 * Helper functions for the entry points. Work horses. 222 */ 223 224static int 225CommonMatch(handle, widthPtr, heightPtr, colorMap, numBits, numCols, comp, mask) 226 tkimg_MFile *handle; 227 int *widthPtr, *heightPtr; 228 unsigned char **colorMap; 229 int *numBits, *numCols, *comp; 230 unsigned int *mask; 231{ 232 unsigned char buf[28]; 233 int c,i, compression, nBits, clrUsed, offBits; 234 235 if ((tkimg_Read(handle, (char *) buf, 2) != 2) 236 || (strncmp("BM", (char *) buf, 2) != 0) 237 || (tkimg_Read(handle, (char *) buf, 24) != 24) 238 || buf[13] || buf[14] || buf[15]) { 239 return 0; 240 } 241 242 offBits = (buf[11]<<24) + (buf[10]<<16) + (buf[9]<<8) + buf[8]; 243 c = buf[12]; 244 if ((c == 40) || (c == 64)) { 245 *widthPtr = (buf[19]<<24) + (buf[18]<<16) + (buf[17]<<8) + buf[16]; 246 *heightPtr = (buf[23]<<24) + (buf[22]<<16) + (buf[21]<<8) + buf[20]; 247 if (tkimg_Read(handle, (char *) buf, 24) != 24) { 248 return 0; 249 } 250 nBits = buf[2]; 251 compression = buf[4]; 252 clrUsed = (buf[21]<<8) + buf[20]; 253 offBits -= c+14; 254 } else if (c == 12) { 255 *widthPtr = (buf[17]<<8) + buf[16]; 256 *heightPtr = (buf[19]<<8) + buf[18]; 257 nBits = buf[22]; 258 compression = BI_RGB; 259 clrUsed = 0; 260 } else { 261 return 0; 262 } 263 if (*widthPtr <= 0 || *heightPtr <= 0) 264 return 0; 265 266 if (colorMap) { 267 if (c > 36) tkimg_Read(handle, (char *) buf, c - 36); 268 if (compression == BI_BITFIELDS) { 269 /* Read the channel masks. */ 270 tkimg_Read(handle, (char *) buf, 3*4); 271 if (mask) { 272 mask[0] = getUInt32((unsigned char *) &buf[0]); 273 mask[1] = getUInt32((unsigned char *) &buf[4]); 274 mask[2] = getUInt32((unsigned char *) &buf[8]); 275 } 276 offBits -= 3*4; 277 } 278 if (!clrUsed && nBits < 24) { 279 clrUsed = 1 << nBits; 280 } 281 if (nBits<16) { 282 unsigned char colbuf[4], *ptr; 283 offBits -= (3+(c!=12)) * clrUsed; 284 *colorMap = ptr = (unsigned char *) ckalloc(3*clrUsed); 285 for (i = 0; i < clrUsed; i++) { 286 tkimg_Read(handle, (char *) colbuf, 3+(c!=12)); 287 *ptr++ = colbuf[0]; *ptr++ = colbuf[1]; *ptr++ = colbuf[2]; 288 /*printf("color %d: %d %d %d\n", i, colbuf[2], colbuf[1], colbuf[0]);*/ 289 } 290 } 291 while (offBits>28) { 292 offBits -= 28; 293 tkimg_Read(handle, (char *) buf, 28); 294 } 295 if (offBits) tkimg_Read(handle, (char *) buf, offBits); 296 if (numCols) { 297 *numCols = clrUsed; 298 } 299 } 300 if (numBits) { 301 *numBits = nBits; 302 } 303 if (comp) { 304 *comp = compression; 305 } 306 return 1; 307} 308 309static int 310CommonRead(interp, handle, imageHandle, destX, destY, 311 width, height, srcX, srcY) 312 Tcl_Interp *interp; 313 tkimg_MFile *handle; 314 Tk_PhotoHandle imageHandle; 315 int destX, destY; 316 int width, height; 317 int srcX, srcY; 318{ 319 Tk_PhotoImageBlock block; 320 int numBits, bytesPerLine, numCols, comp, x, y; 321 int fileWidth, fileHeight; 322 unsigned char *colorMap = NULL; 323 unsigned int intMask[3]; 324 BitmapChannel masks[3]; 325 char buf[10]; 326 unsigned char *line = NULL, *expline = NULL; 327 unsigned short rgb; 328 329 CommonMatch(handle, &fileWidth, &fileHeight, &colorMap, &numBits, 330 &numCols, &comp, intMask); 331 332 if (numBits == 16) { 333 if (comp == BI_BITFIELDS) { 334 GetChannelMasks(intMask, masks); 335 } else { 336 masks[0].mask = 0x7c00; 337 masks[0].shiftin = 10; 338 masks[0].shiftout = 3; 339 masks[1].mask = 0x03e0; 340 masks[1].shiftin = 5; 341 masks[1].shiftout = 3; 342 masks[2].mask = 0x001f; 343 masks[2].shiftin = 0; 344 masks[2].shiftout = 3; 345 } 346 } 347 348 /* printf("reading %d-bit BMP %dx%d\n", numBits, width, height); */ 349 if (comp == BI_RLE8 || comp == BI_RLE4) { 350 tkimg_ReadBuffer(1); 351 } 352 353 if (tkimg_PhotoExpand(interp, imageHandle, destX + width, destY + height) == TCL_ERROR) { 354 goto error; 355 } 356 357 bytesPerLine = ((numBits * fileWidth + 31)/32)*4; 358 359 /* printf("bytesPerLine = %d numBits=%d (%dx%d)\n", 360 * bytesPerLine, numBits, width, height); 361 */ 362 block.pixelSize = 3; 363 block.pitch = width * 3; 364 block.width = width; 365 block.height = 1; 366 block.offset[0] = 2; 367 block.offset[1] = 1; 368 block.offset[2] = 0; 369 block.offset[3] = block.offset[0]; 370 371 if (comp == BI_RGB || comp == BI_BITFIELDS) { /* No compression */ 372 line = (unsigned char *) ckalloc(bytesPerLine); 373 for(y=srcY+height; y<fileHeight; y++) { 374 tkimg_Read(handle, (char *)line, bytesPerLine); 375 } 376 switch (numBits) { 377 case 32: 378 block.pixelPtr = expline = (unsigned char *) ckalloc(3*width); 379 for( y = height-1; y>=0; y--) { 380 tkimg_Read(handle, (char *)line, bytesPerLine); 381 for (x = srcX; x < (srcX+width); x++) { 382 *expline++ = line[x*4 + 0]; 383 *expline++ = line[x*4 + 1]; 384 *expline++ = line[x*4 + 2]; 385 } 386 if (tkimg_PhotoPutBlock(interp, imageHandle, &block, 387 destX, destY+y, width, 1, TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) { 388 goto error; 389 } 390 expline = block.pixelPtr; 391 } 392 break; 393 case 24: 394 block.pixelPtr = line + srcX*3; 395 for( y = height-1; y>=0; y--) { 396 tkimg_Read(handle, (char *)line, bytesPerLine); 397 if (tkimg_PhotoPutBlock(interp, imageHandle, &block, 398 destX, destY+y, width, 1, TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) { 399 goto error; 400 } 401 } 402 break; 403 case 16: 404 block.pixelPtr = expline = (unsigned char *) ckalloc(3*width); 405 for( y = height-1; y>=0; y--) { 406 tkimg_Read(handle, (char *)line, bytesPerLine); 407 for (x = srcX; x < (srcX+width); x++) { 408 rgb = getUInt16 (&line[x*2]); 409 *expline++ = ((rgb & masks[2].mask) >> masks[2].shiftin) << masks[2].shiftout; 410 *expline++ = ((rgb & masks[1].mask) >> masks[1].shiftin) << masks[1].shiftout; 411 *expline++ = ((rgb & masks[0].mask) >> masks[0].shiftin) << masks[0].shiftout; 412 } 413 if (tkimg_PhotoPutBlock(interp, imageHandle, &block, 414 destX, destY+y, width, 1, TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) { 415 goto error; 416 } 417 expline = block.pixelPtr; 418 } 419 break; 420 case 8: 421 block.pixelPtr = expline = (unsigned char *) ckalloc(3*width); 422 for( y = height-1; y>=0; y--) { 423 tkimg_Read(handle, (char *)line, bytesPerLine); 424 for (x = srcX; x < (srcX+width); x++) { 425 memcpy(expline, colorMap+(3*line[x]),3); 426 expline += 3; 427 } 428 if (tkimg_PhotoPutBlock(interp, imageHandle, &block, 429 destX, destY+y, width, 1, TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) { 430 goto error; 431 } 432 expline = block.pixelPtr; 433 } 434 break; 435 case 4: 436 block.pixelPtr = expline = (unsigned char *) ckalloc(3*width); 437 for( y = height-1; y>=0; y--) { 438 int c; 439 tkimg_Read(handle, (char *)line, bytesPerLine); 440 for (x = srcX; x < (srcX+width); x++) { 441 if (x&1) { 442 c = line[x/2] & 0x0f; 443 } else { 444 c = line[x/2] >> 4; 445 } 446 memcpy(expline, colorMap+(3*c),3); 447 expline += 3; 448 } 449 if (tkimg_PhotoPutBlock(interp, imageHandle, &block, 450 destX, destY+y, width, 1, TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) { 451 goto error; 452 } 453 expline = block.pixelPtr; 454 } 455 break; 456 case 1: 457 block.pixelPtr = expline = (unsigned char *) ckalloc(3*width); 458 for( y = height-1; y>=0; y--) { 459 int c; 460 tkimg_Read(handle, (char *)line, bytesPerLine); 461 for (x = srcX; x < (srcX+width); x++) { 462 c = (line[x/8] >> (7-(x%8))) & 1; 463 memcpy(expline, colorMap+(3*c),3); 464 expline += 3; 465 } 466 if (tkimg_PhotoPutBlock(interp, imageHandle, &block, 467 destX, destY+y, width, 1, TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) { 468 goto error; 469 } 470 expline = block.pixelPtr; 471 } 472 break; 473 default: 474 sprintf(buf,"%d", numBits); 475 Tcl_AppendResult(interp, buf, 476 "-bits BMP file not (yet) supported", (char *) NULL); 477 goto error; 478 } 479 } else { /* RLE Compression */ 480 int i, j, c; 481 unsigned char howMuch; 482 unsigned char rleBuf[2]; 483 unsigned char rleDelta[2]; 484 unsigned char val; 485 486 x = srcX; 487 y = fileHeight - 1; 488 block.pixelPtr = expline = (unsigned char *) ckalloc (3*fileWidth); 489 490 if (numBits != 4 && numBits != 8) { 491 sprintf (buf, "%d", numBits); 492 Tcl_AppendResult(interp, "RLE compression not supported for ", 493 buf, "-bit pixel values", (char *) NULL); 494 goto error; 495 } 496 497 while (1) { 498 if (2 != tkimg_Read(handle, (char *)rleBuf, 2)) { 499 Tcl_AppendResult(interp, "Unexpected EOF", (char *) NULL); 500 goto error; 501 } 502 /* printf("In: (%d %X) --> \n", rleBuf[0], rleBuf[1]); */ 503 if (rleBuf[0] != 0) { 504 howMuch = rleBuf[0]; 505 switch (numBits) { 506 case 8: { 507 for (i=0; i<howMuch; i++, x++) { 508 memcpy (expline, colorMap + 3*rleBuf[1], 3); 509 expline += 3; 510 } 511 break; 512 } 513 case 4: { 514 for (i=0; i<howMuch; i++, x++) { 515 if (x&1) { 516 c = rleBuf[1] & 0x0f; 517 } else { 518 c = rleBuf[1] >> 4; 519 } 520 memcpy(expline, colorMap + 3*c, 3); 521 if (x>=srcX+width-1) { 522 break; 523 } 524 expline += 3; 525 } 526 break; 527 } 528 } 529 } else { 530 if (rleBuf[1]>2) { 531 /* uncompressed record */ 532 howMuch = rleBuf[1]; 533 /* printf ("Uncompressed: %d\n", howMuch); fflush (stdout); */ 534 switch (numBits) { 535 case 8: { 536 for (i=0; i<howMuch; i++, x++) { 537 if (1 != tkimg_Read(handle, (char *)&val, 1)) { 538 Tcl_AppendResult(interp, "Unexpected EOF", (char *)NULL); 539 goto error; 540 } 541 memcpy(expline, colorMap + 3*val, 3); 542 expline += 3; 543 } 544 break; 545 } 546 case 4: { 547 for (i=0; i<howMuch; i+=2) { 548 if (1 != tkimg_Read(handle, (char *)&val, 1)) { 549 Tcl_AppendResult(interp, "Unexpected EOF", (char *)NULL); 550 goto error; 551 } 552 for (j=0; j<2; j++, x++) { 553 if (x&1) { 554 c = val & 0x0f; 555 } else { 556 c = val >> 4; 557 } 558 memcpy(expline, colorMap + 3*c, 3); 559 if (x>=srcX+width-1) { 560 break; 561 } 562 expline += 3; 563 } 564 } 565 break; 566 } 567 } 568 569 if ((howMuch % 2) && (numBits==4)) { 570 howMuch++; 571 } 572 573 if ((howMuch / (8 / numBits)) % 2) { 574 if (1 != tkimg_Read(handle, (char *)&val, 1)) { 575 Tcl_AppendResult(interp, "Unexpected EOF", (char *)NULL); 576 goto error; 577 } 578 } 579 } else if (rleBuf[1]==0) { 580 /* End of line */ 581 /* printf("New line: y=%d x=%d\n", y, x); fflush(stdout); */ 582 if (tkimg_PhotoPutBlock(interp, imageHandle, &block, destX, destY+y, 583 width, 1, TK_PHOTO_COMPOSITE_SET) == TCL_ERROR) { 584 goto error; 585 } 586 y--; 587 x = srcX; 588 expline = block.pixelPtr; 589 } else if (rleBuf[1]==1) { 590 /* End of bitmap */ 591 break; 592 } else if (rleBuf[1]==2) { 593 /* Deltarecord */ 594 /* printf("Deltarecord\n"); fflush(stdout); */ 595 if (2 != tkimg_Read(handle, (char *) rleDelta, 2)) { 596 Tcl_AppendResult(interp, "Unexpected EOF", (char *) NULL); 597 goto error; 598 } 599 x += rleDelta[0]; 600 y += rleDelta[1]; 601 } 602 } 603 } 604 } 605 tkimg_ReadBuffer(0); 606 607 if (colorMap) { 608 ckfree((char *) colorMap); 609 } 610 if (line) { 611 ckfree((char *) line); 612 } 613 if (expline) { 614 ckfree((char *) block.pixelPtr); 615 } 616 return TCL_OK ; 617 618error: 619 tkimg_ReadBuffer(0); 620 if (colorMap) { 621 ckfree((char *) colorMap); 622 } 623 if (line) { 624 ckfree((char *) line); 625 } 626 if (expline) { 627 ckfree((char *) block.pixelPtr); 628 } 629 return TCL_ERROR; 630} 631 632static int 633CommonWrite(interp, handle, blockPtr) 634 Tcl_Interp *interp; 635 tkimg_MFile *handle; 636 Tk_PhotoImageBlock *blockPtr; 637{ 638 int bperline, nbytes, ncolors, i, x, y, greenOffset, blueOffset, alphaOffset; 639 unsigned char *imagePtr, *pixelPtr; 640 unsigned char buf[4]; 641 int colors[256]; 642 643 greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; 644 blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; 645 alphaOffset = blockPtr->offset[0]; 646 if (alphaOffset < blockPtr->offset[2]) { 647 alphaOffset = blockPtr->offset[2]; 648 } 649 if (++alphaOffset < blockPtr->pixelSize) { 650 alphaOffset -= blockPtr->offset[0]; 651 } else { 652 alphaOffset = 0; 653 } 654 ncolors = 0; 655 if (greenOffset || blueOffset) { 656 for (y = 0; ncolors <= 256 && y < blockPtr->height; y++) { 657 pixelPtr = blockPtr->pixelPtr + y*blockPtr->pitch + blockPtr->offset[0]; 658 for (x=0; ncolors <= 256 && x<blockPtr->width; x++) { 659 int pixel; 660 if (alphaOffset && (pixelPtr[alphaOffset] == 0)) 661 pixel = 0xd9d9d9; 662 else 663 pixel = (pixelPtr[0]<<16) | (pixelPtr[greenOffset]<<8) | pixelPtr[blueOffset]; 664 for (i = 0; i < ncolors && pixel != colors[i]; i++); 665 if (i == ncolors) { 666 if (ncolors < 256) { 667 colors[ncolors] = pixel; 668 } 669 ncolors++; 670 } 671 pixelPtr += blockPtr->pixelSize; 672 } 673 } 674 if (ncolors <= 256 && (blockPtr->width * blockPtr->height >= 512)) { 675 while (ncolors < 256) { 676 colors[ncolors++] = 0; 677 } 678 nbytes = 1; 679 } else { 680 nbytes = 3; 681 ncolors = 0; 682 } 683 } else { 684 nbytes = 1; 685 } 686 687 bperline = ((blockPtr->width * nbytes + 3) / 4) * 4; 688 689 tkimg_Write(handle,"BM", 2); 690 putint(handle, 54 + (ncolors*4) + bperline * blockPtr->height); 691 putint(handle, 0); 692 putint(handle, 54 + (ncolors*4)); 693 putint(handle, 40); 694 putint(handle, blockPtr->width); 695 putint(handle, blockPtr->height); 696 putint(handle, 1 + (nbytes<<19)); 697 putint(handle, 0); 698 putint(handle, bperline * blockPtr->height); 699 putint(handle, 75*39); 700 putint(handle, 75*39); 701 putint(handle, ncolors); 702 putint(handle, ncolors); 703 704 for (i = 0; i < ncolors ; i++) { 705 putint(handle, colors[i]); 706 } 707 708 bperline -= blockPtr->width * nbytes; 709 710 imagePtr = blockPtr->pixelPtr + blockPtr->offset[0] 711 + blockPtr->height * blockPtr->pitch; 712 for (y = 0; y < blockPtr->height; y++) { 713 pixelPtr = imagePtr -= blockPtr->pitch; 714 for (x=0; x<blockPtr->width; x++) { 715 if (ncolors) { 716 int pixel; 717 if (alphaOffset && (pixelPtr[alphaOffset] == 0)) 718 pixel = 0xd9d9d9; 719 else 720 pixel = (pixelPtr[0]<<16)|(pixelPtr[greenOffset]<<8)|pixelPtr[blueOffset]; 721 for (i = 0; i < ncolors && pixel != colors[i]; i += 1); 722 buf[0] = i; 723 } else if (alphaOffset && (pixelPtr[alphaOffset] == 0)) { 724 buf[0] = buf[1] = buf[2] = 0xd9; 725 } else { 726 buf[0] = pixelPtr[blueOffset]; 727 buf[1] = pixelPtr[greenOffset]; 728 buf[2] = pixelPtr[0]; 729 } 730 tkimg_Write(handle, (char *) buf, nbytes); 731 pixelPtr += blockPtr->pixelSize; 732 } 733 if (bperline) { 734 tkimg_Write(handle, "\0\0\0", bperline); 735 } 736 } 737 return(TCL_OK); 738} 739 740static void 741putint(handle, i) 742 tkimg_MFile *handle; 743 int i; 744{ 745 unsigned char buf[4]; 746 buf[0] = i; 747 buf[1] = i>>8; 748 buf[2] = i>>16; 749 buf[3] = i>>24; 750 tkimg_Write(handle, (char *) buf, 4); 751} 752