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_TRANSLATION_CONTEXT 41#define B_TRANSLATION_CONTEXT "TGATranslator" 42 43// The input formats that this translator supports. 44static 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. 64static 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 84static 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 93const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format); 94const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format); 95const 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// --------------------------------------------------------------- 120BTranslator * 121make_nth_translator(int32 n, image_id you, uint32 flags, ...) 122{ 123 BTranslator *ptranslator = NULL; 124 if (!n) 125 ptranslator = new(std::nothrow) 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// --------------------------------------------------------------- 144TGATranslator::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 172TGATranslator::~TGATranslator() 173{ 174} 175 176uint8 177TGATranslator::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// --------------------------------------------------------------- 250status_t 251identify_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_LEFT) 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 435status_t 436TGATranslator::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 445status_t 446pix_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 652status_t 653copy_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 669status_t 670copy_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 687status_t 688pix_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(std::nothrow) 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// --------------------------------------------------------------- 830status_t 831translate_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(std::nothrow) uint8[tgaRowBytes]; 877 if (!tgaRowData) 878 return B_ERROR; 879 uint8 *bitsRowData = new(std::nothrow) 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// --------------------------------------------------------------- 960status_t 961translate_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(std::nothrow) uint8[tgaRowBytes]; 970 if (!tgaRowData) 971 return B_ERROR; 972 973 uint8 *medRowData = new(std::nothrow) uint8[imagespec.width]; 974 if (!medRowData) { 975 delete[] tgaRowData; 976 tgaRowData = NULL; 977 return B_ERROR; 978 } 979 uint8 *bitsRowData = new(std::nothrow) 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// --------------------------------------------------------------- 1067status_t 1068write_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// --------------------------------------------------------------- 1136status_t 1137write_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// --------------------------------------------------------------- 1188status_t 1189TGATranslator::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 1402status_t 1403pix_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// --------------------------------------------------------------- 1533status_t 1534TGATranslator::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(std::nothrow) uint8[tgaRowBytes]; 1565 if (!tgaRowData) 1566 return B_ERROR; 1567 uint8 *bitsRowData = new(std::nothrow) 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// --------------------------------------------------------------- 1629status_t 1630TGATranslator::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(std::nothrow) 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 1737status_t 1738pix_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// --------------------------------------------------------------- 1836status_t 1837translate_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(std::nothrow) uint8[tgaRowBytes]; 1868 if (!tgaRowData) 1869 return B_ERROR; 1870 uint8 *bitsRowData = new(std::nothrow) 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// --------------------------------------------------------------- 1932status_t 1933TGATranslator::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(std::nothrow) 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// --------------------------------------------------------------- 2072status_t 2073TGATranslator::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(std::nothrow) 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 2197status_t 2198TGATranslator::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 2214BView * 2215TGATranslator::NewConfigView(TranslatorSettings *settings) 2216{ 2217 return new(std::nothrow) TGAView(B_TRANSLATE("TGATranslator Settings"), 2218 B_WILL_DRAW, settings); 2219} 2220 2221