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