1 /*****************************************************************************/ 2 // TGATranslator 3 // Written by Michael Wilber, Haiku Translation Kit Team 4 // 5 // TGATranslator.cpp 6 // 7 // This BTranslator based object is for opening and writing TGA files. 8 // 9 // 10 // Copyright (c) 2002 Haiku, Inc. 11 // 12 // Permission is hereby granted, free of charge, to any person obtaining a 13 // copy of this software and associated documentation files (the "Software"), 14 // to deal in the Software without restriction, including without limitation 15 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 // and/or sell copies of the Software, and to permit persons to whom the 17 // Software is furnished to do so, subject to the following conditions: 18 // 19 // The above copyright notice and this permission notice shall be included 20 // in all copies or substantial portions of the Software. 21 // 22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 23 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 // DEALINGS IN THE SOFTWARE. 29 /*****************************************************************************/ 30 31 #include <string.h> 32 #include <stdio.h> 33 #include "TGATranslator.h" 34 #include "TGAView.h" 35 #include "StreamBuffer.h" 36 37 // The input formats that this translator supports. 38 translation_format gInputFormats[] = { 39 { 40 B_TRANSLATOR_BITMAP, 41 B_TRANSLATOR_BITMAP, 42 BBT_IN_QUALITY, 43 BBT_IN_CAPABILITY, 44 "image/x-be-bitmap", 45 "Be Bitmap Format (TGATranslator)" 46 }, 47 { 48 B_TGA_FORMAT, 49 B_TRANSLATOR_BITMAP, 50 TGA_IN_QUALITY, 51 TGA_IN_CAPABILITY, 52 "image/x-targa", 53 "Targa image" 54 } 55 }; 56 57 // The output formats that this translator supports. 58 translation_format gOutputFormats[] = { 59 { 60 B_TRANSLATOR_BITMAP, 61 B_TRANSLATOR_BITMAP, 62 BBT_OUT_QUALITY, 63 BBT_OUT_CAPABILITY, 64 "image/x-be-bitmap", 65 "Be Bitmap Format (TGATranslator)" 66 }, 67 { 68 B_TGA_FORMAT, 69 B_TRANSLATOR_BITMAP, 70 TGA_OUT_QUALITY, 71 TGA_OUT_CAPABILITY, 72 "image/x-targa", 73 "Targa image" 74 } 75 }; 76 77 // Default settings for the Translator 78 TranSetting gDefaultSettings[] = { 79 {B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false}, 80 {B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}, 81 {TGA_SETTING_RLE, TRAN_SETTING_BOOL, false}, 82 // RLE compression is off by default 83 {TGA_SETTING_IGNORE_ALPHA, TRAN_SETTING_BOOL, false} 84 // Don't ignore the alpha channel by default 85 }; 86 87 // --------------------------------------------------------------- 88 // make_nth_translator 89 // 90 // Creates a TGATranslator object to be used by BTranslatorRoster 91 // 92 // Preconditions: 93 // 94 // Parameters: n, The translator to return. Since 95 // TGATranslator only publishes one 96 // translator, it only returns a 97 // TGATranslator if n == 0 98 // 99 // you, The image_id of the add-on that 100 // contains code (not used). 101 // 102 // flags, Has no meaning yet, should be 0. 103 // 104 // Postconditions: 105 // 106 // Returns: NULL if n is not zero, 107 // a new TGATranslator if n is zero 108 // --------------------------------------------------------------- 109 BTranslator * 110 make_nth_translator(int32 n, image_id you, uint32 flags, ...) 111 { 112 BTranslator *ptranslator = NULL; 113 if (!n) 114 ptranslator = new TGATranslator(); 115 116 return ptranslator; 117 } 118 119 // --------------------------------------------------------------- 120 // Constructor 121 // 122 // Sets up the version info and the name of the translator so that 123 // these values can be returned when they are requested. 124 // 125 // Preconditions: 126 // 127 // Parameters: 128 // 129 // Postconditions: 130 // 131 // Returns: 132 // --------------------------------------------------------------- 133 TGATranslator::TGATranslator() 134 : BaseTranslator("TGA Images", "TGA image translator", 135 TGA_TRANSLATOR_VERSION, 136 gInputFormats, sizeof(gInputFormats) / sizeof(translation_format), 137 gOutputFormats, sizeof(gOutputFormats) / sizeof(translation_format), 138 "TGATranslator_Settings", 139 gDefaultSettings, sizeof(gDefaultSettings) / sizeof(TranSetting), 140 B_TRANSLATOR_BITMAP, B_TGA_FORMAT) 141 { 142 } 143 144 // --------------------------------------------------------------- 145 // Destructor 146 // 147 // Does nothing 148 // 149 // Preconditions: 150 // 151 // Parameters: 152 // 153 // Postconditions: 154 // 155 // Returns: 156 // --------------------------------------------------------------- 157 // 158 // NOTE: It may be the case, that under Be's libtranslation.so, 159 // that this destructor will never be called 160 TGATranslator::~TGATranslator() 161 { 162 } 163 164 uint8 165 TGATranslator::tga_alphabits(TGAFileHeader &filehead, TGAColorMapSpec &mapspec, 166 TGAImageSpec &imagespec) 167 { 168 if (fSettings->SetGetBool(TGA_SETTING_IGNORE_ALPHA)) 169 return 0; 170 else { 171 uint8 nalpha; 172 if (filehead.imagetype == TGA_NOCOMP_COLORMAP || 173 filehead.imagetype == TGA_RLE_COLORMAP) { 174 // color mapped images 175 176 if (mapspec.entrysize == 32) 177 nalpha = 8; 178 else if (mapspec.entrysize == 16) 179 nalpha = 1; 180 else 181 nalpha = 0; 182 183 } else { 184 // non-color mapped images 185 186 if (imagespec.depth == 32) 187 // Some programs that generate 32-bit TGA files 188 // have an alpha channel, but have an incorrect 189 // descriptor which says there are no alpha bits. 190 // This logic is so that the alpha data can be 191 // obtained from TGA files that lie. 192 nalpha = 8; 193 else 194 nalpha = imagespec.descriptor & TGA_DESC_ALPHABITS; 195 } 196 197 return nalpha; 198 } 199 } 200 201 // --------------------------------------------------------------- 202 // identify_tga_header 203 // 204 // Determines if the data in inSource is in the TGA format. 205 // If it is, it returns info about the data in inSource 206 // to outInfo, pfileheader, pmapspec and pimagespec. 207 // 208 // Preconditions: 209 // 210 // Parameters: inSource, The source of the image data 211 // 212 // outInfo, Information about the translator 213 // is copied here 214 // 215 // pfileheader, File header info for the TGA is 216 // copied here after it is read from 217 // the file. 218 // 219 // pmapspec, color map info for the TGA is copied 220 // here after it is read from the file 221 // 222 // pimagespec, Info about the image width/height etc. 223 // is copied here after it is read from 224 // the file 225 // 226 // 227 // Postconditions: 228 // 229 // Returns: B_NO_TRANSLATOR, if the data does not look like 230 // TGA format data 231 // 232 // B_ERROR, if the header data could not be converted to host 233 // format 234 // 235 // B_OK, if the data looks like bits data and no errors were 236 // encountered 237 // --------------------------------------------------------------- 238 status_t 239 identify_tga_header(BPositionIO *inSource, translator_info *outInfo, 240 TGAFileHeader *pfileheader = NULL, TGAColorMapSpec *pmapspec = NULL, 241 TGAImageSpec *pimagespec = NULL) 242 { 243 uint8 buf[TGA_HEADERS_SIZE]; 244 245 // read in the rest of the TGA headers 246 ssize_t size = TGA_HEADERS_SIZE; 247 if (size > 0 && inSource->Read(buf, size) != size) 248 return B_NO_TRANSLATOR; 249 250 // Read in TGA file header 251 TGAFileHeader fileheader; 252 fileheader.idlength = buf[0]; 253 254 fileheader.colormaptype = buf[1]; 255 if (fileheader.colormaptype > 1) 256 return B_NO_TRANSLATOR; 257 258 fileheader.imagetype = buf[2]; 259 if ((fileheader.imagetype > 3 && fileheader.imagetype < 9) || 260 fileheader.imagetype > 11) 261 return B_NO_TRANSLATOR; 262 if ((fileheader.colormaptype == TGA_NO_COLORMAP && 263 fileheader.imagetype == TGA_NOCOMP_COLORMAP) || 264 (fileheader.colormaptype == TGA_COLORMAP && 265 fileheader.imagetype != TGA_NOCOMP_COLORMAP && 266 fileheader.imagetype != TGA_RLE_COLORMAP)) 267 return B_NO_TRANSLATOR; 268 269 // Read in TGA color map spec 270 TGAColorMapSpec mapspec; 271 memcpy(&mapspec.firstentry, buf + 3, 2); 272 mapspec.firstentry = B_LENDIAN_TO_HOST_INT16(mapspec.firstentry); 273 if (fileheader.colormaptype == 0 && mapspec.firstentry != 0) 274 return B_NO_TRANSLATOR; 275 276 memcpy(&mapspec.length, buf + 5, 2); 277 mapspec.length = B_LENDIAN_TO_HOST_INT16(mapspec.length); 278 if (fileheader.colormaptype == TGA_NO_COLORMAP && 279 mapspec.length != 0) 280 return B_NO_TRANSLATOR; 281 if (fileheader.colormaptype == TGA_COLORMAP && 282 mapspec.length == 0) 283 return B_NO_TRANSLATOR; 284 285 mapspec.entrysize = buf[7]; 286 if (fileheader.colormaptype == TGA_NO_COLORMAP && 287 mapspec.entrysize != 0) 288 return B_NO_TRANSLATOR; 289 if (fileheader.colormaptype == TGA_COLORMAP && 290 mapspec.entrysize != 15 && mapspec.entrysize != 16 && 291 mapspec.entrysize != 24 && mapspec.entrysize != 32) 292 return B_NO_TRANSLATOR; 293 294 // Read in TGA image spec 295 TGAImageSpec imagespec; 296 memcpy(&imagespec.xorigin, buf + 8, 2); 297 imagespec.xorigin = B_LENDIAN_TO_HOST_INT16(imagespec.xorigin); 298 299 memcpy(&imagespec.yorigin, buf + 10, 2); 300 imagespec.yorigin = B_LENDIAN_TO_HOST_INT16(imagespec.yorigin); 301 302 memcpy(&imagespec.width, buf + 12, 2); 303 imagespec.width = B_LENDIAN_TO_HOST_INT16(imagespec.width); 304 if (imagespec.width == 0) 305 return B_NO_TRANSLATOR; 306 307 memcpy(&imagespec.height, buf + 14, 2); 308 imagespec.height = B_LENDIAN_TO_HOST_INT16(imagespec.height); 309 if (imagespec.height == 0) 310 return B_NO_TRANSLATOR; 311 312 imagespec.depth = buf[16]; 313 if (imagespec.depth < 1 || imagespec.depth > 32) 314 return B_NO_TRANSLATOR; 315 if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR || 316 fileheader.imagetype == TGA_RLE_TRUECOLOR) && 317 imagespec.depth != 15 && imagespec.depth != 16 && 318 imagespec.depth != 24 && imagespec.depth != 32) 319 return B_NO_TRANSLATOR; 320 if ((fileheader.imagetype == TGA_NOCOMP_BW || 321 fileheader.imagetype == TGA_RLE_BW) && 322 imagespec.depth != 8) 323 return B_NO_TRANSLATOR; 324 if (fileheader.colormaptype == TGA_COLORMAP && 325 imagespec.depth != 8) 326 return B_NO_TRANSLATOR; 327 328 imagespec.descriptor = buf[17]; 329 // images ordered from Right to Left (rather than Left to Right) 330 // are not supported 331 if (imagespec.descriptor & TGA_ORIGIN_HORZ_BIT == TGA_ORIGIN_RIGHT) 332 return B_NO_TRANSLATOR; 333 // unused descriptor bits, these bits must be zero 334 if (imagespec.descriptor & TGA_DESC_BITS76) 335 return B_NO_TRANSLATOR; 336 if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR || 337 fileheader.imagetype == TGA_RLE_TRUECOLOR) && 338 imagespec.depth == 32 && 339 imagespec.descriptor & TGA_DESC_ALPHABITS != 8 && 340 imagespec.descriptor & TGA_DESC_ALPHABITS != 0) 341 return B_NO_TRANSLATOR; 342 if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR || 343 fileheader.imagetype == TGA_RLE_TRUECOLOR) && 344 imagespec.depth == 24 && 345 imagespec.descriptor & TGA_DESC_ALPHABITS != 0) 346 return B_NO_TRANSLATOR; 347 if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR || 348 fileheader.imagetype == TGA_RLE_TRUECOLOR) && 349 imagespec.depth == 16 && 350 imagespec.descriptor & TGA_DESC_ALPHABITS != 1 && 351 imagespec.descriptor & TGA_DESC_ALPHABITS != 0) 352 if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR || 353 fileheader.imagetype == TGA_RLE_TRUECOLOR) && 354 imagespec.depth == 15 && 355 imagespec.descriptor & TGA_DESC_ALPHABITS != 0) 356 return B_NO_TRANSLATOR; 357 358 // Fill in headers passed to this function 359 if (pfileheader) { 360 pfileheader->idlength = fileheader.idlength; 361 pfileheader->colormaptype = fileheader.colormaptype; 362 pfileheader->imagetype = fileheader.imagetype; 363 } 364 if (pmapspec) { 365 pmapspec->firstentry = mapspec.firstentry; 366 pmapspec->length = mapspec.length; 367 pmapspec->entrysize = mapspec.entrysize; 368 } 369 if (pimagespec) { 370 pimagespec->xorigin = imagespec.xorigin; 371 pimagespec->yorigin = imagespec.yorigin; 372 pimagespec->width = imagespec.width; 373 pimagespec->height = imagespec.height; 374 pimagespec->depth = imagespec.depth; 375 pimagespec->descriptor = imagespec.descriptor; 376 } 377 378 if (outInfo) { 379 outInfo->type = B_TGA_FORMAT; 380 outInfo->group = B_TRANSLATOR_BITMAP; 381 outInfo->quality = TGA_IN_QUALITY; 382 outInfo->capability = TGA_IN_CAPABILITY; 383 sprintf(outInfo->name, "Targa image (%d bits", 384 imagespec.depth); 385 switch (fileheader.imagetype) { 386 case TGA_NOCOMP_COLORMAP: 387 strcat(outInfo->name, " colormap"); 388 break; 389 case TGA_NOCOMP_TRUECOLOR: 390 strcat(outInfo->name, " truecolor"); 391 break; 392 case TGA_NOCOMP_BW: 393 strcat(outInfo->name, " gray"); 394 break; 395 case TGA_RLE_COLORMAP: 396 strcat(outInfo->name, " RLE colormap"); 397 break; 398 case TGA_RLE_TRUECOLOR: 399 strcat(outInfo->name, " RLE truecolor"); 400 break; 401 case TGA_RLE_BW: 402 strcat(outInfo->name, " RLE gray"); 403 break; 404 } 405 strcat(outInfo->name, ")"); 406 strcpy(outInfo->MIME, "image/x-targa"); 407 } 408 409 return B_OK; 410 } 411 412 status_t 413 TGATranslator::DerivedIdentify(BPositionIO *inSource, 414 const translation_format *inFormat, BMessage *ioExtension, 415 translator_info *outInfo, uint32 outType) 416 { 417 return identify_tga_header(inSource, outInfo); 418 } 419 420 // Convert width pixels from pbits to TGA format, storing the 421 // result in ptga 422 status_t 423 pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace, 424 uint16 width, const color_map *pmap, int32 bitsBytesPerPixel) 425 { 426 status_t bytescopied = 0; 427 428 switch (fromspace) { 429 case B_RGBA32: 430 bytescopied = width * 4; 431 memcpy(ptga, pbits, bytescopied); 432 break; 433 434 case B_RGBA32_BIG: 435 bytescopied = width * 4; 436 while (width--) { 437 ptga[0] = pbits[3]; 438 ptga[1] = pbits[2]; 439 ptga[2] = pbits[1]; 440 ptga[3] = pbits[0]; 441 442 ptga += 4; 443 pbits += 4; 444 } 445 break; 446 447 case B_CMYA32: 448 bytescopied = width * 4; 449 while (width--) { 450 ptga[0] = 255 - pbits[2]; 451 ptga[1] = 255 - pbits[1]; 452 ptga[2] = 255 - pbits[0]; 453 ptga[3] = pbits[3]; 454 455 ptga += 4; 456 pbits += 4; 457 } 458 break; 459 460 case B_RGB32: 461 case B_RGB24: 462 bytescopied = width * 3; 463 while (width--) { 464 memcpy(ptga, pbits, 3); 465 466 ptga += 3; 467 pbits += bitsBytesPerPixel; 468 } 469 break; 470 471 case B_CMYK32: 472 { 473 int32 comp; 474 bytescopied = width * 3; 475 while (width--) { 476 comp = 255 - pbits[2] - pbits[3]; 477 ptga[0] = (comp < 0) ? 0 : comp; 478 479 comp = 255 - pbits[1] - pbits[3]; 480 ptga[1] = (comp < 0) ? 0 : comp; 481 482 comp = 255 - pbits[0] - pbits[3]; 483 ptga[2] = (comp < 0) ? 0 : comp; 484 485 ptga += 3; 486 pbits += 4; 487 } 488 break; 489 } 490 491 case B_CMY32: 492 case B_CMY24: 493 bytescopied = width * 3; 494 while (width--) { 495 ptga[0] = 255 - pbits[2]; 496 ptga[1] = 255 - pbits[1]; 497 ptga[2] = 255 - pbits[0]; 498 499 ptga += 3; 500 pbits += bitsBytesPerPixel; 501 } 502 break; 503 504 case B_RGB16: 505 case B_RGB16_BIG: 506 { 507 // Expand to 24 bit because the TGA format handles 508 // 16 bit images differently than the Be Image Format 509 // which would cause a loss in quality 510 uint16 val; 511 bytescopied = width * 3; 512 while (width--) { 513 if (fromspace == B_RGB16) 514 val = pbits[0] + (pbits[1] << 8); 515 else 516 val = pbits[1] + (pbits[0] << 8); 517 518 ptga[0] = 519 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 520 ptga[1] = 521 ((val & 0x7e0) >> 3) | ((val & 0x7e0) >> 9); 522 ptga[2] = 523 ((val & 0xf800) >> 8) | ((val & 0xf800) >> 13); 524 525 ptga += 3; 526 pbits += 2; 527 } 528 break; 529 } 530 531 case B_RGBA15: 532 bytescopied = width * 2; 533 memcpy(ptga, pbits, bytescopied); 534 break; 535 536 case B_RGBA15_BIG: 537 bytescopied = width * 2; 538 while (width--) { 539 ptga[0] = pbits[1]; 540 ptga[1] = pbits[0]; 541 542 ptga += 2; 543 pbits += 2; 544 } 545 break; 546 547 case B_RGB15: 548 bytescopied = width * 2; 549 while (width--) { 550 ptga[0] = pbits[0]; 551 ptga[1] = pbits[1] | 0x80; 552 // alpha bit is always 1 553 554 ptga += 2; 555 pbits += 2; 556 } 557 break; 558 559 case B_RGB15_BIG: 560 bytescopied = width * 2; 561 while (width--) { 562 ptga[0] = pbits[1]; 563 ptga[1] = pbits[0] | 0x80; 564 // alpha bit is always 1 565 566 ptga += 2; 567 pbits += 2; 568 } 569 break; 570 571 case B_RGB32_BIG: 572 bytescopied = width * 3; 573 while (width--) { 574 ptga[0] = pbits[3]; 575 ptga[1] = pbits[2]; 576 ptga[2] = pbits[1]; 577 578 ptga += 3; 579 pbits += 4; 580 } 581 break; 582 583 case B_RGB24_BIG: 584 bytescopied = width * 3; 585 while (width--) { 586 ptga[0] = pbits[2]; 587 ptga[1] = pbits[1]; 588 ptga[2] = pbits[0]; 589 590 ptga += 3; 591 pbits += 3; 592 } 593 break; 594 595 case B_CMAP8: 596 { 597 rgb_color c; 598 bytescopied = width * 3; 599 while (width--) { 600 c = pmap->color_list[pbits[0]]; 601 ptga[0] = c.blue; 602 ptga[1] = c.green; 603 ptga[2] = c.red; 604 605 ptga += 3; 606 pbits++; 607 } 608 break; 609 } 610 611 case B_GRAY8: 612 // NOTE: this code assumes that the 613 // destination TGA color space is either 614 // 8 bit indexed color or 8 bit grayscale 615 bytescopied = width; 616 memcpy(ptga, pbits, bytescopied); 617 break; 618 619 default: 620 bytescopied = B_ERROR; 621 break; 622 } // switch (fromspace) 623 624 return bytescopied; 625 } 626 627 // create a TGA RLE packet for pixel and copy the 628 // packet header and pixel data to ptga 629 status_t 630 copy_rle_packet(uint8 *ptga, uint32 pixel, uint8 count, 631 color_space fromspace, const color_map *pmap, 632 int32 bitsBytesPerPixel) 633 { 634 // copy packet header 635 // (made of type and count) 636 uint8 packethead = (count - 1) | 0x80; 637 ptga[0] = packethead; 638 ptga++; 639 640 return pix_bits_to_tga(reinterpret_cast<uint8 *> (&pixel), 641 ptga, fromspace, 1, pmap, bitsBytesPerPixel) + 1; 642 } 643 644 // create a TGA raw packet for pixel and copy the 645 // packet header and pixel data to ptga 646 status_t 647 copy_raw_packet(uint8 *ptga, uint8 *praw, uint8 count, 648 color_space fromspace, const color_map *pmap, 649 int32 bitsBytesPerPixel) 650 { 651 // copy packet header 652 // (made of type and count) 653 uint8 packethead = count - 1; 654 ptga[0] = packethead; 655 ptga++; 656 657 return pix_bits_to_tga(praw, ptga, fromspace, 658 count, pmap, bitsBytesPerPixel) + 1; 659 } 660 661 // convert a row of pixel data from pbits to a 662 // row of pixel data in the TGA format using 663 // Run Length Encoding 664 status_t 665 pix_bits_to_tgarle(uint8 *pbits, uint8 *ptga, color_space fromspace, 666 uint16 width, const color_map *pmap, int32 bitsBytesPerPixel) 667 { 668 if (width == 0) 669 return B_ERROR; 670 671 uint32 current = 0, next = 0, aftnext = 0; 672 uint16 nread = 0; 673 status_t result, bytescopied = 0; 674 uint8 *prawbuf, *praw; 675 prawbuf = new uint8[bitsBytesPerPixel * 128]; 676 praw = prawbuf; 677 if (!prawbuf) 678 return B_ERROR; 679 680 uint8 rlecount = 1, rawcount = 0; 681 bool bJustWroteRLE = false; 682 683 memcpy(¤t, pbits, bitsBytesPerPixel); 684 pbits += bitsBytesPerPixel; 685 if (width == 1) { 686 result = copy_raw_packet(ptga, 687 reinterpret_cast<uint8 *> (¤t), 1, 688 fromspace, pmap, bitsBytesPerPixel); 689 690 ptga += result; 691 bytescopied += result; 692 nread++; 693 // don't enter the while loop 694 695 } else { 696 memcpy(&next, pbits, bitsBytesPerPixel); 697 pbits += bitsBytesPerPixel; 698 nread++; 699 } 700 701 while (nread < width) { 702 703 if (nread < width - 1) { 704 memcpy(&aftnext, pbits, bitsBytesPerPixel); 705 pbits += bitsBytesPerPixel; 706 } 707 nread++; 708 709 // RLE Packet Creation 710 if (current == next && !bJustWroteRLE) { 711 rlecount++; 712 713 if (next != aftnext || nread == width || rlecount == 128) { 714 result = copy_rle_packet(ptga, current, rlecount, 715 fromspace, pmap, bitsBytesPerPixel); 716 717 ptga += result; 718 bytescopied += result; 719 rlecount = 1; 720 bJustWroteRLE = true; 721 } 722 723 // RAW Packet Creation 724 } else { 725 726 if (!bJustWroteRLE) { 727 // output the current pixel only if 728 // it was not just written out in an RLE packet 729 rawcount++; 730 memcpy(praw, ¤t, bitsBytesPerPixel); 731 praw += bitsBytesPerPixel; 732 } 733 734 if (nread == width) { 735 // if in the last iteration of the loop, 736 // "next" will be the last pixel in the row, 737 // and will need to be written out for this 738 // special case 739 740 if (rawcount == 128) { 741 result = copy_raw_packet(ptga, prawbuf, rawcount, 742 fromspace, pmap, bitsBytesPerPixel); 743 744 ptga += result; 745 bytescopied += result; 746 praw = prawbuf; 747 rawcount = 0; 748 } 749 750 rawcount++; 751 memcpy(praw, &next, bitsBytesPerPixel); 752 praw += bitsBytesPerPixel; 753 } 754 755 if ((!bJustWroteRLE && next == aftnext) || 756 nread == width || rawcount == 128) { 757 result = copy_raw_packet(ptga, prawbuf, rawcount, 758 fromspace, pmap, bitsBytesPerPixel); 759 760 ptga += result; 761 bytescopied += result; 762 praw = prawbuf; 763 rawcount = 0; 764 } 765 766 bJustWroteRLE = false; 767 } 768 769 current = next; 770 next = aftnext; 771 } 772 773 delete[] prawbuf; 774 prawbuf = NULL; 775 776 return bytescopied; 777 } 778 779 // --------------------------------------------------------------- 780 // translate_from_bits_to_tgatc 781 // 782 // Converts various varieties of the Be Bitmap format ('bits') to 783 // the TGA True Color format (RLE or uncompressed) 784 // 785 // Preconditions: 786 // 787 // Parameters: inSource, contains the bits data to convert 788 // 789 // outDestination, where the TGA data will be written 790 // 791 // fromspace, the format of the data in inSource 792 // 793 // imagespec, info about width / height / etc. of 794 // the image 795 // 796 // brle, output using RLE if true, uncompressed 797 // if false 798 // 799 // 800 // Postconditions: 801 // 802 // Returns: B_ERROR, if memory couldn't be allocated or another 803 // error occured 804 // 805 // B_OK, if no errors occurred 806 // --------------------------------------------------------------- 807 status_t 808 translate_from_bits_to_tgatc(BPositionIO *inSource, 809 BPositionIO *outDestination, color_space fromspace, 810 TGAImageSpec &imagespec, bool brle) 811 { 812 int32 bitsBytesPerPixel = 0; 813 switch (fromspace) { 814 case B_RGB32: 815 case B_RGB32_BIG: 816 case B_RGBA32: 817 case B_RGBA32_BIG: 818 case B_CMY32: 819 case B_CMYA32: 820 case B_CMYK32: 821 bitsBytesPerPixel = 4; 822 break; 823 824 case B_RGB24: 825 case B_RGB24_BIG: 826 case B_CMY24: 827 bitsBytesPerPixel = 3; 828 break; 829 830 case B_RGB16: 831 case B_RGB16_BIG: 832 case B_RGBA15: 833 case B_RGBA15_BIG: 834 case B_RGB15: 835 case B_RGB15_BIG: 836 bitsBytesPerPixel = 2; 837 break; 838 839 case B_CMAP8: 840 case B_GRAY8: 841 bitsBytesPerPixel = 1; 842 break; 843 844 default: 845 return B_ERROR; 846 } 847 int32 bitsRowBytes = imagespec.width * bitsBytesPerPixel; 848 uint8 tgaBytesPerPixel = (imagespec.depth / 8) + 849 ((imagespec.depth % 8) ? 1 : 0); 850 int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel) + 851 (imagespec.width / 2); 852 uint32 tgapixrow = 0; 853 uint8 *tgaRowData = new uint8[tgaRowBytes]; 854 if (!tgaRowData) 855 return B_ERROR; 856 uint8 *bitsRowData = new uint8[bitsRowBytes]; 857 if (!bitsRowData) { 858 delete[] tgaRowData; 859 tgaRowData = NULL; 860 return B_ERROR; 861 } 862 863 // conversion function pointer, points to either 864 // RLE or normal TGA conversion function 865 status_t (*convert_to_tga)(uint8 *pbits, uint8 *ptga, 866 color_space fromspace, uint16 width, const color_map *pmap, 867 int32 bitsBytesPerPixel); 868 869 if (brle) 870 convert_to_tga = pix_bits_to_tgarle; 871 else 872 convert_to_tga = pix_bits_to_tga; 873 874 ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes); 875 const color_map *pmap = NULL; 876 if (fromspace == B_CMAP8) { 877 pmap = system_colors(); 878 if (!pmap) 879 return B_ERROR; 880 } 881 while (rd == bitsRowBytes) { 882 status_t bytescopied; 883 bytescopied = convert_to_tga(bitsRowData, tgaRowData, fromspace, 884 imagespec.width, pmap, bitsBytesPerPixel); 885 886 outDestination->Write(tgaRowData, bytescopied); 887 tgapixrow++; 888 // if I've read all of the pixel data, break 889 // out of the loop so I don't try to read 890 // non-pixel data 891 if (tgapixrow == imagespec.height) 892 break; 893 894 rd = inSource->Read(bitsRowData, bitsRowBytes); 895 } // while (rd == bitsRowBytes) 896 897 delete[] bitsRowData; 898 bitsRowData = NULL; 899 delete[] tgaRowData; 900 tgaRowData = NULL; 901 902 return B_OK; 903 } 904 905 // --------------------------------------------------------------- 906 // translate_from_bits1_to_tgabw 907 // 908 // Converts 1-bit Be Bitmaps ('bits') to the 909 // black and white (8-bit grayscale) TGA format 910 // 911 // Preconditions: 912 // 913 // Parameters: inSource, contains the bits data to convert 914 // 915 // outDestination, where the TGA data will be written 916 // 917 // bitsRowBytes, number of bytes in one row of 918 // bits data 919 // 920 // imagespec, info about width / height / etc. of 921 // the image 922 // 923 // brle, output using RLE if true, uncompressed 924 // if false 925 // 926 // 927 // Postconditions: 928 // 929 // Returns: B_ERROR, if memory couldn't be allocated or another 930 // error occured 931 // 932 // B_OK, if no errors occurred 933 // --------------------------------------------------------------- 934 status_t 935 translate_from_bits1_to_tgabw(BPositionIO *inSource, 936 BPositionIO *outDestination, int32 bitsRowBytes, 937 TGAImageSpec &imagespec, bool brle) 938 { 939 uint8 tgaBytesPerPixel = 1; 940 int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel) + 941 (imagespec.width / 2); 942 uint32 tgapixrow = 0; 943 uint8 *tgaRowData = new uint8[tgaRowBytes]; 944 if (!tgaRowData) 945 return B_ERROR; 946 947 uint8 *medRowData = new uint8[imagespec.width]; 948 if (!medRowData) { 949 delete[] tgaRowData; 950 tgaRowData = NULL; 951 return B_ERROR; 952 } 953 uint8 *bitsRowData = new uint8[bitsRowBytes]; 954 if (!bitsRowData) { 955 delete[] medRowData; 956 medRowData = NULL; 957 delete[] tgaRowData; 958 tgaRowData = NULL; 959 return B_ERROR; 960 } 961 962 // conversion function pointer, points to either 963 // RLE or normal TGA conversion function 964 status_t (*convert_to_tga)(uint8 *pbits, uint8 *ptga, 965 color_space fromspace, uint16 width, const color_map *pmap, 966 int32 bitsBytesPerPixel); 967 968 if (brle) 969 convert_to_tga = pix_bits_to_tgarle; 970 else 971 convert_to_tga = pix_bits_to_tga; 972 973 ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes); 974 while (rd == bitsRowBytes) { 975 uint32 tgapixcol = 0; 976 for (int32 i = 0; (tgapixcol < imagespec.width) && 977 (i < bitsRowBytes); i++) { 978 // process each byte in the row 979 uint8 pixels = bitsRowData[i]; 980 for (uint8 compbit = 128; (tgapixcol < imagespec.width) && 981 compbit; compbit >>= 1) { 982 // for each bit in the current byte, convert to a TGA palette 983 // index and store that in the tgaRowData 984 if (pixels & compbit) 985 // black 986 medRowData[tgapixcol] = 0; 987 else 988 // white 989 medRowData[tgapixcol] = 255; 990 tgapixcol++; 991 } 992 } 993 994 status_t bytescopied; 995 bytescopied = convert_to_tga(medRowData, tgaRowData, B_GRAY8, 996 imagespec.width, NULL, 1); 997 998 outDestination->Write(tgaRowData, bytescopied); 999 tgapixrow++; 1000 // if I've read all of the pixel data, break 1001 // out of the loop so I don't try to read 1002 // non-pixel data 1003 if (tgapixrow == imagespec.height) 1004 break; 1005 1006 rd = inSource->Read(bitsRowData, bitsRowBytes); 1007 } // while (rd == bitsRowBytes) 1008 1009 delete[] bitsRowData; 1010 bitsRowData = NULL; 1011 delete[] medRowData; 1012 medRowData = NULL; 1013 delete[] tgaRowData; 1014 tgaRowData = NULL; 1015 1016 return B_OK; 1017 } 1018 1019 // --------------------------------------------------------------- 1020 // write_tga_headers 1021 // 1022 // Writes the TGA headers to outDestination. 1023 // 1024 // Preconditions: 1025 // 1026 // Parameters: outDestination, where the headers are written to 1027 // 1028 // fileheader, TGA file header 1029 // 1030 // mapspec, color map information 1031 // 1032 // imagespec, width / height / etc. info 1033 // 1034 // 1035 // Postconditions: 1036 // 1037 // Returns: B_ERROR, if something went wrong 1038 // 1039 // B_OK, if there were no problems writing out the headers 1040 // --------------------------------------------------------------- 1041 status_t 1042 write_tga_headers(BPositionIO *outDestination, TGAFileHeader &fileheader, 1043 TGAColorMapSpec &mapspec, TGAImageSpec &imagespec) 1044 { 1045 uint8 tgaheaders[TGA_HEADERS_SIZE]; 1046 1047 // Convert host format headers to Little Endian (Intel) byte order 1048 TGAFileHeader outFileheader; 1049 outFileheader.idlength = fileheader.idlength; 1050 outFileheader.colormaptype = fileheader.colormaptype; 1051 outFileheader.imagetype = fileheader.imagetype; 1052 1053 TGAColorMapSpec outMapspec; 1054 outMapspec.firstentry = B_HOST_TO_LENDIAN_INT16(mapspec.firstentry); 1055 outMapspec.length = B_HOST_TO_LENDIAN_INT16(mapspec.length); 1056 outMapspec.entrysize = mapspec.entrysize; 1057 1058 TGAImageSpec outImagespec; 1059 outImagespec.xorigin = B_HOST_TO_LENDIAN_INT16(imagespec.xorigin); 1060 outImagespec.yorigin = B_HOST_TO_LENDIAN_INT16(imagespec.yorigin); 1061 outImagespec.width = B_HOST_TO_LENDIAN_INT16(imagespec.width); 1062 outImagespec.height = B_HOST_TO_LENDIAN_INT16(imagespec.height); 1063 outImagespec.depth = imagespec.depth; 1064 outImagespec.descriptor = imagespec.descriptor; 1065 1066 // Copy TGA headers to buffer to be written out 1067 // all at once 1068 tgaheaders[0] = outFileheader.idlength; 1069 tgaheaders[1] = outFileheader.colormaptype; 1070 tgaheaders[2] = outFileheader.imagetype; 1071 1072 memcpy(tgaheaders + 3, &outMapspec.firstentry, 2); 1073 memcpy(tgaheaders + 5, &outMapspec.length, 2); 1074 tgaheaders[7] = outMapspec.entrysize; 1075 1076 memcpy(tgaheaders + 8, &outImagespec.xorigin, 2); 1077 memcpy(tgaheaders + 10, &outImagespec.yorigin, 2); 1078 memcpy(tgaheaders + 12, &outImagespec.width, 2); 1079 memcpy(tgaheaders + 14, &outImagespec.height, 2); 1080 tgaheaders[16] = outImagespec.depth; 1081 tgaheaders[17] = outImagespec.descriptor; 1082 1083 ssize_t written; 1084 written = outDestination->Write(tgaheaders, TGA_HEADERS_SIZE); 1085 1086 if (written == TGA_HEADERS_SIZE) 1087 return B_OK; 1088 else 1089 return B_ERROR; 1090 } 1091 1092 // --------------------------------------------------------------- 1093 // write_tga_footer 1094 // 1095 // Writes the TGA footer. This information is contant in this 1096 // code because this translator does not output the developer 1097 // information section of the TGA format. 1098 // 1099 // Preconditions: 1100 // 1101 // Parameters: outDestination, where the headers are written to 1102 // 1103 // 1104 // Postconditions: 1105 // 1106 // Returns: B_ERROR, if something went wrong 1107 // 1108 // B_OK, if there were no problems writing out the headers 1109 // --------------------------------------------------------------- 1110 status_t 1111 write_tga_footer(BPositionIO *outDestination) 1112 { 1113 const int32 kfootersize = 26; 1114 uint8 footer[kfootersize]; 1115 1116 memset(footer, 0, 8); 1117 // set the Extension Area Offset and Developer 1118 // Area Offset to zero (as they are not present) 1119 1120 memcpy(footer + 8, "TRUEVISION-XFILE.", 18); 1121 // copy the string including the '.' and the '\0' 1122 1123 ssize_t written; 1124 written = outDestination->Write(footer, kfootersize); 1125 if (written == kfootersize) 1126 return B_OK; 1127 else 1128 return B_ERROR; 1129 } 1130 1131 // --------------------------------------------------------------- 1132 // translate_from_bits 1133 // 1134 // Convert the data in inSource from the Be Bitmap format ('bits') 1135 // to the format specified in outType (either bits or TGA). 1136 // 1137 // Preconditions: 1138 // 1139 // Parameters: inSource, the bits data to translate 1140 // 1141 // amtread, the amount of data already read from 1142 // inSource 1143 // 1144 // read, pointer to the data already read from 1145 // inSource 1146 // 1147 // 1148 // outType, the type of data to convert to 1149 // 1150 // outDestination, where the output is written to 1151 // 1152 // Postconditions: 1153 // 1154 // Returns: B_NO_TRANSLATOR, if the data is not in a supported 1155 // format 1156 // 1157 // B_ERROR, if there was an error allocating memory or some other 1158 // error 1159 // 1160 // B_OK, if successfully translated the data from the bits format 1161 // --------------------------------------------------------------- 1162 status_t 1163 TGATranslator::translate_from_bits(BPositionIO *inSource, uint32 outType, 1164 BPositionIO *outDestination) 1165 { 1166 TranslatorBitmap bitsHeader; 1167 bool bheaderonly = false, bdataonly = false, brle; 1168 brle = fSettings->SetGetBool(TGA_SETTING_RLE); 1169 1170 status_t result; 1171 result = identify_bits_header(inSource, NULL, &bitsHeader); 1172 if (result != B_OK) 1173 return result; 1174 1175 // Translate B_TRANSLATOR_BITMAP to B_TGA_FORMAT 1176 if (outType == B_TGA_FORMAT) { 1177 // Set up TGA header 1178 TGAFileHeader fileheader; 1179 fileheader.idlength = 0; 1180 fileheader.colormaptype = TGA_NO_COLORMAP; 1181 fileheader.imagetype = 0; 1182 1183 TGAColorMapSpec mapspec; 1184 mapspec.firstentry = 0; 1185 mapspec.length = 0; 1186 mapspec.entrysize = 0; 1187 1188 TGAImageSpec imagespec; 1189 imagespec.xorigin = 0; 1190 imagespec.yorigin = 0; 1191 imagespec.width = static_cast<uint16> (bitsHeader.bounds.Width() + 1); 1192 imagespec.height = static_cast<uint16> (bitsHeader.bounds.Height() + 1); 1193 imagespec.depth = 0; 1194 imagespec.descriptor = TGA_ORIGIN_VERT_BIT; 1195 1196 // determine fileSize / imagesize 1197 switch (bitsHeader.colors) { 1198 1199 // Output to 32-bit True Color TGA (8 bits alpha) 1200 case B_RGBA32: 1201 case B_RGBA32_BIG: 1202 case B_CMYA32: 1203 if (brle) 1204 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1205 else 1206 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1207 imagespec.depth = 32; 1208 imagespec.descriptor |= 8; 1209 // 8 bits of alpha 1210 break; 1211 1212 // Output to 24-bit True Color TGA (no alpha) 1213 case B_RGB32: 1214 case B_RGB32_BIG: 1215 case B_RGB24: 1216 case B_RGB24_BIG: 1217 case B_CMYK32: 1218 case B_CMY32: 1219 case B_CMY24: 1220 if (brle) 1221 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1222 else 1223 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1224 imagespec.depth = 24; 1225 break; 1226 1227 // Output to 16-bit True Color TGA (no alpha) 1228 // (TGA doesn't see 16 bit images as Be does 1229 // so converting 16 bit Be Image to 16-bit TGA 1230 // image would result in loss of quality) 1231 case B_RGB16: 1232 case B_RGB16_BIG: 1233 if (brle) 1234 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1235 else 1236 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1237 imagespec.depth = 24; 1238 break; 1239 1240 // Output to 15-bit True Color TGA (1 bit alpha) 1241 case B_RGB15: 1242 case B_RGB15_BIG: 1243 if (brle) 1244 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1245 else 1246 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1247 imagespec.depth = 16; 1248 imagespec.descriptor |= 1; 1249 // 1 bit of alpha (always opaque) 1250 break; 1251 1252 // Output to 16-bit True Color TGA (1 bit alpha) 1253 case B_RGBA15: 1254 case B_RGBA15_BIG: 1255 if (brle) 1256 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1257 else 1258 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1259 imagespec.depth = 16; 1260 imagespec.descriptor |= 1; 1261 // 1 bit of alpha 1262 break; 1263 1264 // Output to 8-bit Color Mapped TGA 32 bits per color map entry 1265 case B_CMAP8: 1266 fileheader.colormaptype = TGA_COLORMAP; 1267 if (brle) 1268 fileheader.imagetype = TGA_RLE_COLORMAP; 1269 else 1270 fileheader.imagetype = TGA_NOCOMP_COLORMAP; 1271 mapspec.firstentry = 0; 1272 mapspec.length = 256; 1273 mapspec.entrysize = 32; 1274 imagespec.depth = 8; 1275 imagespec.descriptor |= 8; 1276 // the pixel values contain 8 bits of attribute data 1277 break; 1278 1279 // Output to 8-bit Black and White TGA 1280 case B_GRAY8: 1281 case B_GRAY1: 1282 if (brle) 1283 fileheader.imagetype = TGA_RLE_BW; 1284 else 1285 fileheader.imagetype = TGA_NOCOMP_BW; 1286 imagespec.depth = 8; 1287 break; 1288 1289 default: 1290 return B_NO_TRANSLATOR; 1291 } 1292 1293 // write out the TGA headers 1294 if (bheaderonly || (!bheaderonly && !bdataonly)) { 1295 result = write_tga_headers(outDestination, fileheader, 1296 mapspec, imagespec); 1297 if (result != B_OK) 1298 return result; 1299 } 1300 if (bheaderonly) 1301 // if user only wants the header, bail out 1302 // before the data is written 1303 return result; 1304 1305 // write out the TGA pixel data 1306 switch (bitsHeader.colors) { 1307 case B_RGB32: 1308 case B_RGB32_BIG: 1309 case B_RGBA32: 1310 case B_RGBA32_BIG: 1311 case B_RGB24: 1312 case B_RGB24_BIG: 1313 case B_RGB16: 1314 case B_RGB16_BIG: 1315 case B_RGB15: 1316 case B_RGB15_BIG: 1317 case B_RGBA15: 1318 case B_RGBA15_BIG: 1319 case B_CMYK32: 1320 case B_CMY32: 1321 case B_CMYA32: 1322 case B_CMY24: 1323 result = translate_from_bits_to_tgatc(inSource, outDestination, 1324 bitsHeader.colors, imagespec, brle); 1325 break; 1326 1327 case B_CMAP8: 1328 { 1329 // write Be's system palette to the TGA file 1330 uint8 pal[1024]; 1331 const color_map *pmap = system_colors(); 1332 if (!pmap) 1333 return B_ERROR; 1334 for (int32 i = 0; i < 256; i++) { 1335 uint8 *palent = pal + (i * 4); 1336 rgb_color c = pmap->color_list[i]; 1337 palent[0] = c.blue; 1338 palent[1] = c.green; 1339 palent[2] = c.red; 1340 palent[3] = c.alpha; 1341 } 1342 if (outDestination->Write(pal, 1024) != 1024) 1343 return B_ERROR; 1344 1345 result = translate_from_bits_to_tgatc(inSource, outDestination, 1346 B_GRAY8, imagespec, brle); 1347 break; 1348 } 1349 1350 case B_GRAY8: 1351 result = translate_from_bits_to_tgatc(inSource, outDestination, 1352 B_GRAY8, imagespec, brle); 1353 break; 1354 1355 case B_GRAY1: 1356 result = translate_from_bits1_to_tgabw(inSource, outDestination, 1357 bitsHeader.rowBytes, imagespec, brle); 1358 break; 1359 1360 default: 1361 result = B_NO_TRANSLATOR; 1362 break; 1363 } 1364 1365 if (result == B_OK) 1366 result = write_tga_footer(outDestination); 1367 1368 return result; 1369 1370 } else 1371 return B_NO_TRANSLATOR; 1372 } 1373 1374 // convert a row of uncompressed, non-color mapped 1375 // TGA pixels from ptga to pbits 1376 status_t 1377 pix_tganm_to_bits(uint8 *pbits, uint8 *ptga, 1378 uint16 width, uint8 depth, uint8 tgaBytesPerPixel, 1379 uint8 nalpha) 1380 { 1381 status_t result = B_OK; 1382 1383 switch (depth) { 1384 case 32: 1385 if (nalpha == 8 && tgaBytesPerPixel == 4) 1386 memcpy(pbits, ptga, 4 * width); 1387 else if (nalpha == 8) { 1388 // copy the same 32-bit pixel over and over 1389 while (width--) { 1390 memcpy(pbits, ptga, 4); 1391 pbits += 4; 1392 } 1393 } else { 1394 while (width--) { 1395 memcpy(pbits, ptga, 3); 1396 1397 pbits += 4; 1398 ptga += tgaBytesPerPixel; 1399 } 1400 } 1401 break; 1402 1403 case 24: 1404 while (width--) { 1405 memcpy(pbits, ptga, 3); 1406 1407 pbits += 4; 1408 ptga += tgaBytesPerPixel; 1409 } 1410 break; 1411 1412 case 16: 1413 { 1414 uint16 val; 1415 if (nalpha == 1) { 1416 while (width--) { 1417 val = ptga[0] + (ptga[1] << 8); 1418 pbits[0] = 1419 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1420 pbits[1] = 1421 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1422 pbits[2] = 1423 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1424 pbits[3] = (val & 0x8000) ? 255 : 0; 1425 1426 pbits += 4; 1427 ptga += tgaBytesPerPixel; 1428 } 1429 } else { 1430 while (width--) { 1431 val = ptga[0] + (ptga[1] << 8); 1432 pbits[0] = 1433 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1434 pbits[1] = 1435 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1436 pbits[2] = 1437 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1438 1439 pbits += 4; 1440 ptga += tgaBytesPerPixel; 1441 } 1442 } 1443 break; 1444 } 1445 1446 case 15: 1447 { 1448 uint16 val; 1449 while (width--) { 1450 val = ptga[0] + (ptga[1] << 8); 1451 pbits[0] = 1452 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1453 pbits[1] = 1454 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1455 pbits[2] = 1456 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1457 1458 pbits += 4; 1459 ptga += tgaBytesPerPixel; 1460 } 1461 break; 1462 } 1463 1464 case 8: 1465 while (width--) { 1466 memset(pbits, ptga[0], 3); 1467 1468 pbits += 4; 1469 ptga += tgaBytesPerPixel; 1470 } 1471 break; 1472 1473 default: 1474 result = B_ERROR; 1475 break; 1476 } 1477 1478 return result; 1479 } 1480 1481 // --------------------------------------------------------------- 1482 // translate_from_tganm_to_bits 1483 // 1484 // Translates a uncompressed, non-palette TGA from inSource 1485 // to the B_RGB32 or B_RGBA32 bits format. 1486 // 1487 // Preconditions: 1488 // 1489 // Parameters: inSource, the TGA data to be translated 1490 // 1491 // outDestination, where the bits data will be written to 1492 // 1493 // filehead, image type info 1494 // 1495 // mapspec, color map info 1496 // 1497 // imagespec, width / height info 1498 // 1499 // 1500 // 1501 // Postconditions: 1502 // 1503 // Returns: B_ERROR, if there is an error allocating memory 1504 // 1505 // B_OK, if all went well 1506 // --------------------------------------------------------------- 1507 status_t 1508 TGATranslator::translate_from_tganm_to_bits(BPositionIO *inSource, 1509 BPositionIO *outDestination, TGAFileHeader &filehead, 1510 TGAColorMapSpec &mapspec, TGAImageSpec &imagespec) 1511 { 1512 bool bvflip; 1513 if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) 1514 bvflip = false; 1515 else 1516 bvflip = true; 1517 uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec); 1518 int32 bitsRowBytes = imagespec.width * 4; 1519 uint8 tgaBytesPerPixel = (imagespec.depth / 8) + 1520 ((imagespec.depth % 8) ? 1 : 0); 1521 int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel); 1522 uint32 tgapixrow = 0; 1523 1524 // Setup outDestination so that it can be written to 1525 // from the end of the file to the beginning instead of 1526 // the other way around 1527 off_t bitsFileSize = (bitsRowBytes * imagespec.height) + 1528 sizeof(TranslatorBitmap); 1529 if (outDestination->SetSize(bitsFileSize) != B_OK) 1530 // This call should work for BFile and BMallocIO objects, 1531 // but may not work for other BPositionIO based types 1532 return B_ERROR; 1533 off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes; 1534 if (bvflip) 1535 outDestination->Seek(bitsoffset, SEEK_CUR); 1536 1537 // allocate row buffers 1538 uint8 *tgaRowData = new uint8[tgaRowBytes]; 1539 if (!tgaRowData) 1540 return B_ERROR; 1541 uint8 *bitsRowData = new uint8[bitsRowBytes]; 1542 if (!bitsRowData) { 1543 delete[] tgaRowData; 1544 tgaRowData = NULL; 1545 return B_ERROR; 1546 } 1547 1548 // perform the actual translation 1549 memset(bitsRowData, 0xff, bitsRowBytes); 1550 ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes); 1551 while (rd == tgaRowBytes) { 1552 pix_tganm_to_bits(bitsRowData, tgaRowData, 1553 imagespec.width, imagespec.depth, 1554 tgaBytesPerPixel, nalpha); 1555 1556 outDestination->Write(bitsRowData, bitsRowBytes); 1557 tgapixrow++; 1558 // if I've read all of the pixel data, break 1559 // out of the loop so I don't try to read 1560 // non-pixel data 1561 if (tgapixrow == imagespec.height) 1562 break; 1563 1564 if (bvflip) 1565 outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR); 1566 rd = inSource->Read(tgaRowData, tgaRowBytes); 1567 } 1568 1569 delete[] tgaRowData; 1570 tgaRowData = NULL; 1571 delete[] bitsRowData; 1572 bitsRowData = NULL; 1573 1574 return B_OK; 1575 } 1576 1577 // --------------------------------------------------------------- 1578 // translate_from_tganmrle_to_bits 1579 // 1580 // Convert non color map, RLE TGA to Be bitmap format 1581 // and write results to outDestination 1582 // 1583 // Preconditions: 1584 // 1585 // Parameters: inSource, the TGA data to be translated 1586 // 1587 // outDestination, where the bits data will be written to 1588 // 1589 // filehead, image type info 1590 // 1591 // mapspec, color map info 1592 // 1593 // imagespec, width / height info 1594 // 1595 // 1596 // 1597 // Postconditions: 1598 // 1599 // Returns: B_ERROR, if there is an error allocating memory 1600 // 1601 // B_OK, if all went well 1602 // --------------------------------------------------------------- 1603 status_t 1604 TGATranslator::translate_from_tganmrle_to_bits(BPositionIO *inSource, 1605 BPositionIO *outDestination, TGAFileHeader &filehead, 1606 TGAColorMapSpec &mapspec, TGAImageSpec &imagespec) 1607 { 1608 status_t result = B_OK; 1609 1610 bool bvflip; 1611 if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) 1612 bvflip = false; 1613 else 1614 bvflip = true; 1615 uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec); 1616 int32 bitsRowBytes = imagespec.width * 4; 1617 uint8 tgaBytesPerPixel = (imagespec.depth / 8) + 1618 ((imagespec.depth % 8) ? 1 : 0); 1619 uint16 tgapixrow = 0, tgapixcol = 0; 1620 1621 // Setup outDestination so that it can be written to 1622 // from the end of the file to the beginning instead of 1623 // the other way around 1624 off_t bitsFileSize = (bitsRowBytes * imagespec.height) + 1625 sizeof(TranslatorBitmap); 1626 if (outDestination->SetSize(bitsFileSize) != B_OK) 1627 // This call should work for BFile and BMallocIO objects, 1628 // but may not work for other BPositionIO based types 1629 return B_ERROR; 1630 off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes; 1631 if (bvflip) 1632 outDestination->Seek(bitsoffset, SEEK_CUR); 1633 1634 // allocate row buffers 1635 uint8 *bitsRowData = new uint8[bitsRowBytes]; 1636 if (!bitsRowData) 1637 return B_ERROR; 1638 1639 // perform the actual translation 1640 memset(bitsRowData, 0xff, bitsRowBytes); 1641 uint8 *pbitspixel = bitsRowData; 1642 uint8 packethead; 1643 StreamBuffer sbuf(inSource, TGA_STREAM_BUFFER_SIZE, true); 1644 ssize_t rd = 0; 1645 if (sbuf.InitCheck() == B_OK) 1646 rd = sbuf.Read(&packethead, 1); 1647 while (rd == 1) { 1648 // Run Length Packet 1649 if (packethead & TGA_RLE_PACKET_TYPE_BIT) { 1650 uint8 tgapixel[4], rlecount; 1651 rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; 1652 if (tgapixcol + rlecount > imagespec.width) { 1653 result = B_NO_TRANSLATOR; 1654 break; 1655 } 1656 rd = sbuf.Read(tgapixel, tgaBytesPerPixel); 1657 if (rd == tgaBytesPerPixel) { 1658 pix_tganm_to_bits(pbitspixel, tgapixel, 1659 rlecount, imagespec.depth, 0, nalpha); 1660 1661 pbitspixel += 4 * rlecount; 1662 tgapixcol += rlecount; 1663 } else { 1664 result = B_NO_TRANSLATOR; 1665 break; // error 1666 } 1667 1668 // Raw Packet 1669 } else { 1670 uint8 tgaPixelBuf[512], rawcount; 1671 uint16 rawbytes; 1672 rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; 1673 if (tgapixcol + rawcount > imagespec.width) { 1674 result = B_NO_TRANSLATOR; 1675 break; 1676 } 1677 rawbytes = tgaBytesPerPixel * rawcount; 1678 rd = sbuf.Read(tgaPixelBuf, rawbytes); 1679 if (rd == rawbytes) { 1680 pix_tganm_to_bits(pbitspixel, tgaPixelBuf, 1681 rawcount, imagespec.depth, tgaBytesPerPixel, nalpha); 1682 1683 pbitspixel += 4 * rawcount; 1684 tgapixcol += rawcount; 1685 } else { 1686 result = B_NO_TRANSLATOR; 1687 break; 1688 } 1689 } 1690 1691 if (tgapixcol == imagespec.width) { 1692 outDestination->Write(bitsRowData, bitsRowBytes); 1693 tgapixcol = 0; 1694 tgapixrow++; 1695 if (tgapixrow == imagespec.height) 1696 break; 1697 if (bvflip) 1698 outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR); 1699 pbitspixel = bitsRowData; 1700 } 1701 rd = sbuf.Read(&packethead, 1); 1702 } 1703 1704 delete[] bitsRowData; 1705 bitsRowData = NULL; 1706 1707 return result; 1708 } 1709 1710 // convert a row of color mapped pixels to pbits 1711 status_t 1712 pix_tgam_to_bits(uint8 *pbits, uint8 *ptgaindices, 1713 uint16 width, uint8 depth, uint8 *pmap) 1714 { 1715 status_t result = B_OK; 1716 uint8 *ptgapixel = NULL; 1717 1718 switch (depth) { 1719 case 32: 1720 for (uint16 i = 0; i < width; i++) { 1721 ptgapixel = pmap + 1722 (ptgaindices[i] * 4); 1723 1724 memcpy(pbits, ptgapixel, 4); 1725 1726 pbits += 4; 1727 } 1728 break; 1729 1730 case 24: 1731 for (uint16 i = 0; i < width; i++) { 1732 ptgapixel = pmap + 1733 (ptgaindices[i] * 3); 1734 1735 memcpy(pbits, ptgapixel, 3); 1736 1737 pbits += 4; 1738 } 1739 break; 1740 1741 case 16: 1742 for (uint16 i = 0; i < width; i++) { 1743 uint16 val; 1744 1745 ptgapixel = pmap + 1746 (ptgaindices[i] * 2); 1747 val = ptgapixel[0] + (ptgapixel[1] << 8); 1748 pbits[0] = 1749 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1750 pbits[1] = 1751 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1752 pbits[2] = 1753 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1754 pbits[3] = (val & 0x8000) ? 255 : 0; 1755 1756 pbits += 4; 1757 } 1758 break; 1759 1760 case 15: 1761 for (uint16 i = 0; i < width; i++) { 1762 uint16 val; 1763 1764 ptgapixel = pmap + 1765 (ptgaindices[i] * 2); 1766 val = ptgapixel[0] + (ptgapixel[1] << 8); 1767 pbits[0] = 1768 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1769 pbits[1] = 1770 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1771 pbits[2] = 1772 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1773 1774 pbits += 4; 1775 } 1776 break; 1777 1778 default: 1779 result = B_ERROR; 1780 break; 1781 } 1782 1783 return result; 1784 } 1785 1786 // --------------------------------------------------------------- 1787 // translate_from_tgam_to_bits 1788 // 1789 // Translates a paletted TGA from inSource to the bits format. 1790 // 1791 // Preconditions: 1792 // 1793 // Parameters: inSource, the TGA data to be translated 1794 // 1795 // outDestination, where the bits data will be written to 1796 // 1797 // mapspec, info about the color map (palette) 1798 // 1799 // imagespec, width / height info 1800 // 1801 // pmap, color palette 1802 // 1803 // 1804 // Postconditions: 1805 // 1806 // Returns: B_ERROR, if there is an error allocating memory 1807 // 1808 // B_OK, if all went well 1809 // --------------------------------------------------------------- 1810 status_t 1811 translate_from_tgam_to_bits(BPositionIO *inSource, 1812 BPositionIO *outDestination, TGAColorMapSpec &mapspec, 1813 TGAImageSpec &imagespec, uint8 *pmap) 1814 { 1815 bool bvflip; 1816 if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) 1817 bvflip = false; 1818 else 1819 bvflip = true; 1820 1821 int32 bitsRowBytes = imagespec.width * 4; 1822 uint8 tgaBytesPerPixel = (imagespec.depth / 8) + 1823 ((imagespec.depth % 8) ? 1 : 0); 1824 int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel); 1825 uint32 tgapixrow = 0; 1826 1827 // Setup outDestination so that it can be written to 1828 // from the end of the file to the beginning instead of 1829 // the other way around 1830 off_t bitsFileSize = (bitsRowBytes * imagespec.height) + 1831 sizeof(TranslatorBitmap); 1832 if (outDestination->SetSize(bitsFileSize) != B_OK) 1833 // This call should work for BFile and BMallocIO objects, 1834 // but may not work for other BPositionIO based types 1835 return B_ERROR; 1836 off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes; 1837 if (bvflip) 1838 outDestination->Seek(bitsoffset, SEEK_CUR); 1839 1840 // allocate row buffers 1841 uint8 *tgaRowData = new uint8[tgaRowBytes]; 1842 if (!tgaRowData) 1843 return B_ERROR; 1844 uint8 *bitsRowData = new uint8[bitsRowBytes]; 1845 if (!bitsRowData) { 1846 delete[] tgaRowData; 1847 tgaRowData = NULL; 1848 return B_ERROR; 1849 } 1850 1851 // perform the actual translation 1852 memset(bitsRowData, 0xff, bitsRowBytes); 1853 ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes); 1854 while (rd == tgaRowBytes) { 1855 pix_tgam_to_bits(bitsRowData, tgaRowData, 1856 imagespec.width, mapspec.entrysize, pmap); 1857 1858 outDestination->Write(bitsRowData, bitsRowBytes); 1859 tgapixrow++; 1860 // if I've read all of the pixel data, break 1861 // out of the loop so I don't try to read 1862 // non-pixel data 1863 if (tgapixrow == imagespec.height) 1864 break; 1865 1866 if (bvflip) 1867 outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR); 1868 rd = inSource->Read(tgaRowData, tgaRowBytes); 1869 } 1870 1871 delete[] tgaRowData; 1872 tgaRowData = NULL; 1873 delete[] bitsRowData; 1874 bitsRowData = NULL; 1875 1876 return B_OK; 1877 } 1878 1879 // --------------------------------------------------------------- 1880 // translate_from_tgamrle_to_bits 1881 // 1882 // Translates a color mapped or non color mapped RLE TGA from 1883 // inSource to the bits format. 1884 // 1885 // Preconditions: 1886 // 1887 // Parameters: inSource, the TGA data to be translated 1888 // 1889 // outDestination, where the bits data will be written to 1890 // 1891 // filehead, image type info 1892 // 1893 // mapspec, info about the color map (palette) 1894 // 1895 // imagespec, width / height info 1896 // 1897 // pmap, color palette 1898 // 1899 // 1900 // Postconditions: 1901 // 1902 // Returns: B_ERROR, if there is an error allocating memory 1903 // 1904 // B_OK, if all went well 1905 // --------------------------------------------------------------- 1906 status_t 1907 TGATranslator::translate_from_tgamrle_to_bits(BPositionIO *inSource, 1908 BPositionIO *outDestination, TGAFileHeader &filehead, 1909 TGAColorMapSpec &mapspec, TGAImageSpec &imagespec, uint8 *pmap) 1910 { 1911 status_t result = B_OK; 1912 1913 bool bvflip; 1914 if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) 1915 bvflip = false; 1916 else 1917 bvflip = true; 1918 uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec); 1919 int32 bitsRowBytes = imagespec.width * 4; 1920 uint8 tgaPalBytesPerPixel = (mapspec.entrysize / 8) + 1921 ((mapspec.entrysize % 8) ? 1 : 0); 1922 uint8 tgaBytesPerPixel = (imagespec.depth / 8) + 1923 ((imagespec.depth % 8) ? 1 : 0); 1924 uint16 tgapixrow = 0, tgapixcol = 0; 1925 1926 // Setup outDestination so that it can be written to 1927 // from the end of the file to the beginning instead of 1928 // the other way around 1929 off_t bitsFileSize = (bitsRowBytes * imagespec.height) + 1930 sizeof(TranslatorBitmap); 1931 if (outDestination->SetSize(bitsFileSize) != B_OK) 1932 // This call should work for BFile and BMallocIO objects, 1933 // but may not work for other BPositionIO based types 1934 return B_ERROR; 1935 off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes; 1936 if (bvflip) 1937 outDestination->Seek(bitsoffset, SEEK_CUR); 1938 1939 // allocate row buffers 1940 uint8 *bitsRowData = new uint8[bitsRowBytes]; 1941 if (!bitsRowData) 1942 return B_ERROR; 1943 1944 // perform the actual translation 1945 memset(bitsRowData, 0xff, bitsRowBytes); 1946 uint8 *pbitspixel = bitsRowData; 1947 uint8 packethead; 1948 StreamBuffer sbuf(inSource, TGA_STREAM_BUFFER_SIZE, true); 1949 ssize_t rd = 0; 1950 if (sbuf.InitCheck() == B_OK) 1951 rd = sbuf.Read(&packethead, 1); 1952 while (rd == 1) { 1953 // Run Length Packet 1954 if (packethead & TGA_RLE_PACKET_TYPE_BIT) { 1955 uint8 tgaindex, rlecount; 1956 rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; 1957 if (tgapixcol + rlecount > imagespec.width) { 1958 result = B_NO_TRANSLATOR; 1959 break; 1960 } 1961 rd = sbuf.Read(&tgaindex, 1); 1962 if (rd == tgaBytesPerPixel) { 1963 uint8 *ptgapixel; 1964 ptgapixel = pmap + (tgaindex * tgaPalBytesPerPixel); 1965 1966 pix_tganm_to_bits(pbitspixel, ptgapixel, rlecount, 1967 mapspec.entrysize, 0, nalpha); 1968 1969 pbitspixel += 4 * rlecount; 1970 tgapixcol += rlecount; 1971 } else { 1972 result = B_NO_TRANSLATOR; 1973 break; // error 1974 } 1975 1976 // Raw Packet 1977 } else { 1978 uint8 tgaIndexBuf[128], rawcount; 1979 rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; 1980 if (tgapixcol + rawcount > imagespec.width) { 1981 result = B_NO_TRANSLATOR; 1982 break; 1983 } 1984 rd = sbuf.Read(tgaIndexBuf, rawcount); 1985 if (rd == rawcount) { 1986 pix_tgam_to_bits(pbitspixel, tgaIndexBuf, 1987 rawcount, mapspec.entrysize, pmap); 1988 1989 pbitspixel += 4 * rawcount; 1990 tgapixcol += rawcount; 1991 } else { 1992 result = B_NO_TRANSLATOR; 1993 break; 1994 } 1995 } 1996 1997 if (tgapixcol == imagespec.width) { 1998 outDestination->Write(bitsRowData, bitsRowBytes); 1999 tgapixcol = 0; 2000 tgapixrow++; 2001 if (tgapixrow == imagespec.height) 2002 break; 2003 if (bvflip) 2004 outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR); 2005 pbitspixel = bitsRowData; 2006 } 2007 rd = sbuf.Read(&packethead, 1); 2008 } 2009 2010 delete[] bitsRowData; 2011 bitsRowData = NULL; 2012 2013 return result; 2014 } 2015 2016 // --------------------------------------------------------------- 2017 // translate_from_tga 2018 // 2019 // Convert the data in inSource from the TGA format 2020 // to the format specified in outType (either bits or TGA). 2021 // 2022 // Preconditions: 2023 // 2024 // Parameters: inSource, the bits data to translate 2025 // 2026 // amtread, the amount of data already read from 2027 // inSource 2028 // 2029 // read, pointer to the data already read from 2030 // inSource 2031 // 2032 // outType, the type of data to convert to 2033 // 2034 // outDestination, where the output is written to 2035 // 2036 // Postconditions: 2037 // 2038 // Returns: B_NO_TRANSLATOR, if the data is not in a supported 2039 // format 2040 // 2041 // B_ERROR, if there was an error allocating memory or some other 2042 // error 2043 // 2044 // B_OK, if successfully translated the data from the bits format 2045 // --------------------------------------------------------------- 2046 status_t 2047 TGATranslator::translate_from_tga(BPositionIO *inSource, uint32 outType, 2048 BPositionIO *outDestination) 2049 { 2050 TGAFileHeader fileheader; 2051 TGAColorMapSpec mapspec; 2052 TGAImageSpec imagespec; 2053 bool bheaderonly = false, bdataonly = false; 2054 2055 status_t result; 2056 result = identify_tga_header(inSource, NULL, &fileheader, &mapspec, 2057 &imagespec); 2058 if (result != B_OK) 2059 return result; 2060 2061 // if the user wants to translate a TGA to a TGA, easy enough :) 2062 if (outType == B_TGA_FORMAT) { 2063 // write out the TGA headers 2064 if (bheaderonly || (!bheaderonly && !bdataonly)) { 2065 result = write_tga_headers(outDestination, fileheader, 2066 mapspec, imagespec); 2067 if (result != B_OK) 2068 return result; 2069 } 2070 if (bheaderonly) 2071 // if the user only wants the header, 2072 // bail before it is written 2073 return result; 2074 2075 const int32 kbuflen = 1024; 2076 uint8 buf[kbuflen]; 2077 ssize_t rd = inSource->Read(buf, kbuflen); 2078 while (rd > 0) { 2079 outDestination->Write(buf, rd); 2080 rd = inSource->Read(buf, kbuflen); 2081 } 2082 if (rd == 0) 2083 return B_OK; 2084 else 2085 return B_ERROR; 2086 2087 // if translating a TGA to a Be Bitmap 2088 } else if (outType == B_TRANSLATOR_BITMAP) { 2089 TranslatorBitmap bitsHeader; 2090 bitsHeader.magic = B_TRANSLATOR_BITMAP; 2091 bitsHeader.bounds.left = 0; 2092 bitsHeader.bounds.top = 0; 2093 bitsHeader.bounds.right = imagespec.width - 1; 2094 bitsHeader.bounds.bottom = imagespec.height - 1; 2095 2096 // skip over Image ID data (if present) 2097 if (fileheader.idlength > 0) 2098 inSource->Seek(fileheader.idlength, SEEK_CUR); 2099 2100 // read in palette and/or skip non-TGA data 2101 uint8 *ptgapalette = NULL; 2102 if (fileheader.colormaptype == TGA_COLORMAP) { 2103 uint32 nentrybytes; 2104 nentrybytes = mapspec.entrysize / 8; 2105 if (mapspec.entrysize % 8) 2106 nentrybytes++; 2107 ptgapalette = new uint8[nentrybytes * mapspec.length]; 2108 inSource->Read(ptgapalette, nentrybytes * mapspec.length); 2109 } 2110 2111 bitsHeader.rowBytes = imagespec.width * 4; 2112 if (fileheader.imagetype != TGA_NOCOMP_BW && 2113 fileheader.imagetype != TGA_RLE_BW && 2114 tga_alphabits(fileheader, mapspec, imagespec)) 2115 bitsHeader.colors = B_RGBA32; 2116 else 2117 bitsHeader.colors = B_RGB32; 2118 int32 datasize = bitsHeader.rowBytes * imagespec.height; 2119 bitsHeader.dataSize = datasize; 2120 2121 // write out Be's Bitmap header 2122 if (bheaderonly || (!bheaderonly && !bdataonly)) { 2123 if (swap_data(B_UINT32_TYPE, &bitsHeader, 2124 sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) 2125 return B_ERROR; 2126 outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap)); 2127 } 2128 if (bheaderonly) 2129 // if the user only wants the header, 2130 // bail before the data is written 2131 return B_OK; 2132 2133 // write out the actual image data 2134 switch (fileheader.imagetype) { 2135 case TGA_NOCOMP_TRUECOLOR: 2136 case TGA_NOCOMP_BW: 2137 result = translate_from_tganm_to_bits(inSource, 2138 outDestination, fileheader, mapspec, imagespec); 2139 break; 2140 2141 case TGA_NOCOMP_COLORMAP: 2142 result = translate_from_tgam_to_bits(inSource, 2143 outDestination, mapspec, imagespec, ptgapalette); 2144 break; 2145 2146 case TGA_RLE_TRUECOLOR: 2147 case TGA_RLE_BW: 2148 result = translate_from_tganmrle_to_bits(inSource, 2149 outDestination, fileheader, mapspec, imagespec); 2150 break; 2151 2152 case TGA_RLE_COLORMAP: 2153 result = translate_from_tgamrle_to_bits(inSource, outDestination, 2154 fileheader, mapspec, imagespec, ptgapalette); 2155 break; 2156 2157 default: 2158 result = B_NO_TRANSLATOR; 2159 break; 2160 } 2161 2162 delete[] ptgapalette; 2163 ptgapalette = NULL; 2164 2165 return result; 2166 2167 } else 2168 return B_NO_TRANSLATOR; 2169 } 2170 2171 status_t 2172 TGATranslator::DerivedTranslate(BPositionIO *inSource, 2173 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 2174 BPositionIO *outDestination, int32 baseType) 2175 { 2176 if (baseType == 1) 2177 // if inSource is in bits format 2178 return translate_from_bits(inSource, outType, outDestination); 2179 else if (baseType == 0) 2180 // if inSource is NOT in bits format 2181 return translate_from_tga(inSource, outType, outDestination); 2182 else 2183 // if BaseTranslator did not properly identify the data as 2184 // bits or not bits 2185 return B_NO_TRANSLATOR; 2186 } 2187 2188 BView * 2189 TGATranslator::NewConfigView(TranslatorSettings *settings) 2190 { 2191 return new TGAView(BRect(0, 0, 225, 175), "TGATranslator Settings", 2192 B_FOLLOW_ALL, B_WILL_DRAW, settings); 2193 } 2194 2195