1 /*****************************************************************************/ 2 // TIFFTranslator 3 // Written by Michael Wilber, OBOS Translation Kit Team 4 // 5 // TIFFTranslator.cpp 6 // 7 // This BTranslator based object is for opening and writing 8 // TIFF images. 9 // 10 // 11 // Copyright (c) 2003 OpenBeOS Project 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a 14 // copy of this software and associated documentation files (the "Software"), 15 // to deal in the Software without restriction, including without limitation 16 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 // and/or sell copies of the Software, and to permit persons to whom the 18 // Software is furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included 21 // in all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 // DEALINGS IN THE SOFTWARE. 30 /*****************************************************************************/ 31 32 #include <stdio.h> 33 #include <string.h> 34 #include "TIFFTranslator.h" 35 #include "TIFFView.h" 36 #include "TiffIfd.h" 37 #include "TiffIfdList.h" 38 #include "StreamBuffer.h" 39 #include "BitReader.h" 40 41 // The input formats that this translator supports. 42 translation_format gInputFormats[] = { 43 { 44 B_TRANSLATOR_BITMAP, 45 B_TRANSLATOR_BITMAP, 46 BBT_IN_QUALITY, 47 BBT_IN_CAPABILITY, 48 "image/x-be-bitmap", 49 "Be Bitmap Format (TIFFTranslator)" 50 }, 51 { 52 B_TIFF_FORMAT, 53 B_TRANSLATOR_BITMAP, 54 TIFF_IN_QUALITY, 55 TIFF_IN_CAPABILITY, 56 "image/tiff", 57 "TIFF image" 58 } 59 }; 60 61 // The output formats that this translator supports. 62 translation_format gOutputFormats[] = { 63 { 64 B_TRANSLATOR_BITMAP, 65 B_TRANSLATOR_BITMAP, 66 BBT_OUT_QUALITY, 67 BBT_OUT_CAPABILITY, 68 "image/x-be-bitmap", 69 "Be Bitmap Format (TIFFTranslator)" 70 }, 71 { 72 B_TIFF_FORMAT, 73 B_TRANSLATOR_BITMAP, 74 TIFF_OUT_QUALITY, 75 TIFF_OUT_CAPABILITY, 76 "image/tiff", 77 "TIFF image" 78 } 79 }; 80 81 // --------------------------------------------------------------- 82 // make_nth_translator 83 // 84 // Creates a TIFFTranslator object to be used by BTranslatorRoster 85 // 86 // Preconditions: 87 // 88 // Parameters: n, The translator to return. Since 89 // TIFFTranslator only publishes one 90 // translator, it only returns a 91 // TIFFTranslator if n == 0 92 // 93 // you, The image_id of the add-on that 94 // contains code (not used). 95 // 96 // flags, Has no meaning yet, should be 0. 97 // 98 // Postconditions: 99 // 100 // Returns: NULL if n is not zero, 101 // a new TIFFTranslator if n is zero 102 // --------------------------------------------------------------- 103 BTranslator * 104 make_nth_translator(int32 n, image_id you, uint32 flags, ...) 105 { 106 if (!n) 107 return new TIFFTranslator(); 108 else 109 return NULL; 110 } 111 112 TiffDetails::TiffDetails() 113 { 114 memset(this, 0, sizeof(TiffDetails)); 115 } 116 117 TiffDetails::~TiffDetails() 118 { 119 delete[] pstripOffsets; 120 delete[] pstripByteCounts; 121 delete[] pcolorMap; 122 123 memset(this, 0, sizeof(TiffDetails)); 124 } 125 126 // --------------------------------------------------------------- 127 // Constructor 128 // 129 // Sets up the version info and the name of the translator so that 130 // these values can be returned when they are requested. 131 // 132 // Preconditions: 133 // 134 // Parameters: 135 // 136 // Postconditions: 137 // 138 // Returns: 139 // --------------------------------------------------------------- 140 TIFFTranslator::TIFFTranslator() 141 : BTranslator() 142 { 143 fpblackTree = NULL; 144 fpwhiteTree = NULL; 145 146 strcpy(fName, "TIFF Images"); 147 sprintf(fInfo, "TIFF image translator v%d.%d.%d %s", 148 TIFF_TRANSLATOR_VERSION / 100, (TIFF_TRANSLATOR_VERSION / 10) % 10, 149 TIFF_TRANSLATOR_VERSION % 10, __DATE__); 150 } 151 152 // --------------------------------------------------------------- 153 // Destructor 154 // 155 // Does nothing 156 // 157 // Preconditions: 158 // 159 // Parameters: 160 // 161 // Postconditions: 162 // 163 // Returns: 164 // --------------------------------------------------------------- 165 TIFFTranslator::~TIFFTranslator() 166 { 167 delete fpblackTree; 168 fpblackTree = NULL; 169 delete fpwhiteTree; 170 fpwhiteTree = NULL; 171 } 172 173 // --------------------------------------------------------------- 174 // TranslatorName 175 // 176 // Returns the short name of the translator. 177 // 178 // Preconditions: 179 // 180 // Parameters: 181 // 182 // Postconditions: 183 // 184 // Returns: a const char * to the short name of the translator 185 // --------------------------------------------------------------- 186 const char * 187 TIFFTranslator::TranslatorName() const 188 { 189 return fName; 190 } 191 192 // --------------------------------------------------------------- 193 // TranslatorInfo 194 // 195 // Returns a more verbose name for the translator than the one 196 // TranslatorName() returns. This usually includes version info. 197 // 198 // Preconditions: 199 // 200 // Parameters: 201 // 202 // Postconditions: 203 // 204 // Returns: a const char * to the verbose name of the translator 205 // --------------------------------------------------------------- 206 const char * 207 TIFFTranslator::TranslatorInfo() const 208 { 209 return fInfo; 210 } 211 212 // --------------------------------------------------------------- 213 // TranslatorVersion 214 // 215 // Returns the integer representation of the current version of 216 // this translator. 217 // 218 // Preconditions: 219 // 220 // Parameters: 221 // 222 // Postconditions: 223 // 224 // Returns: 225 // --------------------------------------------------------------- 226 int32 227 TIFFTranslator::TranslatorVersion() const 228 { 229 return TIFF_TRANSLATOR_VERSION; 230 } 231 232 // --------------------------------------------------------------- 233 // InputFormats 234 // 235 // Returns a list of input formats supported by this translator. 236 // 237 // Preconditions: 238 // 239 // Parameters: out_count, The number of input formats 240 // support is returned here. 241 // 242 // Postconditions: 243 // 244 // Returns: the list of input formats and the number of input 245 // formats through the out_count parameter, if out_count is NULL, 246 // NULL is returned 247 // --------------------------------------------------------------- 248 const translation_format * 249 TIFFTranslator::InputFormats(int32 *out_count) const 250 { 251 if (out_count) { 252 *out_count = sizeof(gInputFormats) / 253 sizeof(translation_format); 254 return gInputFormats; 255 } else 256 return NULL; 257 } 258 259 // --------------------------------------------------------------- 260 // OutputFormats 261 // 262 // Returns a list of output formats supported by this translator. 263 // 264 // Preconditions: 265 // 266 // Parameters: out_count, The number of output formats 267 // support is returned here. 268 // 269 // Postconditions: 270 // 271 // Returns: the list of output formats and the number of output 272 // formats through the out_count parameter, if out_count is NULL, 273 // NULL is returned 274 // --------------------------------------------------------------- 275 const translation_format * 276 TIFFTranslator::OutputFormats(int32 *out_count) const 277 { 278 if (out_count) { 279 *out_count = sizeof(gOutputFormats) / 280 sizeof(translation_format); 281 return gOutputFormats; 282 } else 283 return NULL; 284 } 285 286 // --------------------------------------------------------------- 287 // identify_bits_header 288 // 289 // Determines if the data in inSource is in the 290 // B_TRANSLATOR_BITMAP ('bits') format. If it is, it returns 291 // info about the data in inSource to outInfo and pheader. 292 // 293 // Preconditions: 294 // 295 // Parameters: inSource, The source of the image data 296 // 297 // outInfo, Information about the translator 298 // is copied here 299 // 300 // amtread, Amount of data read from inSource 301 // before this function was called 302 // 303 // read, Pointer to the data that was read 304 // in before this function was called 305 // 306 // pheader, The bits header is copied here after 307 // it is read in from inSource 308 // 309 // Postconditions: 310 // 311 // Returns: B_NO_TRANSLATOR, if the data does not look like 312 // bits format data 313 // 314 // B_ERROR, if the header data could not be converted to host 315 // format 316 // 317 // B_OK, if the data looks like bits data and no errors were 318 // encountered 319 // --------------------------------------------------------------- 320 status_t 321 identify_bits_header(BPositionIO *inSource, translator_info *outInfo, 322 ssize_t amtread, uint8 *read, TranslatorBitmap *pheader = NULL) 323 { 324 TranslatorBitmap header; 325 326 memcpy(&header, read, amtread); 327 // copy portion of header already read in 328 // read in the rest of the header 329 ssize_t size = sizeof(TranslatorBitmap) - amtread; 330 if (inSource->Read( 331 (reinterpret_cast<uint8 *> (&header)) + amtread, size) != size) 332 return B_NO_TRANSLATOR; 333 334 // convert to host byte order 335 if (swap_data(B_UINT32_TYPE, &header, sizeof(TranslatorBitmap), 336 B_SWAP_BENDIAN_TO_HOST) != B_OK) 337 return B_ERROR; 338 339 // check if header values are reasonable 340 if (header.colors != B_RGB32 && 341 header.colors != B_RGB32_BIG && 342 header.colors != B_RGBA32 && 343 header.colors != B_RGBA32_BIG && 344 header.colors != B_RGB24 && 345 header.colors != B_RGB24_BIG && 346 header.colors != B_RGB16 && 347 header.colors != B_RGB16_BIG && 348 header.colors != B_RGB15 && 349 header.colors != B_RGB15_BIG && 350 header.colors != B_RGBA15 && 351 header.colors != B_RGBA15_BIG && 352 header.colors != B_CMAP8 && 353 header.colors != B_GRAY8 && 354 header.colors != B_GRAY1 && 355 header.colors != B_CMYK32 && 356 header.colors != B_CMY32 && 357 header.colors != B_CMYA32 && 358 header.colors != B_CMY24) 359 return B_NO_TRANSLATOR; 360 if (header.rowBytes * (header.bounds.Height() + 1) != header.dataSize) 361 return B_NO_TRANSLATOR; 362 363 if (outInfo) { 364 outInfo->type = B_TRANSLATOR_BITMAP; 365 outInfo->group = B_TRANSLATOR_BITMAP; 366 outInfo->quality = BBT_IN_QUALITY; 367 outInfo->capability = BBT_IN_CAPABILITY; 368 strcpy(outInfo->name, "Be Bitmap Format (TIFFTranslator)"); 369 strcpy(outInfo->MIME, "image/x-be-bitmap"); 370 } 371 372 if (pheader) { 373 pheader->magic = header.magic; 374 pheader->bounds = header.bounds; 375 pheader->rowBytes = header.rowBytes; 376 pheader->colors = header.colors; 377 pheader->dataSize = header.dataSize; 378 } 379 380 return B_OK; 381 } 382 383 // If this TIFF has unsupported features, 384 // return B_NO_TRANSLATOR, otherwise, 385 // return B_OK 386 status_t 387 check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails, bool bAllocArrays) 388 { 389 if (!pdetails) 390 return B_BAD_VALUE; 391 392 try { 393 // Extra Samples are not yet supported 394 if (ifd.HasField(TAG_EXTRA_SAMPLES)) 395 return B_NO_TRANSLATOR; 396 397 // Only the default values are supported for the 398 // following fields. HasField is called so that 399 // if a field is not present, a TiffIfdFieldNotFoundException 400 // will not be thrown when GetUint is called. 401 // (If they are not present, that is fine, but if 402 // they are present and have a non-default value, 403 // that is a problem) 404 if (ifd.HasField(TAG_ORIENTATION) && 405 ifd.GetUint(TAG_ORIENTATION) != 1) 406 return B_NO_TRANSLATOR; 407 if (ifd.HasField(TAG_PLANAR_CONFIGURATION) && 408 ifd.GetUint(TAG_PLANAR_CONFIGURATION) != 1) 409 return B_NO_TRANSLATOR; 410 if (ifd.HasField(TAG_SAMPLE_FORMAT) && 411 ifd.GetUint(TAG_SAMPLE_FORMAT) != 1) 412 return B_NO_TRANSLATOR; 413 414 // Copy fields useful to TIFFTranslator 415 uint32 width = ifd.GetUint(TAG_IMAGE_WIDTH); 416 uint32 height = ifd.GetUint(TAG_IMAGE_HEIGHT); 417 uint16 interpretation = ifd.GetUint(TAG_PHOTO_INTERPRETATION); 418 419 uint32 compression; 420 if (!ifd.HasField(TAG_COMPRESSION)) 421 compression = COMPRESSION_NONE; 422 else 423 compression = ifd.GetUint(TAG_COMPRESSION); 424 425 uint32 t4options = 0; 426 uint16 imageType = 0, bitsPerPixel = 0, fillOrder = 1; 427 switch (interpretation) { 428 // black and white or grayscale images 429 case PHOTO_WHITEZERO: 430 case PHOTO_BLACKZERO: 431 // default value for samples per pixel is 1 432 if (ifd.HasField(TAG_SAMPLES_PER_PIXEL) && 433 ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 1) 434 return B_NO_TRANSLATOR; 435 436 // Only 1D and fill byte boundary t4options are 437 // supported 438 if (ifd.HasField(TAG_T4_OPTIONS)) 439 t4options = ifd.GetUint(TAG_T4_OPTIONS); 440 if (t4options != 0 && t4options != T4_FILL_BYTE_BOUNDARY) 441 return B_NO_TRANSLATOR; 442 443 // default value for bits per sample is 1 444 if (!ifd.HasField(TAG_BITS_PER_SAMPLE) || 445 ifd.GetUint(TAG_BITS_PER_SAMPLE) == 1) { 446 bitsPerPixel = 1; 447 448 if (compression != COMPRESSION_NONE && 449 compression != COMPRESSION_HUFFMAN && 450 compression != COMPRESSION_T4 && 451 compression != COMPRESSION_PACKBITS) 452 return B_NO_TRANSLATOR; 453 454 if (ifd.HasField(TAG_FILL_ORDER)) { 455 fillOrder = ifd.GetUint(TAG_FILL_ORDER); 456 if (fillOrder != 1 && fillOrder != 2) 457 return B_NO_TRANSLATOR; 458 } 459 460 } else if (ifd.GetUint(TAG_BITS_PER_SAMPLE) == 4 || 461 ifd.GetUint(TAG_BITS_PER_SAMPLE) == 8) { 462 bitsPerPixel = ifd.GetUint(TAG_BITS_PER_SAMPLE); 463 464 if (ifd.HasField(TAG_FILL_ORDER) && 465 ifd.GetUint(TAG_FILL_ORDER) != 1) 466 return B_NO_TRANSLATOR; 467 if (compression != COMPRESSION_NONE && 468 compression != COMPRESSION_PACKBITS) 469 return B_NO_TRANSLATOR; 470 } else 471 return B_NO_TRANSLATOR; 472 473 imageType = TIFF_BILEVEL; 474 475 break; 476 477 // Palette color images 478 case PHOTO_PALETTE: 479 if (ifd.HasField(TAG_FILL_ORDER) && 480 ifd.GetUint(TAG_FILL_ORDER) != 1) 481 return B_NO_TRANSLATOR; 482 if (compression != COMPRESSION_NONE && 483 compression != COMPRESSION_PACKBITS) 484 return B_NO_TRANSLATOR; 485 486 // default value for samples per pixel is 1 487 if (ifd.HasField(TAG_SAMPLES_PER_PIXEL) && 488 ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 1) 489 return B_NO_TRANSLATOR; 490 491 bitsPerPixel = ifd.GetUint(TAG_BITS_PER_SAMPLE); 492 if (bitsPerPixel != 4 && bitsPerPixel != 8) 493 return B_NO_TRANSLATOR; 494 495 // ensure that the color map is the expected length 496 if (ifd.GetCount(TAG_COLOR_MAP) != 497 (uint32) (3 * (1 << bitsPerPixel))) 498 return B_NO_TRANSLATOR; 499 500 imageType = TIFF_PALETTE; 501 break; 502 503 case PHOTO_RGB: 504 if (ifd.HasField(TAG_FILL_ORDER) && 505 ifd.GetUint(TAG_FILL_ORDER) != 1) 506 return B_NO_TRANSLATOR; 507 if (compression != COMPRESSION_NONE && 508 compression != COMPRESSION_PACKBITS) 509 return B_NO_TRANSLATOR; 510 511 if (ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 3) 512 return B_NO_TRANSLATOR; 513 if (ifd.GetCount(TAG_BITS_PER_SAMPLE) != 3 || 514 ifd.GetUint(TAG_BITS_PER_SAMPLE, 1) != 8 || 515 ifd.GetUint(TAG_BITS_PER_SAMPLE, 2) != 8 || 516 ifd.GetUint(TAG_BITS_PER_SAMPLE, 3) != 8) 517 return B_NO_TRANSLATOR; 518 519 imageType = TIFF_RGB; 520 break; 521 522 case PHOTO_SEPARATED: 523 if (ifd.HasField(TAG_FILL_ORDER) && 524 ifd.GetUint(TAG_FILL_ORDER) != 1) 525 return B_NO_TRANSLATOR; 526 if (compression != COMPRESSION_NONE && 527 compression != COMPRESSION_PACKBITS) 528 return B_NO_TRANSLATOR; 529 530 // CMYK (default ink set) 531 // is the only ink set supported 532 if (ifd.HasField(TAG_INK_SET) && 533 ifd.GetUint(TAG_INK_SET) != INK_SET_CMYK) 534 return B_NO_TRANSLATOR; 535 536 if (ifd.GetUint(TAG_SAMPLES_PER_PIXEL) != 4) 537 return B_NO_TRANSLATOR; 538 if (ifd.GetCount(TAG_BITS_PER_SAMPLE) != 4 || 539 ifd.GetUint(TAG_BITS_PER_SAMPLE, 1) != 8 || 540 ifd.GetUint(TAG_BITS_PER_SAMPLE, 2) != 8 || 541 ifd.GetUint(TAG_BITS_PER_SAMPLE, 3) != 8 || 542 ifd.GetUint(TAG_BITS_PER_SAMPLE, 4) != 8) 543 return B_NO_TRANSLATOR; 544 545 imageType = TIFF_CMYK; 546 break; 547 548 default: 549 return B_NO_TRANSLATOR; 550 } 551 552 uint32 rowsPerStrip, stripsPerImage; 553 if (!ifd.HasField(TAG_ROWS_PER_STRIP)) 554 rowsPerStrip = DEFAULT_ROWS_PER_STRIP; 555 else 556 rowsPerStrip = ifd.GetUint(TAG_ROWS_PER_STRIP); 557 if (rowsPerStrip == DEFAULT_ROWS_PER_STRIP) 558 stripsPerImage = 1; 559 else 560 stripsPerImage = (height + rowsPerStrip - 1) / rowsPerStrip; 561 562 if (ifd.GetCount(TAG_STRIP_OFFSETS) != stripsPerImage || 563 ifd.GetCount(TAG_STRIP_BYTE_COUNTS) != stripsPerImage) 564 return B_NO_TRANSLATOR; 565 566 // return read in details 567 pdetails->width = width; 568 pdetails->height = height; 569 pdetails->compression = compression; 570 pdetails->t4options = t4options; 571 pdetails->rowsPerStrip = rowsPerStrip; 572 pdetails->stripsPerImage = stripsPerImage; 573 pdetails->interpretation = interpretation; 574 pdetails->bitsPerPixel = bitsPerPixel; 575 pdetails->imageType = imageType; 576 pdetails->fillOrder = fillOrder; 577 578 if (bAllocArrays) { 579 ifd.GetUint32Array(TAG_STRIP_OFFSETS, 580 &pdetails->pstripOffsets); 581 ifd.GetUint32Array(TAG_STRIP_BYTE_COUNTS, 582 &pdetails->pstripByteCounts); 583 584 if (pdetails->imageType == TIFF_PALETTE) 585 ifd.GetAdjustedColorMap(&pdetails->pcolorMap); 586 } 587 588 } catch (TiffIfdException) { 589 return B_NO_TRANSLATOR; 590 } 591 592 return B_OK; 593 } 594 595 // copy descriptive information about the TIFF image 596 // into strname 597 void 598 copy_tiff_name(char *strname, TiffDetails *pdetails, swap_action swp) 599 { 600 if (!strname || !pdetails) 601 return; 602 603 strcpy(strname, "TIFF image ("); 604 605 // byte order 606 if (swp == B_SWAP_BENDIAN_TO_HOST) 607 strcat(strname, "Big, "); 608 else 609 strcat(strname, "Little, "); 610 611 // image type 612 const char *strtype = NULL; 613 switch (pdetails->imageType) { 614 case TIFF_BILEVEL: 615 if (pdetails->bitsPerPixel == 1) 616 strtype = "Mono, "; 617 else 618 strtype = "Gray, "; 619 break; 620 case TIFF_PALETTE: 621 strtype = "Palette, "; 622 break; 623 case TIFF_RGB: 624 strtype = "RGB, "; 625 break; 626 case TIFF_CMYK: 627 strtype = "CMYK, "; 628 break; 629 default: 630 strtype = "??, "; 631 break; 632 } 633 strcat(strname, strtype); 634 635 // compression 636 const char *strcomp = NULL; 637 switch (pdetails->compression) { 638 case COMPRESSION_NONE: 639 strcomp = "None)"; 640 break; 641 case COMPRESSION_HUFFMAN: 642 strcomp = "Huffman)"; 643 break; 644 case COMPRESSION_T4: 645 strcomp = "Group 3)"; 646 break; 647 case COMPRESSION_T6: 648 strcomp = "Group 4)"; 649 break; 650 case COMPRESSION_LZW: 651 strcomp = "LZW)"; 652 break; 653 case COMPRESSION_PACKBITS: 654 strcomp = "PackBits)"; 655 break; 656 default: 657 strcomp = "??)"; 658 break; 659 } 660 strcat(strname, strcomp); 661 } 662 663 status_t 664 identify_tiff_header(BPositionIO *inSource, BMessage *ioExtension, 665 translator_info *outInfo, ssize_t amtread, uint8 *read, swap_action swp, 666 TiffDetails *pdetails = NULL) 667 { 668 if (amtread != 4) 669 return B_ERROR; 670 671 uint32 firstIFDOffset = 0; 672 ssize_t nread = inSource->Read(&firstIFDOffset, 4); 673 if (nread != 4) { 674 // Unable to read first IFD offset 675 return B_NO_TRANSLATOR; 676 } 677 if (swap_data(B_UINT32_TYPE, &firstIFDOffset, 678 sizeof(uint32), swp) != B_OK) { 679 // swap_data() error 680 return B_ERROR; 681 } 682 TiffIfdList ifdlist(firstIFDOffset, *inSource, swp); 683 684 status_t initcheck; 685 initcheck = ifdlist.InitCheck(); 686 687 // Read in some fields in order to determine whether or not 688 // this particular TIFF image is supported by this translator 689 690 // Check the required fields 691 if (initcheck == B_OK) { 692 693 int32 document_count, document_index = 1; 694 document_count = ifdlist.GetCount(); 695 696 if (ioExtension) { 697 // Add page count to ioExtension 698 ioExtension->RemoveName(DOCUMENT_COUNT); 699 ioExtension->AddInt32(DOCUMENT_COUNT, document_count); 700 701 // Check if a document index has been specified 702 ioExtension->FindInt32(DOCUMENT_INDEX, &document_index); 703 if (document_index < 1 || document_index > document_count) 704 return B_NO_TRANSLATOR; 705 } 706 707 // Identify the page the user asked for 708 TiffIfd *pifd = ifdlist.GetIfd(document_index - 1); 709 710 bool bAllocArrays = true; 711 TiffDetails localdetails; 712 if (!pdetails) { 713 bAllocArrays = false; 714 pdetails = &localdetails; 715 } 716 status_t result; 717 result = check_tiff_fields(*pifd, pdetails, bAllocArrays); 718 719 if (result == B_OK && outInfo) { 720 outInfo->type = B_TIFF_FORMAT; 721 outInfo->group = B_TRANSLATOR_BITMAP; 722 outInfo->quality = TIFF_IN_QUALITY; 723 outInfo->capability = TIFF_IN_CAPABILITY; 724 strcpy(outInfo->MIME, "image/tiff"); 725 726 copy_tiff_name(outInfo->name, pdetails, swp); 727 } 728 729 return result; 730 } 731 732 if (initcheck != B_ERROR && initcheck != B_NO_MEMORY) 733 // return B_NO_TRANSLATOR if unexpected data was encountered 734 return B_NO_TRANSLATOR; 735 else 736 // return B_ERROR or B_NO_MEMORY 737 return initcheck; 738 } 739 740 // --------------------------------------------------------------- 741 // Identify 742 // 743 // Examines the data from inSource and determines if it is in a 744 // format that this translator knows how to work with. 745 // 746 // Preconditions: 747 // 748 // Parameters: inSource, where the data to examine is 749 // 750 // inFormat, a hint about the data in inSource, 751 // it is ignored since it is only a hint 752 // 753 // ioExtension, configuration settings for the 754 // translator (not used) 755 // 756 // outInfo, information about what data is in 757 // inSource and how well this translator 758 // can handle that data is stored here 759 // 760 // outType, The format that the user wants 761 // the data in inSource to be 762 // converted to 763 // 764 // Postconditions: 765 // 766 // Returns: B_NO_TRANSLATOR, if this translator can't handle 767 // the data in inSource 768 // 769 // B_ERROR, if there was an error converting the data to the host 770 // format 771 // 772 // B_BAD_VALUE, if the settings in ioExtension are bad 773 // 774 // B_OK, if this translator understood the data and there were 775 // no errors found 776 // 777 // Other errors if BPositionIO::Read() returned an error value 778 // --------------------------------------------------------------- 779 status_t 780 TIFFTranslator::Identify(BPositionIO *inSource, 781 const translation_format *inFormat, BMessage *ioExtension, 782 translator_info *outInfo, uint32 outType) 783 { 784 if (!outType) 785 outType = B_TRANSLATOR_BITMAP; 786 if (outType != B_TRANSLATOR_BITMAP && outType != B_TIFF_FORMAT) 787 return B_NO_TRANSLATOR; 788 789 // Convert the magic numbers to the various byte orders so that 790 // I won't have to convert the data read in to see whether or not 791 // it is a supported type 792 uint32 nbits = B_TRANSLATOR_BITMAP; 793 if (swap_data(B_UINT32_TYPE, &nbits, sizeof(uint32), 794 B_SWAP_HOST_TO_BENDIAN) != B_OK) 795 return B_ERROR; 796 797 // Read in the magic number and determine if it 798 // is a supported type 799 uint8 ch[4]; 800 if (inSource->Read(ch, 4) != 4) 801 return B_NO_TRANSLATOR; 802 803 // Read settings from ioExtension 804 bool bheaderonly = false, bdataonly = false; 805 if (ioExtension) { 806 if (ioExtension->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderonly)) 807 // if failed, make sure bool is default value 808 bheaderonly = false; 809 if (ioExtension->FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bdataonly)) 810 // if failed, make sure bool is default value 811 bdataonly = false; 812 813 if (bheaderonly && bdataonly) 814 // can't both "only write the header" and "only write the data" 815 // at the same time 816 return B_BAD_VALUE; 817 } 818 819 uint32 n32ch; 820 memcpy(&n32ch, ch, sizeof(uint32)); 821 // if B_TRANSLATOR_BITMAP type 822 if (n32ch == nbits) 823 return identify_bits_header(inSource, outInfo, 4, ch); 824 825 // Might be TIFF image 826 else { 827 // TIFF Byte Order / Magic 828 const uint8 kleSig[] = { 0x49, 0x49, 0x2a, 0x00 }; 829 const uint8 kbeSig[] = { 0x4d, 0x4d, 0x00, 0x2a }; 830 831 swap_action swp; 832 if (memcmp(ch, kleSig, 4) == 0) { 833 swp = B_SWAP_LENDIAN_TO_HOST; 834 // Byte Order: little endian 835 } else if (memcmp(ch, kbeSig, 4) == 0) { 836 swp = B_SWAP_BENDIAN_TO_HOST; 837 // Byte Order: big endian 838 } else { 839 // If not a TIFF or a Be Bitmap image 840 // (invalid byte order value) 841 return B_NO_TRANSLATOR; 842 } 843 844 return identify_tiff_header(inSource, ioExtension, outInfo, 4, ch, swp); 845 } 846 } 847 848 void 849 tiff_to_bits(uint8 *ptiff, uint32 tifflen, uint8 *pbits, TiffDetails &details) 850 { 851 uint8 *ptiffend = ptiff + tifflen; 852 853 switch (details.imageType) { 854 case TIFF_BILEVEL: 855 if (details.bitsPerPixel == 1) { 856 // black and white 857 uint8 black[3] = { 0x00, 0x00, 0x00 }, 858 white[3] = { 0xFF, 0xFF, 0xFF }; 859 uint8 *colors[2]; 860 if (details.interpretation == PHOTO_WHITEZERO) { 861 colors[0] = white; 862 colors[1] = black; 863 } else { 864 colors[0] = black; 865 colors[1] = white; 866 } 867 868 for (uint32 i = 0; i < details.width; i++) { 869 uint8 eightbits = (ptiff + (i / 8))[0]; 870 uint8 abit; 871 abit = (eightbits >> (7 - (i % 8))) & 1; 872 873 memcpy(pbits + (i * 4), colors[abit], 3); 874 } 875 } else { 876 // grayscale 877 if (details.bitsPerPixel == 8) { 878 if (details.interpretation == PHOTO_WHITEZERO) { 879 for (uint32 i = 0; i < details.width; i++) { 880 memset(pbits, 255 - ptiff[i], 3); 881 pbits += 4; 882 } 883 } else { 884 for (uint32 i = 0; i < details.width; i++) { 885 memset(pbits, ptiff[i], 3); 886 pbits += 4; 887 } 888 } 889 } else if (details.bitsPerPixel == 4) { 890 const uint8 mask = 0x0f; 891 if (details.interpretation == PHOTO_WHITEZERO) { 892 for (uint32 i = 0; i < details.width; i++) { 893 uint8 values = (ptiff + (i / 2))[0]; 894 uint8 value = (values >> (4 * (1 - (i % 2)))) & mask; 895 memset(pbits, 255 - (value * 16), 3); 896 pbits += 4; 897 } 898 } else { 899 for (uint32 i = 0; i < details.width; i++) { 900 uint8 values = (ptiff + (i / 2))[0]; 901 uint8 value = (values >> (4 * (1 - (i % 2)))) & mask; 902 memset(pbits, (value * 16), 3); 903 pbits += 4; 904 } 905 } 906 } 907 } 908 909 break; 910 911 case TIFF_PALETTE: 912 { 913 // NOTE: All of the entries in the color map were 914 // divided by 256 before they were copied to pcolorMap. 915 // 916 // The first 3rd of the color map is made of the Red values, 917 // the second 3rd of the color map is made of the Green values, 918 // and the last 3rd of the color map is made of the Blue values. 919 if (details.bitsPerPixel == 8) { 920 for (uint32 i = 0; i < details.width; i++) { 921 pbits[2] = details.pcolorMap[ptiff[i]]; 922 pbits[1] = details.pcolorMap[256 + ptiff[i]]; 923 pbits[0] = details.pcolorMap[512 + ptiff[i]]; 924 925 pbits += 4; 926 } 927 } else if (details.bitsPerPixel == 4) { 928 const uint8 mask = 0x0f; 929 for (uint32 i = 0; i < details.width; i++) { 930 uint8 indices = (ptiff + (i / 2))[0]; 931 uint8 index = (indices >> (4 * (1 - (i % 2)))) & mask; 932 933 pbits[2] = details.pcolorMap[index]; 934 pbits[1] = details.pcolorMap[16 + index]; 935 pbits[0] = details.pcolorMap[32 + index]; 936 937 pbits += 4; 938 } 939 } 940 break; 941 } 942 943 case TIFF_RGB: 944 while (ptiff < ptiffend) { 945 pbits[2] = ptiff[0]; 946 pbits[1] = ptiff[1]; 947 pbits[0] = ptiff[2]; 948 949 ptiff += 3; 950 pbits += 4; 951 } 952 break; 953 954 case TIFF_CMYK: 955 { 956 while (ptiff < ptiffend) { 957 int32 comp; 958 comp = 255 - ptiff[0] - ptiff[3]; 959 pbits[2] = (comp < 0) ? 0 : comp; 960 961 comp = 255 - ptiff[1] - ptiff[3]; 962 pbits[1] = (comp < 0) ? 0 : comp; 963 964 comp = 255 - ptiff[2] - ptiff[3]; 965 pbits[0] = (comp < 0) ? 0 : comp; 966 967 ptiff += 4; 968 pbits += 4; 969 } 970 break; 971 } 972 } 973 } 974 975 // unpack the Packbits compressed data from 976 // pstreambuf and put it into tiffbuffer 977 ssize_t 978 unpack(StreamBuffer *pstreambuf, uint8 *tiffbuffer, uint32 tiffbufferlen) 979 { 980 uint32 tiffwrit = 0, read = 0, len; 981 while (tiffwrit < tiffbufferlen) { 982 983 uint8 uctrl; 984 if (pstreambuf->Read(&uctrl, 1) != 1) 985 return B_ERROR; 986 read++; 987 988 int32 control; 989 control = static_cast<signed char>(uctrl); 990 991 // copy control + 1 bytes literally 992 if (control >= 0 && control <= 127) { 993 994 len = control + 1; 995 if (tiffwrit + len > tiffbufferlen) 996 return B_ERROR; 997 if (pstreambuf->Read(tiffbuffer + tiffwrit, len) != 998 static_cast<ssize_t>(len)) 999 return B_ERROR; 1000 read += len; 1001 1002 tiffwrit += len; 1003 1004 // copy the next byte (-control) + 1 times 1005 } else if (control >= -127 && control <= -1) { 1006 1007 uint8 byt; 1008 if (pstreambuf->Read(&byt, 1) != 1) 1009 return B_ERROR; 1010 read++; 1011 1012 len = (-control) + 1; 1013 if (tiffwrit + len > tiffbufferlen) 1014 return B_ERROR; 1015 memset(tiffbuffer + tiffwrit, byt, len); 1016 1017 tiffwrit += len; 1018 } 1019 } 1020 1021 return read; 1022 } 1023 1024 ssize_t 1025 TIFFTranslator::decode_t4(BitReader &stream, TiffDetails &details, 1026 uint8 *pbits, bool bfirstLine) 1027 { 1028 if (bfirstLine) { 1029 // determine number of fill bits 1030 // (if that T4Option is set) 1031 uint32 fillbits = 0; 1032 if (details.t4options & T4_FILL_BYTE_BOUNDARY) { 1033 fillbits = (12 - stream.BitsInBuffer()) % 8; 1034 if (fillbits) 1035 fillbits = 8 - fillbits; 1036 } 1037 // read in and verify end-of-line sequence 1038 uint32 nzeros = 11 + fillbits; 1039 while (nzeros--) { 1040 if (stream.NextBit() != 0) { 1041 debugger("EOL: expected zero bit"); 1042 return B_ERROR; 1043 } 1044 } 1045 if (stream.NextBit() != 1) { 1046 debugger("EOL: expected one bit"); 1047 return B_ERROR; 1048 } 1049 } 1050 1051 const uint8 kblack = 0x00, kwhite = 0xff; 1052 uint8 colors[2]; 1053 if (details.interpretation == PHOTO_WHITEZERO) { 1054 colors[0] = kwhite; 1055 colors[1] = kblack; 1056 } else { 1057 colors[0] = kblack; 1058 colors[1] = kwhite; 1059 } 1060 1061 uint32 pixelswrit = 0; 1062 DecodeTree *ptrees[2] = {fpwhiteTree, fpblackTree}; 1063 uint8 currentcolor = 0; 1064 uint8 *pcurrentpixel = pbits; 1065 status_t value = 0; 1066 while (pixelswrit < details.width || value >= 64) { 1067 value = ptrees[currentcolor]->GetValue(stream); 1068 if (value < 0) { 1069 debugger("value < 0"); 1070 return B_ERROR; 1071 } 1072 1073 if (pixelswrit + value > details.width) { 1074 debugger("gone past end of line"); 1075 return B_ERROR; 1076 } 1077 pixelswrit += value; 1078 1079 // covert run length to B_RGB32 pixels 1080 uint32 pixelsleft = value; 1081 while (pixelsleft--) { 1082 memset(pcurrentpixel, colors[currentcolor], 3); 1083 pcurrentpixel += 4; 1084 } 1085 1086 if (value < 64) 1087 currentcolor = 1 - currentcolor; 1088 } 1089 1090 // determine number of fill bits 1091 // (if that T4Option is set) 1092 uint32 fillbits = 0; 1093 if (details.t4options & T4_FILL_BYTE_BOUNDARY) { 1094 fillbits = (12 - stream.BitsInBuffer()) % 8; 1095 if (fillbits) 1096 fillbits = 8 - fillbits; 1097 } 1098 // read in end-of-line sequence 1099 uint32 ndontcare = 12 + fillbits; 1100 status_t sbit = 0; 1101 while (ndontcare--) { 1102 sbit = stream.NextBit(); 1103 if (sbit != 0 && sbit != 1) { 1104 debugger("EOL: couldn't read all bits"); 1105 return B_ERROR; 1106 } 1107 } 1108 1109 return stream.BytesRead(); 1110 } 1111 1112 ssize_t 1113 TIFFTranslator::decode_huffman(StreamBuffer *pstreambuf, TiffDetails &details, 1114 uint8 *pbits) 1115 { 1116 BitReader stream(details.fillOrder, pstreambuf); 1117 if (stream.InitCheck() != B_OK) { 1118 debugger("stream init error"); 1119 return B_ERROR; 1120 } 1121 1122 const uint8 kblack = 0x00, kwhite = 0xff; 1123 uint8 colors[2]; 1124 if (details.interpretation == PHOTO_WHITEZERO) { 1125 colors[0] = kwhite; 1126 colors[1] = kblack; 1127 } else { 1128 colors[0] = kblack; 1129 colors[1] = kwhite; 1130 } 1131 1132 uint32 pixelswrit = 0; 1133 DecodeTree *ptrees[2] = {fpwhiteTree, fpblackTree}; 1134 uint8 currentcolor = 0; 1135 uint8 *pcurrentpixel = pbits; 1136 status_t value = 0; 1137 while (pixelswrit < details.width || value >= 64) { 1138 value = ptrees[currentcolor]->GetValue(stream); 1139 if (value < 0) { 1140 debugger("value < 0"); 1141 return B_ERROR; 1142 } 1143 1144 if (pixelswrit + value > details.width) { 1145 debugger("gone past end of line"); 1146 return B_ERROR; 1147 } 1148 pixelswrit += value; 1149 1150 // covert run length to B_RGB32 pixels 1151 uint32 pixelsleft = value; 1152 while (pixelsleft--) { 1153 memset(pcurrentpixel, colors[currentcolor], 3); 1154 pcurrentpixel += 4; 1155 } 1156 1157 if (value < 64) 1158 currentcolor = 1 - currentcolor; 1159 } 1160 1161 return stream.BytesRead(); 1162 } 1163 1164 status_t 1165 TIFFTranslator::translate_from_tiff(BPositionIO *inSource, 1166 BMessage *ioExtension, ssize_t amtread, uint8 *read, swap_action swp, 1167 uint32 outType, BPositionIO *outDestination) 1168 { 1169 // Can only output to bits for now 1170 if (outType != B_TRANSLATOR_BITMAP) 1171 return B_NO_TRANSLATOR; 1172 1173 status_t result; 1174 1175 TiffDetails details; 1176 result = identify_tiff_header(inSource, ioExtension, NULL, 1177 amtread, read, swp, &details); 1178 if (result == B_OK) { 1179 // If the TIFF is supported by this translator 1180 1181 // If TIFF uses Huffman compression, load 1182 // trees for decoding Huffman compression 1183 if (details.compression == COMPRESSION_HUFFMAN || 1184 details.compression == COMPRESSION_T4) { 1185 result = LoadHuffmanTrees(); 1186 if (result != B_OK) 1187 return result; 1188 } 1189 1190 TranslatorBitmap bitsHeader; 1191 bitsHeader.magic = B_TRANSLATOR_BITMAP; 1192 bitsHeader.bounds.left = 0; 1193 bitsHeader.bounds.top = 0; 1194 bitsHeader.bounds.right = details.width - 1; 1195 bitsHeader.bounds.bottom = details.height - 1; 1196 bitsHeader.rowBytes = 4 * details.width; 1197 bitsHeader.colors = B_RGB32; 1198 bitsHeader.dataSize = bitsHeader.rowBytes * details.height; 1199 1200 // write out Be's Bitmap header 1201 if (swap_data(B_UINT32_TYPE, &bitsHeader, 1202 sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) 1203 return B_ERROR; 1204 outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap)); 1205 1206 uint32 inbufferlen, outbufferlen; 1207 outbufferlen = 4 * details.width; 1208 switch (details.imageType) { 1209 case TIFF_BILEVEL: 1210 case TIFF_PALETTE: 1211 { 1212 uint32 pixelsPerByte = 8 / details.bitsPerPixel; 1213 inbufferlen = (details.width / pixelsPerByte) + 1214 ((details.width % pixelsPerByte) ? 1 : 0); 1215 break; 1216 } 1217 case TIFF_RGB: 1218 inbufferlen = 3 * details.width; 1219 break; 1220 1221 case TIFF_CMYK: 1222 inbufferlen = 4 * details.width; 1223 break; 1224 1225 default: 1226 // just to be safe 1227 return B_NO_TRANSLATOR; 1228 } 1229 1230 uint8 *inbuffer = new uint8[inbufferlen], 1231 *outbuffer = new uint8[outbufferlen]; 1232 if (!inbuffer || !outbuffer) 1233 return B_NO_MEMORY; 1234 // set all channels to 0xff so that I won't have 1235 // to set the alpha byte to 0xff every time 1236 memset(outbuffer, 0xff, outbufferlen); 1237 1238 // buffer for making reading compressed data 1239 // fast and convenient 1240 StreamBuffer *pstreambuf = NULL; 1241 BitReader bitreader(details.fillOrder, pstreambuf, false); 1242 // this creates an invalid bitreader, but it is 1243 // initialized properly with the SetTo() call 1244 if (details.compression != COMPRESSION_NONE) { 1245 pstreambuf = new StreamBuffer(inSource, 2048, false); 1246 if (pstreambuf->InitCheck() != B_OK) 1247 return B_NO_MEMORY; 1248 } 1249 1250 bool bfirstLine = true; 1251 for (uint32 i = 0; i < details.stripsPerImage; i++) { 1252 uint32 read = 0; 1253 1254 // If using compression, prepare streambuffer 1255 // for reading 1256 if (details.compression != COMPRESSION_NONE && 1257 !pstreambuf->Seek(details.pstripOffsets[i])) 1258 return B_NO_TRANSLATOR; 1259 1260 if (details.compression == COMPRESSION_T4 && 1261 bitreader.SetTo(details.fillOrder, pstreambuf) != B_OK) 1262 return B_NO_TRANSLATOR; 1263 1264 // Read / Write one line at a time for each 1265 // line in the strip 1266 while (read < details.pstripByteCounts[i]) { 1267 1268 ssize_t ret = 0; 1269 switch (details.compression) { 1270 case COMPRESSION_NONE: 1271 ret = inSource->ReadAt(details.pstripOffsets[i] + read, 1272 inbuffer, inbufferlen); 1273 if (ret != static_cast<ssize_t>(inbufferlen)) 1274 // break out of while loop 1275 ret = -1; 1276 break; 1277 1278 case COMPRESSION_HUFFMAN: 1279 ret = decode_huffman(pstreambuf, details, outbuffer); 1280 if (ret < 1) 1281 // break out of while loop 1282 ret = -1; 1283 break; 1284 1285 case COMPRESSION_T4: 1286 ret = decode_t4(bitreader, details, outbuffer, 1287 bfirstLine); 1288 if (ret < 1) 1289 // break out of while loop 1290 ret = -1; 1291 else 1292 ret -= read; 1293 // unlike other decoders, decode_t4 retruns 1294 // the total bytes read from the current 1295 // strip 1296 break; 1297 1298 case COMPRESSION_PACKBITS: 1299 ret = unpack(pstreambuf, inbuffer, inbufferlen); 1300 if (ret < 1) 1301 // break out of while loop 1302 ret = -1; 1303 break; 1304 } 1305 if (ret < 0) 1306 break; 1307 1308 read += ret; 1309 if (details.compression != COMPRESSION_HUFFMAN && 1310 details.compression != COMPRESSION_T4) 1311 tiff_to_bits(inbuffer, inbufferlen, outbuffer, details); 1312 outDestination->Write(outbuffer, outbufferlen); 1313 bfirstLine = false; 1314 } 1315 // If while loop was broken... 1316 if (read < details.pstripByteCounts[i]) { 1317 debugger("while loop broken"); 1318 break; 1319 } 1320 } 1321 1322 // Clean up 1323 if (pstreambuf) { 1324 delete pstreambuf; 1325 pstreambuf = NULL; 1326 } 1327 1328 delete[] inbuffer; 1329 inbuffer = NULL; 1330 delete[] outbuffer; 1331 outbuffer = NULL; 1332 1333 return B_OK; 1334 1335 } else 1336 return result; 1337 } 1338 1339 // --------------------------------------------------------------- 1340 // Translate 1341 // 1342 // Translates the data in inSource to the type outType and stores 1343 // the translated data in outDestination. 1344 // 1345 // Preconditions: 1346 // 1347 // Parameters: inSource, the data to be translated 1348 // 1349 // inInfo, hint about the data in inSource (not used) 1350 // 1351 // ioExtension, configuration options for the 1352 // translator 1353 // 1354 // outType, the type to convert inSource to 1355 // 1356 // outDestination, where the translated data is 1357 // put 1358 // 1359 // Postconditions: 1360 // 1361 // Returns: B_BAD_VALUE, if the options in ioExtension are bad 1362 // 1363 // B_NO_TRANSLATOR, if this translator doesn't understand the data 1364 // 1365 // B_ERROR, if there was an error allocating memory or converting 1366 // data 1367 // 1368 // B_OK, if all went well 1369 // --------------------------------------------------------------- 1370 status_t 1371 TIFFTranslator::Translate(BPositionIO *inSource, 1372 const translator_info *inInfo, BMessage *ioExtension, 1373 uint32 outType, BPositionIO *outDestination) 1374 { 1375 if (!outType) 1376 outType = B_TRANSLATOR_BITMAP; 1377 if (outType != B_TRANSLATOR_BITMAP && outType != B_TIFF_FORMAT) 1378 return B_NO_TRANSLATOR; 1379 1380 // Convert the magic numbers to the various byte orders so that 1381 // I won't have to convert the data read in to see whether or not 1382 // it is a supported type 1383 uint32 nbits = B_TRANSLATOR_BITMAP; 1384 if (swap_data(B_UINT32_TYPE, &nbits, sizeof(uint32), 1385 B_SWAP_HOST_TO_BENDIAN) != B_OK) 1386 return B_ERROR; 1387 1388 // Read in the magic number and determine if it 1389 // is a supported type 1390 uint8 ch[4]; 1391 inSource->Seek(0, SEEK_SET); 1392 if (inSource->Read(ch, 4) != 4) 1393 return B_NO_TRANSLATOR; 1394 1395 // Read settings from ioExtension 1396 bool bheaderonly = false, bdataonly = false; 1397 if (ioExtension) { 1398 if (ioExtension->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderonly)) 1399 // if failed, make sure bool is default value 1400 bheaderonly = false; 1401 if (ioExtension->FindBool(B_TRANSLATOR_EXT_DATA_ONLY, &bdataonly)) 1402 // if failed, make sure bool is default value 1403 bdataonly = false; 1404 1405 if (bheaderonly && bdataonly) 1406 // can't both "only write the header" and "only write the data" 1407 // at the same time 1408 return B_BAD_VALUE; 1409 } 1410 1411 uint32 n32ch; 1412 memcpy(&n32ch, ch, sizeof(uint32)); 1413 // if B_TRANSLATOR_BITMAP type 1414 if (n32ch == nbits) 1415 return B_NO_TRANSLATOR; 1416 // Not implemented yet 1417 1418 // Might be TIFF image 1419 else { 1420 // TIFF Byte Order / Magic 1421 const uint8 kleSig[] = { 0x49, 0x49, 0x2a, 0x00 }; 1422 const uint8 kbeSig[] = { 0x4d, 0x4d, 0x00, 0x2a }; 1423 1424 swap_action swp; 1425 if (memcmp(ch, kleSig, 4) == 0) { 1426 swp = B_SWAP_LENDIAN_TO_HOST; 1427 // Byte Order: little endian 1428 } else if (memcmp(ch, kbeSig, 4) == 0) { 1429 swp = B_SWAP_BENDIAN_TO_HOST; 1430 // Byte Order: big endian 1431 } else { 1432 // If not a TIFF or a Be Bitmap image 1433 // (invalid byte order value) 1434 return B_NO_TRANSLATOR; 1435 } 1436 1437 return translate_from_tiff(inSource, ioExtension, 4, ch, swp, outType, 1438 outDestination); 1439 } 1440 } 1441 1442 // --------------------------------------------------------------- 1443 // MakeConfigurationView 1444 // 1445 // Makes a BView object for configuring / displaying info about 1446 // this translator. 1447 // 1448 // Preconditions: 1449 // 1450 // Parameters: ioExtension, configuration options for the 1451 // translator 1452 // 1453 // outView, the view to configure the 1454 // translator is stored here 1455 // 1456 // outExtent, the bounds of the view are 1457 // stored here 1458 // 1459 // Postconditions: 1460 // 1461 // Returns: B_BAD_VALUE if outView or outExtent is NULL, 1462 // B_NO_MEMORY if the view couldn't be allocated, 1463 // B_OK if no errors 1464 // --------------------------------------------------------------- 1465 status_t 1466 TIFFTranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView, 1467 BRect *outExtent) 1468 { 1469 if (!outView || !outExtent) 1470 return B_BAD_VALUE; 1471 1472 TIFFView *view = new TIFFView(BRect(0, 0, 225, 175), 1473 "TIFFTranslator Settings", B_FOLLOW_ALL, B_WILL_DRAW); 1474 if (!view) 1475 return B_NO_MEMORY; 1476 1477 *outView = view; 1478 *outExtent = view->Bounds(); 1479 1480 return B_OK; 1481 } 1482 1483 // Initialize the Huffman decoding trees and 1484 // verify that there were no initialization errors 1485 status_t 1486 TIFFTranslator::LoadHuffmanTrees() 1487 { 1488 if (!fpblackTree) { 1489 fpblackTree = new DecodeTree(false); 1490 if (!fpblackTree) 1491 return B_NO_MEMORY; 1492 } 1493 if (!fpwhiteTree) { 1494 fpwhiteTree = new DecodeTree(true); 1495 if (!fpwhiteTree) 1496 return B_NO_MEMORY; 1497 } 1498 1499 if (fpblackTree->InitCheck() != B_OK) 1500 return fpblackTree->InitCheck(); 1501 1502 return fpwhiteTree->InitCheck(); 1503 } 1504 1505