xref: /haiku/src/add-ons/translators/tiff/TIFFTranslator.cpp (revision 1e36cfc2721ef13a187c6f7354dc9cbc485e89d3)
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