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-2009, Haiku, Inc. All rights reserved. 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 delete[] tgaRowData; 880 delete[] bitsRowData; 881 return B_ERROR; 882 } 883 } 884 while (rd == bitsRowBytes) { 885 status_t bytescopied; 886 bytescopied = convert_to_tga(bitsRowData, tgaRowData, fromspace, 887 imagespec.width, pmap, bitsBytesPerPixel); 888 889 outDestination->Write(tgaRowData, bytescopied); 890 tgapixrow++; 891 // if I've read all of the pixel data, break 892 // out of the loop so I don't try to read 893 // non-pixel data 894 if (tgapixrow == imagespec.height) 895 break; 896 897 rd = inSource->Read(bitsRowData, bitsRowBytes); 898 } // while (rd == bitsRowBytes) 899 900 delete[] bitsRowData; 901 bitsRowData = NULL; 902 delete[] tgaRowData; 903 tgaRowData = NULL; 904 905 return B_OK; 906 } 907 908 // --------------------------------------------------------------- 909 // translate_from_bits1_to_tgabw 910 // 911 // Converts 1-bit Be Bitmaps ('bits') to the 912 // black and white (8-bit grayscale) TGA format 913 // 914 // Preconditions: 915 // 916 // Parameters: inSource, contains the bits data to convert 917 // 918 // outDestination, where the TGA data will be written 919 // 920 // bitsRowBytes, number of bytes in one row of 921 // bits data 922 // 923 // imagespec, info about width / height / etc. of 924 // the image 925 // 926 // brle, output using RLE if true, uncompressed 927 // if false 928 // 929 // 930 // Postconditions: 931 // 932 // Returns: B_ERROR, if memory couldn't be allocated or another 933 // error occured 934 // 935 // B_OK, if no errors occurred 936 // --------------------------------------------------------------- 937 status_t 938 translate_from_bits1_to_tgabw(BPositionIO *inSource, 939 BPositionIO *outDestination, int32 bitsRowBytes, 940 TGAImageSpec &imagespec, bool brle) 941 { 942 uint8 tgaBytesPerPixel = 1; 943 int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel) + 944 (imagespec.width / 2); 945 uint32 tgapixrow = 0; 946 uint8 *tgaRowData = new uint8[tgaRowBytes]; 947 if (!tgaRowData) 948 return B_ERROR; 949 950 uint8 *medRowData = new uint8[imagespec.width]; 951 if (!medRowData) { 952 delete[] tgaRowData; 953 tgaRowData = NULL; 954 return B_ERROR; 955 } 956 uint8 *bitsRowData = new uint8[bitsRowBytes]; 957 if (!bitsRowData) { 958 delete[] medRowData; 959 medRowData = NULL; 960 delete[] tgaRowData; 961 tgaRowData = NULL; 962 return B_ERROR; 963 } 964 965 // conversion function pointer, points to either 966 // RLE or normal TGA conversion function 967 status_t (*convert_to_tga)(uint8 *pbits, uint8 *ptga, 968 color_space fromspace, uint16 width, const color_map *pmap, 969 int32 bitsBytesPerPixel); 970 971 if (brle) 972 convert_to_tga = pix_bits_to_tgarle; 973 else 974 convert_to_tga = pix_bits_to_tga; 975 976 ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes); 977 while (rd == bitsRowBytes) { 978 uint32 tgapixcol = 0; 979 for (int32 i = 0; (tgapixcol < imagespec.width) && 980 (i < bitsRowBytes); i++) { 981 // process each byte in the row 982 uint8 pixels = bitsRowData[i]; 983 for (uint8 compbit = 128; (tgapixcol < imagespec.width) && 984 compbit; compbit >>= 1) { 985 // for each bit in the current byte, convert to a TGA palette 986 // index and store that in the tgaRowData 987 if (pixels & compbit) 988 // black 989 medRowData[tgapixcol] = 0; 990 else 991 // white 992 medRowData[tgapixcol] = 255; 993 tgapixcol++; 994 } 995 } 996 997 status_t bytescopied; 998 bytescopied = convert_to_tga(medRowData, tgaRowData, B_GRAY8, 999 imagespec.width, NULL, 1); 1000 1001 outDestination->Write(tgaRowData, bytescopied); 1002 tgapixrow++; 1003 // if I've read all of the pixel data, break 1004 // out of the loop so I don't try to read 1005 // non-pixel data 1006 if (tgapixrow == imagespec.height) 1007 break; 1008 1009 rd = inSource->Read(bitsRowData, bitsRowBytes); 1010 } // while (rd == bitsRowBytes) 1011 1012 delete[] bitsRowData; 1013 bitsRowData = NULL; 1014 delete[] medRowData; 1015 medRowData = NULL; 1016 delete[] tgaRowData; 1017 tgaRowData = NULL; 1018 1019 return B_OK; 1020 } 1021 1022 // --------------------------------------------------------------- 1023 // write_tga_headers 1024 // 1025 // Writes the TGA headers to outDestination. 1026 // 1027 // Preconditions: 1028 // 1029 // Parameters: outDestination, where the headers are written to 1030 // 1031 // fileheader, TGA file header 1032 // 1033 // mapspec, color map information 1034 // 1035 // imagespec, width / height / etc. info 1036 // 1037 // 1038 // Postconditions: 1039 // 1040 // Returns: B_ERROR, if something went wrong 1041 // 1042 // B_OK, if there were no problems writing out the headers 1043 // --------------------------------------------------------------- 1044 status_t 1045 write_tga_headers(BPositionIO *outDestination, TGAFileHeader &fileheader, 1046 TGAColorMapSpec &mapspec, TGAImageSpec &imagespec) 1047 { 1048 uint8 tgaheaders[TGA_HEADERS_SIZE]; 1049 1050 // Convert host format headers to Little Endian (Intel) byte order 1051 TGAFileHeader outFileheader; 1052 outFileheader.idlength = fileheader.idlength; 1053 outFileheader.colormaptype = fileheader.colormaptype; 1054 outFileheader.imagetype = fileheader.imagetype; 1055 1056 TGAColorMapSpec outMapspec; 1057 outMapspec.firstentry = B_HOST_TO_LENDIAN_INT16(mapspec.firstentry); 1058 outMapspec.length = B_HOST_TO_LENDIAN_INT16(mapspec.length); 1059 outMapspec.entrysize = mapspec.entrysize; 1060 1061 TGAImageSpec outImagespec; 1062 outImagespec.xorigin = B_HOST_TO_LENDIAN_INT16(imagespec.xorigin); 1063 outImagespec.yorigin = B_HOST_TO_LENDIAN_INT16(imagespec.yorigin); 1064 outImagespec.width = B_HOST_TO_LENDIAN_INT16(imagespec.width); 1065 outImagespec.height = B_HOST_TO_LENDIAN_INT16(imagespec.height); 1066 outImagespec.depth = imagespec.depth; 1067 outImagespec.descriptor = imagespec.descriptor; 1068 1069 // Copy TGA headers to buffer to be written out 1070 // all at once 1071 tgaheaders[0] = outFileheader.idlength; 1072 tgaheaders[1] = outFileheader.colormaptype; 1073 tgaheaders[2] = outFileheader.imagetype; 1074 1075 memcpy(tgaheaders + 3, &outMapspec.firstentry, 2); 1076 memcpy(tgaheaders + 5, &outMapspec.length, 2); 1077 tgaheaders[7] = outMapspec.entrysize; 1078 1079 memcpy(tgaheaders + 8, &outImagespec.xorigin, 2); 1080 memcpy(tgaheaders + 10, &outImagespec.yorigin, 2); 1081 memcpy(tgaheaders + 12, &outImagespec.width, 2); 1082 memcpy(tgaheaders + 14, &outImagespec.height, 2); 1083 tgaheaders[16] = outImagespec.depth; 1084 tgaheaders[17] = outImagespec.descriptor; 1085 1086 ssize_t written; 1087 written = outDestination->Write(tgaheaders, TGA_HEADERS_SIZE); 1088 1089 if (written == TGA_HEADERS_SIZE) 1090 return B_OK; 1091 else 1092 return B_ERROR; 1093 } 1094 1095 // --------------------------------------------------------------- 1096 // write_tga_footer 1097 // 1098 // Writes the TGA footer. This information is contant in this 1099 // code because this translator does not output the developer 1100 // information section of the TGA format. 1101 // 1102 // Preconditions: 1103 // 1104 // Parameters: outDestination, where the headers are written to 1105 // 1106 // 1107 // Postconditions: 1108 // 1109 // Returns: B_ERROR, if something went wrong 1110 // 1111 // B_OK, if there were no problems writing out the headers 1112 // --------------------------------------------------------------- 1113 status_t 1114 write_tga_footer(BPositionIO *outDestination) 1115 { 1116 const int32 kfootersize = 26; 1117 uint8 footer[kfootersize]; 1118 1119 memset(footer, 0, 8); 1120 // set the Extension Area Offset and Developer 1121 // Area Offset to zero (as they are not present) 1122 1123 memcpy(footer + 8, "TRUEVISION-XFILE.", 18); 1124 // copy the string including the '.' and the '\0' 1125 1126 ssize_t written; 1127 written = outDestination->Write(footer, kfootersize); 1128 if (written == kfootersize) 1129 return B_OK; 1130 else 1131 return B_ERROR; 1132 } 1133 1134 // --------------------------------------------------------------- 1135 // translate_from_bits 1136 // 1137 // Convert the data in inSource from the Be Bitmap format ('bits') 1138 // to the format specified in outType (either bits or TGA). 1139 // 1140 // Preconditions: 1141 // 1142 // Parameters: inSource, the bits data to translate 1143 // 1144 // amtread, the amount of data already read from 1145 // inSource 1146 // 1147 // read, pointer to the data already read from 1148 // inSource 1149 // 1150 // 1151 // outType, the type of data to convert to 1152 // 1153 // outDestination, where the output is written to 1154 // 1155 // Postconditions: 1156 // 1157 // Returns: B_NO_TRANSLATOR, if the data is not in a supported 1158 // format 1159 // 1160 // B_ERROR, if there was an error allocating memory or some other 1161 // error 1162 // 1163 // B_OK, if successfully translated the data from the bits format 1164 // --------------------------------------------------------------- 1165 status_t 1166 TGATranslator::translate_from_bits(BPositionIO *inSource, uint32 outType, 1167 BPositionIO *outDestination) 1168 { 1169 TranslatorBitmap bitsHeader; 1170 bool bheaderonly = false, bdataonly = false, brle; 1171 brle = fSettings->SetGetBool(TGA_SETTING_RLE); 1172 1173 status_t result; 1174 result = identify_bits_header(inSource, NULL, &bitsHeader); 1175 if (result != B_OK) 1176 return result; 1177 1178 // Translate B_TRANSLATOR_BITMAP to B_TGA_FORMAT 1179 if (outType == B_TGA_FORMAT) { 1180 // Set up TGA header 1181 TGAFileHeader fileheader; 1182 fileheader.idlength = 0; 1183 fileheader.colormaptype = TGA_NO_COLORMAP; 1184 fileheader.imagetype = 0; 1185 1186 TGAColorMapSpec mapspec; 1187 mapspec.firstentry = 0; 1188 mapspec.length = 0; 1189 mapspec.entrysize = 0; 1190 1191 TGAImageSpec imagespec; 1192 imagespec.xorigin = 0; 1193 imagespec.yorigin = 0; 1194 imagespec.width = static_cast<uint16> (bitsHeader.bounds.Width() + 1); 1195 imagespec.height = static_cast<uint16> (bitsHeader.bounds.Height() + 1); 1196 imagespec.depth = 0; 1197 imagespec.descriptor = TGA_ORIGIN_VERT_BIT; 1198 1199 // determine fileSize / imagesize 1200 switch (bitsHeader.colors) { 1201 1202 // Output to 32-bit True Color TGA (8 bits alpha) 1203 case B_RGBA32: 1204 case B_RGBA32_BIG: 1205 case B_CMYA32: 1206 if (brle) 1207 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1208 else 1209 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1210 imagespec.depth = 32; 1211 imagespec.descriptor |= 8; 1212 // 8 bits of alpha 1213 break; 1214 1215 // Output to 24-bit True Color TGA (no alpha) 1216 case B_RGB32: 1217 case B_RGB32_BIG: 1218 case B_RGB24: 1219 case B_RGB24_BIG: 1220 case B_CMYK32: 1221 case B_CMY32: 1222 case B_CMY24: 1223 if (brle) 1224 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1225 else 1226 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1227 imagespec.depth = 24; 1228 break; 1229 1230 // Output to 16-bit True Color TGA (no alpha) 1231 // (TGA doesn't see 16 bit images as Be does 1232 // so converting 16 bit Be Image to 16-bit TGA 1233 // image would result in loss of quality) 1234 case B_RGB16: 1235 case B_RGB16_BIG: 1236 if (brle) 1237 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1238 else 1239 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1240 imagespec.depth = 24; 1241 break; 1242 1243 // Output to 15-bit True Color TGA (1 bit alpha) 1244 case B_RGB15: 1245 case B_RGB15_BIG: 1246 if (brle) 1247 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1248 else 1249 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1250 imagespec.depth = 16; 1251 imagespec.descriptor |= 1; 1252 // 1 bit of alpha (always opaque) 1253 break; 1254 1255 // Output to 16-bit True Color TGA (1 bit alpha) 1256 case B_RGBA15: 1257 case B_RGBA15_BIG: 1258 if (brle) 1259 fileheader.imagetype = TGA_RLE_TRUECOLOR; 1260 else 1261 fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; 1262 imagespec.depth = 16; 1263 imagespec.descriptor |= 1; 1264 // 1 bit of alpha 1265 break; 1266 1267 // Output to 8-bit Color Mapped TGA 32 bits per color map entry 1268 case B_CMAP8: 1269 fileheader.colormaptype = TGA_COLORMAP; 1270 if (brle) 1271 fileheader.imagetype = TGA_RLE_COLORMAP; 1272 else 1273 fileheader.imagetype = TGA_NOCOMP_COLORMAP; 1274 mapspec.firstentry = 0; 1275 mapspec.length = 256; 1276 mapspec.entrysize = 32; 1277 imagespec.depth = 8; 1278 imagespec.descriptor |= 8; 1279 // the pixel values contain 8 bits of attribute data 1280 break; 1281 1282 // Output to 8-bit Black and White TGA 1283 case B_GRAY8: 1284 case B_GRAY1: 1285 if (brle) 1286 fileheader.imagetype = TGA_RLE_BW; 1287 else 1288 fileheader.imagetype = TGA_NOCOMP_BW; 1289 imagespec.depth = 8; 1290 break; 1291 1292 default: 1293 return B_NO_TRANSLATOR; 1294 } 1295 1296 // write out the TGA headers 1297 if (bheaderonly || (!bheaderonly && !bdataonly)) { 1298 result = write_tga_headers(outDestination, fileheader, 1299 mapspec, imagespec); 1300 if (result != B_OK) 1301 return result; 1302 } 1303 if (bheaderonly) 1304 // if user only wants the header, bail out 1305 // before the data is written 1306 return result; 1307 1308 // write out the TGA pixel data 1309 switch (bitsHeader.colors) { 1310 case B_RGB32: 1311 case B_RGB32_BIG: 1312 case B_RGBA32: 1313 case B_RGBA32_BIG: 1314 case B_RGB24: 1315 case B_RGB24_BIG: 1316 case B_RGB16: 1317 case B_RGB16_BIG: 1318 case B_RGB15: 1319 case B_RGB15_BIG: 1320 case B_RGBA15: 1321 case B_RGBA15_BIG: 1322 case B_CMYK32: 1323 case B_CMY32: 1324 case B_CMYA32: 1325 case B_CMY24: 1326 result = translate_from_bits_to_tgatc(inSource, outDestination, 1327 bitsHeader.colors, imagespec, brle); 1328 break; 1329 1330 case B_CMAP8: 1331 { 1332 // write Be's system palette to the TGA file 1333 uint8 pal[1024]; 1334 const color_map *pmap = system_colors(); 1335 if (!pmap) 1336 return B_ERROR; 1337 for (int32 i = 0; i < 256; i++) { 1338 uint8 *palent = pal + (i * 4); 1339 rgb_color c = pmap->color_list[i]; 1340 palent[0] = c.blue; 1341 palent[1] = c.green; 1342 palent[2] = c.red; 1343 palent[3] = c.alpha; 1344 } 1345 if (outDestination->Write(pal, 1024) != 1024) 1346 return B_ERROR; 1347 1348 result = translate_from_bits_to_tgatc(inSource, outDestination, 1349 B_GRAY8, imagespec, brle); 1350 break; 1351 } 1352 1353 case B_GRAY8: 1354 result = translate_from_bits_to_tgatc(inSource, outDestination, 1355 B_GRAY8, imagespec, brle); 1356 break; 1357 1358 case B_GRAY1: 1359 result = translate_from_bits1_to_tgabw(inSource, outDestination, 1360 bitsHeader.rowBytes, imagespec, brle); 1361 break; 1362 1363 default: 1364 result = B_NO_TRANSLATOR; 1365 break; 1366 } 1367 1368 if (result == B_OK) 1369 result = write_tga_footer(outDestination); 1370 1371 return result; 1372 1373 } else 1374 return B_NO_TRANSLATOR; 1375 } 1376 1377 // convert a row of uncompressed, non-color mapped 1378 // TGA pixels from ptga to pbits 1379 status_t 1380 pix_tganm_to_bits(uint8 *pbits, uint8 *ptga, 1381 uint16 width, uint8 depth, uint8 tgaBytesPerPixel, 1382 uint8 nalpha) 1383 { 1384 status_t result = B_OK; 1385 1386 switch (depth) { 1387 case 32: 1388 if (nalpha == 8 && tgaBytesPerPixel == 4) 1389 memcpy(pbits, ptga, 4 * width); 1390 else if (nalpha == 8) { 1391 // copy the same 32-bit pixel over and over 1392 while (width--) { 1393 memcpy(pbits, ptga, 4); 1394 pbits += 4; 1395 } 1396 } else { 1397 while (width--) { 1398 memcpy(pbits, ptga, 3); 1399 1400 pbits += 4; 1401 ptga += tgaBytesPerPixel; 1402 } 1403 } 1404 break; 1405 1406 case 24: 1407 while (width--) { 1408 memcpy(pbits, ptga, 3); 1409 1410 pbits += 4; 1411 ptga += tgaBytesPerPixel; 1412 } 1413 break; 1414 1415 case 16: 1416 { 1417 uint16 val; 1418 if (nalpha == 1) { 1419 while (width--) { 1420 val = ptga[0] + (ptga[1] << 8); 1421 pbits[0] = 1422 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1423 pbits[1] = 1424 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1425 pbits[2] = 1426 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1427 pbits[3] = (val & 0x8000) ? 255 : 0; 1428 1429 pbits += 4; 1430 ptga += tgaBytesPerPixel; 1431 } 1432 } else { 1433 while (width--) { 1434 val = ptga[0] + (ptga[1] << 8); 1435 pbits[0] = 1436 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1437 pbits[1] = 1438 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1439 pbits[2] = 1440 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1441 1442 pbits += 4; 1443 ptga += tgaBytesPerPixel; 1444 } 1445 } 1446 break; 1447 } 1448 1449 case 15: 1450 { 1451 uint16 val; 1452 while (width--) { 1453 val = ptga[0] + (ptga[1] << 8); 1454 pbits[0] = 1455 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1456 pbits[1] = 1457 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1458 pbits[2] = 1459 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1460 1461 pbits += 4; 1462 ptga += tgaBytesPerPixel; 1463 } 1464 break; 1465 } 1466 1467 case 8: 1468 while (width--) { 1469 memset(pbits, ptga[0], 3); 1470 1471 pbits += 4; 1472 ptga += tgaBytesPerPixel; 1473 } 1474 break; 1475 1476 default: 1477 result = B_ERROR; 1478 break; 1479 } 1480 1481 return result; 1482 } 1483 1484 // --------------------------------------------------------------- 1485 // translate_from_tganm_to_bits 1486 // 1487 // Translates a uncompressed, non-palette TGA from inSource 1488 // to the B_RGB32 or B_RGBA32 bits format. 1489 // 1490 // Preconditions: 1491 // 1492 // Parameters: inSource, the TGA data to be translated 1493 // 1494 // outDestination, where the bits data will be written to 1495 // 1496 // filehead, image type info 1497 // 1498 // mapspec, color map info 1499 // 1500 // imagespec, width / height info 1501 // 1502 // 1503 // 1504 // Postconditions: 1505 // 1506 // Returns: B_ERROR, if there is an error allocating memory 1507 // 1508 // B_OK, if all went well 1509 // --------------------------------------------------------------- 1510 status_t 1511 TGATranslator::translate_from_tganm_to_bits(BPositionIO *inSource, 1512 BPositionIO *outDestination, TGAFileHeader &filehead, 1513 TGAColorMapSpec &mapspec, TGAImageSpec &imagespec) 1514 { 1515 bool bvflip; 1516 if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) 1517 bvflip = false; 1518 else 1519 bvflip = true; 1520 uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec); 1521 int32 bitsRowBytes = imagespec.width * 4; 1522 uint8 tgaBytesPerPixel = (imagespec.depth / 8) + 1523 ((imagespec.depth % 8) ? 1 : 0); 1524 int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel); 1525 uint32 tgapixrow = 0; 1526 1527 // Setup outDestination so that it can be written to 1528 // from the end of the file to the beginning instead of 1529 // the other way around 1530 off_t bitsFileSize = (bitsRowBytes * imagespec.height) + 1531 sizeof(TranslatorBitmap); 1532 if (outDestination->SetSize(bitsFileSize) != B_OK) 1533 // This call should work for BFile and BMallocIO objects, 1534 // but may not work for other BPositionIO based types 1535 return B_ERROR; 1536 off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes; 1537 if (bvflip) 1538 outDestination->Seek(bitsoffset, SEEK_CUR); 1539 1540 // allocate row buffers 1541 uint8 *tgaRowData = new uint8[tgaRowBytes]; 1542 if (!tgaRowData) 1543 return B_ERROR; 1544 uint8 *bitsRowData = new uint8[bitsRowBytes]; 1545 if (!bitsRowData) { 1546 delete[] tgaRowData; 1547 tgaRowData = NULL; 1548 return B_ERROR; 1549 } 1550 1551 // perform the actual translation 1552 memset(bitsRowData, 0xff, bitsRowBytes); 1553 ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes); 1554 while (rd == tgaRowBytes) { 1555 pix_tganm_to_bits(bitsRowData, tgaRowData, 1556 imagespec.width, imagespec.depth, 1557 tgaBytesPerPixel, nalpha); 1558 1559 outDestination->Write(bitsRowData, bitsRowBytes); 1560 tgapixrow++; 1561 // if I've read all of the pixel data, break 1562 // out of the loop so I don't try to read 1563 // non-pixel data 1564 if (tgapixrow == imagespec.height) 1565 break; 1566 1567 if (bvflip) 1568 outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR); 1569 rd = inSource->Read(tgaRowData, tgaRowBytes); 1570 } 1571 1572 delete[] tgaRowData; 1573 tgaRowData = NULL; 1574 delete[] bitsRowData; 1575 bitsRowData = NULL; 1576 1577 return B_OK; 1578 } 1579 1580 // --------------------------------------------------------------- 1581 // translate_from_tganmrle_to_bits 1582 // 1583 // Convert non color map, RLE TGA to Be bitmap format 1584 // and write results to outDestination 1585 // 1586 // Preconditions: 1587 // 1588 // Parameters: inSource, the TGA data to be translated 1589 // 1590 // outDestination, where the bits data will be written to 1591 // 1592 // filehead, image type info 1593 // 1594 // mapspec, color map info 1595 // 1596 // imagespec, width / height info 1597 // 1598 // 1599 // 1600 // Postconditions: 1601 // 1602 // Returns: B_ERROR, if there is an error allocating memory 1603 // 1604 // B_OK, if all went well 1605 // --------------------------------------------------------------- 1606 status_t 1607 TGATranslator::translate_from_tganmrle_to_bits(BPositionIO *inSource, 1608 BPositionIO *outDestination, TGAFileHeader &filehead, 1609 TGAColorMapSpec &mapspec, TGAImageSpec &imagespec) 1610 { 1611 status_t result = B_OK; 1612 1613 bool bvflip; 1614 if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) 1615 bvflip = false; 1616 else 1617 bvflip = true; 1618 uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec); 1619 int32 bitsRowBytes = imagespec.width * 4; 1620 uint8 tgaBytesPerPixel = (imagespec.depth / 8) + 1621 ((imagespec.depth % 8) ? 1 : 0); 1622 uint16 tgapixrow = 0, tgapixcol = 0; 1623 1624 // Setup outDestination so that it can be written to 1625 // from the end of the file to the beginning instead of 1626 // the other way around 1627 off_t bitsFileSize = (bitsRowBytes * imagespec.height) + 1628 sizeof(TranslatorBitmap); 1629 if (outDestination->SetSize(bitsFileSize) != B_OK) 1630 // This call should work for BFile and BMallocIO objects, 1631 // but may not work for other BPositionIO based types 1632 return B_ERROR; 1633 off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes; 1634 if (bvflip) 1635 outDestination->Seek(bitsoffset, SEEK_CUR); 1636 1637 // allocate row buffers 1638 uint8 *bitsRowData = new uint8[bitsRowBytes]; 1639 if (!bitsRowData) 1640 return B_ERROR; 1641 1642 // perform the actual translation 1643 memset(bitsRowData, 0xff, bitsRowBytes); 1644 uint8 *pbitspixel = bitsRowData; 1645 uint8 packethead; 1646 StreamBuffer sbuf(inSource, TGA_STREAM_BUFFER_SIZE); 1647 ssize_t rd = 0; 1648 if (sbuf.InitCheck() == B_OK) 1649 rd = sbuf.Read(&packethead, 1); 1650 while (rd == 1) { 1651 // Run Length Packet 1652 if (packethead & TGA_RLE_PACKET_TYPE_BIT) { 1653 uint8 tgapixel[4], rlecount; 1654 rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; 1655 if (tgapixcol + rlecount > imagespec.width) { 1656 result = B_NO_TRANSLATOR; 1657 break; 1658 } 1659 rd = sbuf.Read(tgapixel, tgaBytesPerPixel); 1660 if (rd == tgaBytesPerPixel) { 1661 pix_tganm_to_bits(pbitspixel, tgapixel, 1662 rlecount, imagespec.depth, 0, nalpha); 1663 1664 pbitspixel += 4 * rlecount; 1665 tgapixcol += rlecount; 1666 } else { 1667 result = B_NO_TRANSLATOR; 1668 break; // error 1669 } 1670 1671 // Raw Packet 1672 } else { 1673 uint8 tgaPixelBuf[512], rawcount; 1674 uint16 rawbytes; 1675 rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; 1676 if (tgapixcol + rawcount > imagespec.width) { 1677 result = B_NO_TRANSLATOR; 1678 break; 1679 } 1680 rawbytes = tgaBytesPerPixel * rawcount; 1681 rd = sbuf.Read(tgaPixelBuf, rawbytes); 1682 if (rd == rawbytes) { 1683 pix_tganm_to_bits(pbitspixel, tgaPixelBuf, 1684 rawcount, imagespec.depth, tgaBytesPerPixel, nalpha); 1685 1686 pbitspixel += 4 * rawcount; 1687 tgapixcol += rawcount; 1688 } else { 1689 result = B_NO_TRANSLATOR; 1690 break; 1691 } 1692 } 1693 1694 if (tgapixcol == imagespec.width) { 1695 outDestination->Write(bitsRowData, bitsRowBytes); 1696 tgapixcol = 0; 1697 tgapixrow++; 1698 if (tgapixrow == imagespec.height) 1699 break; 1700 if (bvflip) 1701 outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR); 1702 pbitspixel = bitsRowData; 1703 } 1704 rd = sbuf.Read(&packethead, 1); 1705 } 1706 1707 delete[] bitsRowData; 1708 bitsRowData = NULL; 1709 1710 return result; 1711 } 1712 1713 // convert a row of color mapped pixels to pbits 1714 status_t 1715 pix_tgam_to_bits(uint8 *pbits, uint8 *ptgaindices, 1716 uint16 width, uint8 depth, uint8 *pmap) 1717 { 1718 status_t result = B_OK; 1719 uint8 *ptgapixel = NULL; 1720 1721 switch (depth) { 1722 case 32: 1723 for (uint16 i = 0; i < width; i++) { 1724 ptgapixel = pmap + 1725 (ptgaindices[i] * 4); 1726 1727 memcpy(pbits, ptgapixel, 4); 1728 1729 pbits += 4; 1730 } 1731 break; 1732 1733 case 24: 1734 for (uint16 i = 0; i < width; i++) { 1735 ptgapixel = pmap + 1736 (ptgaindices[i] * 3); 1737 1738 memcpy(pbits, ptgapixel, 3); 1739 1740 pbits += 4; 1741 } 1742 break; 1743 1744 case 16: 1745 for (uint16 i = 0; i < width; i++) { 1746 uint16 val; 1747 1748 ptgapixel = pmap + 1749 (ptgaindices[i] * 2); 1750 val = ptgapixel[0] + (ptgapixel[1] << 8); 1751 pbits[0] = 1752 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1753 pbits[1] = 1754 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1755 pbits[2] = 1756 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1757 pbits[3] = (val & 0x8000) ? 255 : 0; 1758 1759 pbits += 4; 1760 } 1761 break; 1762 1763 case 15: 1764 for (uint16 i = 0; i < width; i++) { 1765 uint16 val; 1766 1767 ptgapixel = pmap + 1768 (ptgaindices[i] * 2); 1769 val = ptgapixel[0] + (ptgapixel[1] << 8); 1770 pbits[0] = 1771 ((val & 0x1f) << 3) | ((val & 0x1f) >> 2); 1772 pbits[1] = 1773 ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7); 1774 pbits[2] = 1775 ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); 1776 1777 pbits += 4; 1778 } 1779 break; 1780 1781 default: 1782 result = B_ERROR; 1783 break; 1784 } 1785 1786 return result; 1787 } 1788 1789 // --------------------------------------------------------------- 1790 // translate_from_tgam_to_bits 1791 // 1792 // Translates a paletted TGA from inSource to the bits format. 1793 // 1794 // Preconditions: 1795 // 1796 // Parameters: inSource, the TGA data to be translated 1797 // 1798 // outDestination, where the bits data will be written to 1799 // 1800 // mapspec, info about the color map (palette) 1801 // 1802 // imagespec, width / height info 1803 // 1804 // pmap, color palette 1805 // 1806 // 1807 // Postconditions: 1808 // 1809 // Returns: B_ERROR, if there is an error allocating memory 1810 // 1811 // B_OK, if all went well 1812 // --------------------------------------------------------------- 1813 status_t 1814 translate_from_tgam_to_bits(BPositionIO *inSource, 1815 BPositionIO *outDestination, TGAColorMapSpec &mapspec, 1816 TGAImageSpec &imagespec, uint8 *pmap) 1817 { 1818 bool bvflip; 1819 if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) 1820 bvflip = false; 1821 else 1822 bvflip = true; 1823 1824 int32 bitsRowBytes = imagespec.width * 4; 1825 uint8 tgaBytesPerPixel = (imagespec.depth / 8) + 1826 ((imagespec.depth % 8) ? 1 : 0); 1827 int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel); 1828 uint32 tgapixrow = 0; 1829 1830 // Setup outDestination so that it can be written to 1831 // from the end of the file to the beginning instead of 1832 // the other way around 1833 off_t bitsFileSize = (bitsRowBytes * imagespec.height) + 1834 sizeof(TranslatorBitmap); 1835 if (outDestination->SetSize(bitsFileSize) != B_OK) 1836 // This call should work for BFile and BMallocIO objects, 1837 // but may not work for other BPositionIO based types 1838 return B_ERROR; 1839 off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes; 1840 if (bvflip) 1841 outDestination->Seek(bitsoffset, SEEK_CUR); 1842 1843 // allocate row buffers 1844 uint8 *tgaRowData = new uint8[tgaRowBytes]; 1845 if (!tgaRowData) 1846 return B_ERROR; 1847 uint8 *bitsRowData = new uint8[bitsRowBytes]; 1848 if (!bitsRowData) { 1849 delete[] tgaRowData; 1850 tgaRowData = NULL; 1851 return B_ERROR; 1852 } 1853 1854 // perform the actual translation 1855 memset(bitsRowData, 0xff, bitsRowBytes); 1856 ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes); 1857 while (rd == tgaRowBytes) { 1858 pix_tgam_to_bits(bitsRowData, tgaRowData, 1859 imagespec.width, mapspec.entrysize, pmap); 1860 1861 outDestination->Write(bitsRowData, bitsRowBytes); 1862 tgapixrow++; 1863 // if I've read all of the pixel data, break 1864 // out of the loop so I don't try to read 1865 // non-pixel data 1866 if (tgapixrow == imagespec.height) 1867 break; 1868 1869 if (bvflip) 1870 outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR); 1871 rd = inSource->Read(tgaRowData, tgaRowBytes); 1872 } 1873 1874 delete[] tgaRowData; 1875 tgaRowData = NULL; 1876 delete[] bitsRowData; 1877 bitsRowData = NULL; 1878 1879 return B_OK; 1880 } 1881 1882 // --------------------------------------------------------------- 1883 // translate_from_tgamrle_to_bits 1884 // 1885 // Translates a color mapped or non color mapped RLE TGA from 1886 // inSource to the bits format. 1887 // 1888 // Preconditions: 1889 // 1890 // Parameters: inSource, the TGA data to be translated 1891 // 1892 // outDestination, where the bits data will be written to 1893 // 1894 // filehead, image type info 1895 // 1896 // mapspec, info about the color map (palette) 1897 // 1898 // imagespec, width / height info 1899 // 1900 // pmap, color palette 1901 // 1902 // 1903 // Postconditions: 1904 // 1905 // Returns: B_ERROR, if there is an error allocating memory 1906 // 1907 // B_OK, if all went well 1908 // --------------------------------------------------------------- 1909 status_t 1910 TGATranslator::translate_from_tgamrle_to_bits(BPositionIO *inSource, 1911 BPositionIO *outDestination, TGAFileHeader &filehead, 1912 TGAColorMapSpec &mapspec, TGAImageSpec &imagespec, uint8 *pmap) 1913 { 1914 status_t result = B_OK; 1915 1916 bool bvflip; 1917 if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) 1918 bvflip = false; 1919 else 1920 bvflip = true; 1921 uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec); 1922 int32 bitsRowBytes = imagespec.width * 4; 1923 uint8 tgaPalBytesPerPixel = (mapspec.entrysize / 8) + 1924 ((mapspec.entrysize % 8) ? 1 : 0); 1925 uint8 tgaBytesPerPixel = (imagespec.depth / 8) + 1926 ((imagespec.depth % 8) ? 1 : 0); 1927 uint16 tgapixrow = 0, tgapixcol = 0; 1928 1929 // Setup outDestination so that it can be written to 1930 // from the end of the file to the beginning instead of 1931 // the other way around 1932 off_t bitsFileSize = (bitsRowBytes * imagespec.height) + 1933 sizeof(TranslatorBitmap); 1934 if (outDestination->SetSize(bitsFileSize) != B_OK) 1935 // This call should work for BFile and BMallocIO objects, 1936 // but may not work for other BPositionIO based types 1937 return B_ERROR; 1938 off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes; 1939 if (bvflip) 1940 outDestination->Seek(bitsoffset, SEEK_CUR); 1941 1942 // allocate row buffers 1943 uint8 *bitsRowData = new uint8[bitsRowBytes]; 1944 if (!bitsRowData) 1945 return B_ERROR; 1946 1947 // perform the actual translation 1948 memset(bitsRowData, 0xff, bitsRowBytes); 1949 uint8 *pbitspixel = bitsRowData; 1950 uint8 packethead; 1951 StreamBuffer sbuf(inSource, TGA_STREAM_BUFFER_SIZE); 1952 ssize_t rd = 0; 1953 if (sbuf.InitCheck() == B_OK) 1954 rd = sbuf.Read(&packethead, 1); 1955 while (rd == 1) { 1956 // Run Length Packet 1957 if (packethead & TGA_RLE_PACKET_TYPE_BIT) { 1958 uint8 tgaindex, rlecount; 1959 rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; 1960 if (tgapixcol + rlecount > imagespec.width) { 1961 result = B_NO_TRANSLATOR; 1962 break; 1963 } 1964 rd = sbuf.Read(&tgaindex, 1); 1965 if (rd == tgaBytesPerPixel) { 1966 uint8 *ptgapixel; 1967 ptgapixel = pmap + (tgaindex * tgaPalBytesPerPixel); 1968 1969 pix_tganm_to_bits(pbitspixel, ptgapixel, rlecount, 1970 mapspec.entrysize, 0, nalpha); 1971 1972 pbitspixel += 4 * rlecount; 1973 tgapixcol += rlecount; 1974 } else { 1975 result = B_NO_TRANSLATOR; 1976 break; // error 1977 } 1978 1979 // Raw Packet 1980 } else { 1981 uint8 tgaIndexBuf[128], rawcount; 1982 rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; 1983 if (tgapixcol + rawcount > imagespec.width) { 1984 result = B_NO_TRANSLATOR; 1985 break; 1986 } 1987 rd = sbuf.Read(tgaIndexBuf, rawcount); 1988 if (rd == rawcount) { 1989 pix_tgam_to_bits(pbitspixel, tgaIndexBuf, 1990 rawcount, mapspec.entrysize, pmap); 1991 1992 pbitspixel += 4 * rawcount; 1993 tgapixcol += rawcount; 1994 } else { 1995 result = B_NO_TRANSLATOR; 1996 break; 1997 } 1998 } 1999 2000 if (tgapixcol == imagespec.width) { 2001 outDestination->Write(bitsRowData, bitsRowBytes); 2002 tgapixcol = 0; 2003 tgapixrow++; 2004 if (tgapixrow == imagespec.height) 2005 break; 2006 if (bvflip) 2007 outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR); 2008 pbitspixel = bitsRowData; 2009 } 2010 rd = sbuf.Read(&packethead, 1); 2011 } 2012 2013 delete[] bitsRowData; 2014 bitsRowData = NULL; 2015 2016 return result; 2017 } 2018 2019 // --------------------------------------------------------------- 2020 // translate_from_tga 2021 // 2022 // Convert the data in inSource from the TGA format 2023 // to the format specified in outType (either bits or TGA). 2024 // 2025 // Preconditions: 2026 // 2027 // Parameters: inSource, the bits data to translate 2028 // 2029 // amtread, the amount of data already read from 2030 // inSource 2031 // 2032 // read, pointer to the data already read from 2033 // inSource 2034 // 2035 // outType, the type of data to convert to 2036 // 2037 // outDestination, where the output is written to 2038 // 2039 // Postconditions: 2040 // 2041 // Returns: B_NO_TRANSLATOR, if the data is not in a supported 2042 // format 2043 // 2044 // B_ERROR, if there was an error allocating memory or some other 2045 // error 2046 // 2047 // B_OK, if successfully translated the data from the bits format 2048 // --------------------------------------------------------------- 2049 status_t 2050 TGATranslator::translate_from_tga(BPositionIO *inSource, uint32 outType, 2051 BPositionIO *outDestination) 2052 { 2053 TGAFileHeader fileheader; 2054 TGAColorMapSpec mapspec; 2055 TGAImageSpec imagespec; 2056 bool bheaderonly = false, bdataonly = false; 2057 2058 status_t result; 2059 result = identify_tga_header(inSource, NULL, &fileheader, &mapspec, 2060 &imagespec); 2061 if (result != B_OK) 2062 return result; 2063 2064 // if the user wants to translate a TGA to a TGA, easy enough :) 2065 if (outType == B_TGA_FORMAT) { 2066 // write out the TGA headers 2067 if (bheaderonly || (!bheaderonly && !bdataonly)) { 2068 result = write_tga_headers(outDestination, fileheader, 2069 mapspec, imagespec); 2070 if (result != B_OK) 2071 return result; 2072 } 2073 if (bheaderonly) 2074 // if the user only wants the header, 2075 // bail before it is written 2076 return result; 2077 2078 const int32 kbuflen = 1024; 2079 uint8 buf[kbuflen]; 2080 ssize_t rd = inSource->Read(buf, kbuflen); 2081 while (rd > 0) { 2082 outDestination->Write(buf, rd); 2083 rd = inSource->Read(buf, kbuflen); 2084 } 2085 if (rd == 0) 2086 return B_OK; 2087 else 2088 return B_ERROR; 2089 2090 // if translating a TGA to a Be Bitmap 2091 } else if (outType == B_TRANSLATOR_BITMAP) { 2092 TranslatorBitmap bitsHeader; 2093 bitsHeader.magic = B_TRANSLATOR_BITMAP; 2094 bitsHeader.bounds.left = 0; 2095 bitsHeader.bounds.top = 0; 2096 bitsHeader.bounds.right = imagespec.width - 1; 2097 bitsHeader.bounds.bottom = imagespec.height - 1; 2098 2099 // skip over Image ID data (if present) 2100 if (fileheader.idlength > 0) 2101 inSource->Seek(fileheader.idlength, SEEK_CUR); 2102 2103 // read in palette and/or skip non-TGA data 2104 uint8 *ptgapalette = NULL; 2105 if (fileheader.colormaptype == TGA_COLORMAP) { 2106 uint32 nentrybytes; 2107 nentrybytes = mapspec.entrysize / 8; 2108 if (mapspec.entrysize % 8) 2109 nentrybytes++; 2110 ptgapalette = new uint8[nentrybytes * mapspec.length]; 2111 inSource->Read(ptgapalette, nentrybytes * mapspec.length); 2112 } 2113 2114 bitsHeader.rowBytes = imagespec.width * 4; 2115 if (fileheader.imagetype != TGA_NOCOMP_BW && 2116 fileheader.imagetype != TGA_RLE_BW && 2117 tga_alphabits(fileheader, mapspec, imagespec)) 2118 bitsHeader.colors = B_RGBA32; 2119 else 2120 bitsHeader.colors = B_RGB32; 2121 int32 datasize = bitsHeader.rowBytes * imagespec.height; 2122 bitsHeader.dataSize = datasize; 2123 2124 // write out Be's Bitmap header 2125 if (bheaderonly || (!bheaderonly && !bdataonly)) { 2126 if (swap_data(B_UINT32_TYPE, &bitsHeader, 2127 sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) 2128 return B_ERROR; 2129 outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap)); 2130 } 2131 if (bheaderonly) 2132 // if the user only wants the header, 2133 // bail before the data is written 2134 return B_OK; 2135 2136 // write out the actual image data 2137 switch (fileheader.imagetype) { 2138 case TGA_NOCOMP_TRUECOLOR: 2139 case TGA_NOCOMP_BW: 2140 result = translate_from_tganm_to_bits(inSource, 2141 outDestination, fileheader, mapspec, imagespec); 2142 break; 2143 2144 case TGA_NOCOMP_COLORMAP: 2145 result = translate_from_tgam_to_bits(inSource, 2146 outDestination, mapspec, imagespec, ptgapalette); 2147 break; 2148 2149 case TGA_RLE_TRUECOLOR: 2150 case TGA_RLE_BW: 2151 result = translate_from_tganmrle_to_bits(inSource, 2152 outDestination, fileheader, mapspec, imagespec); 2153 break; 2154 2155 case TGA_RLE_COLORMAP: 2156 result = translate_from_tgamrle_to_bits(inSource, outDestination, 2157 fileheader, mapspec, imagespec, ptgapalette); 2158 break; 2159 2160 default: 2161 result = B_NO_TRANSLATOR; 2162 break; 2163 } 2164 2165 delete[] ptgapalette; 2166 ptgapalette = NULL; 2167 2168 return result; 2169 2170 } else 2171 return B_NO_TRANSLATOR; 2172 } 2173 2174 status_t 2175 TGATranslator::DerivedTranslate(BPositionIO *inSource, 2176 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 2177 BPositionIO *outDestination, int32 baseType) 2178 { 2179 if (baseType == 1) 2180 // if inSource is in bits format 2181 return translate_from_bits(inSource, outType, outDestination); 2182 else if (baseType == 0) 2183 // if inSource is NOT in bits format 2184 return translate_from_tga(inSource, outType, outDestination); 2185 else 2186 // if BaseTranslator did not properly identify the data as 2187 // bits or not bits 2188 return B_NO_TRANSLATOR; 2189 } 2190 2191 BView * 2192 TGATranslator::NewConfigView(TranslatorSettings *settings) 2193 { 2194 return new TGAView("TGATranslator Settings", B_WILL_DRAW, settings); 2195 } 2196 2197