xref: /haiku/src/add-ons/translators/tga/TGATranslator.cpp (revision c237c4ce593ee823d9867fd997e51e4c447f5623)
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.
44 static const translation_format sInputFormats[] = {
45 	{
46 		B_TRANSLATOR_BITMAP,
47 		B_TRANSLATOR_BITMAP,
48 		BBT_IN_QUALITY,
49 		BBT_IN_CAPABILITY,
50 		"image/x-be-bitmap",
51 		"Be Bitmap Format (TGATranslator)"
52 	},
53 	{
54 		B_TGA_FORMAT,
55 		B_TRANSLATOR_BITMAP,
56 		TGA_IN_QUALITY,
57 		TGA_IN_CAPABILITY,
58 		"image/x-targa",
59 		"Targa image"
60 	}
61 };
62 
63 // The output formats that this translator supports.
64 static const translation_format sOutputFormats[] = {
65 	{
66 		B_TRANSLATOR_BITMAP,
67 		B_TRANSLATOR_BITMAP,
68 		BBT_OUT_QUALITY,
69 		BBT_OUT_CAPABILITY,
70 		"image/x-be-bitmap",
71 		"Be Bitmap Format (TGATranslator)"
72 	},
73 	{
74 		B_TGA_FORMAT,
75 		B_TRANSLATOR_BITMAP,
76 		TGA_OUT_QUALITY,
77 		TGA_OUT_CAPABILITY,
78 		"image/x-targa",
79 		"Targa image"
80 	}
81 };
82 
83 // Default settings for the Translator
84 static const TranSetting sDefaultSettings[] = {
85 	{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
86 	{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false},
87 	{TGA_SETTING_RLE, TRAN_SETTING_BOOL, false},
88 		// RLE compression is off by default
89 	{TGA_SETTING_IGNORE_ALPHA, TRAN_SETTING_BOOL, false}
90 		// Don't ignore the alpha channel by default
91 };
92 
93 const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
94 const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
95 const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
96 
97 
98 // ---------------------------------------------------------------
99 // make_nth_translator
100 //
101 // Creates a TGATranslator object to be used by BTranslatorRoster
102 //
103 // Preconditions:
104 //
105 // Parameters: n,		The translator to return. Since
106 //						TGATranslator only publishes one
107 //						translator, it only returns a
108 //						TGATranslator if n == 0
109 //
110 //             you, 	The image_id of the add-on that
111 //						contains code (not used).
112 //
113 //             flags,	Has no meaning yet, should be 0.
114 //
115 // Postconditions:
116 //
117 // Returns: NULL if n is not zero,
118 //          a new TGATranslator if n is zero
119 // ---------------------------------------------------------------
120 BTranslator *
121 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
122 {
123 	BTranslator *ptranslator = NULL;
124 	if (!n)
125 		ptranslator = new(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 // ---------------------------------------------------------------
144 TGATranslator::TGATranslator()
145 	: BaseTranslator(B_TRANSLATE("TGA images"),
146 		B_TRANSLATE("TGA image translator"),
147 		TGA_TRANSLATOR_VERSION,
148 		sInputFormats, kNumInputFormats,
149 		sOutputFormats, kNumOutputFormats,
150 		"TGATranslator_Settings",
151 		sDefaultSettings, kNumDefaultSettings,
152 		B_TRANSLATOR_BITMAP, B_TGA_FORMAT)
153 {
154 }
155 
156 // ---------------------------------------------------------------
157 // Destructor
158 //
159 // Does nothing
160 //
161 // Preconditions:
162 //
163 // Parameters:
164 //
165 // Postconditions:
166 //
167 // Returns:
168 // ---------------------------------------------------------------
169 //
170 // NOTE: It may be the case, that under Be's libtranslation.so,
171 // that this destructor will never be called
172 TGATranslator::~TGATranslator()
173 {
174 }
175 
176 uint8
177 TGATranslator::tga_alphabits(TGAFileHeader &filehead, TGAColorMapSpec &mapspec,
178 	TGAImageSpec &imagespec)
179 {
180 	if (fSettings->SetGetBool(TGA_SETTING_IGNORE_ALPHA))
181 		return 0;
182 	else {
183 		uint8 nalpha;
184 		if (filehead.imagetype == TGA_NOCOMP_COLORMAP ||
185 			filehead.imagetype == TGA_RLE_COLORMAP) {
186 			// color mapped images
187 
188 			if (mapspec.entrysize == 32)
189 				nalpha = 8;
190 			else if (mapspec.entrysize == 16)
191 				nalpha = 1;
192 			else
193 				nalpha = 0;
194 
195 		} else {
196 			// non-color mapped images
197 
198 			if (imagespec.depth == 32)
199 				// Some programs that generate 32-bit TGA files
200 				// have an alpha channel, but have an incorrect
201 				// descriptor which says there are no alpha bits.
202 				// This logic is so that the alpha data can be
203 				// obtained from TGA files that lie.
204 				nalpha = 8;
205 			else
206 				nalpha = imagespec.descriptor & TGA_DESC_ALPHABITS;
207 		}
208 
209 		return nalpha;
210 	}
211 }
212 
213 // ---------------------------------------------------------------
214 // identify_tga_header
215 //
216 // Determines if the data in inSource is in the TGA format.
217 // If it is, it returns info about the data in inSource
218 // to outInfo, pfileheader, pmapspec and pimagespec.
219 //
220 // Preconditions:
221 //
222 // Parameters:	inSource,	The source of the image data
223 //
224 //				outInfo,	Information about the translator
225 //							is copied here
226 //
227 //				pfileheader,	File header info for the TGA is
228 //								copied here after it is read from
229 //								the file.
230 //
231 //				pmapspec,	color map info for the TGA is copied
232 //							here after it is read from the file
233 //
234 //				pimagespec,	Info about the image width/height etc.
235 //							is copied here after it is read from
236 //							the file
237 //
238 //
239 // Postconditions:
240 //
241 // Returns: B_NO_TRANSLATOR,	if the data does not look like
242 //								TGA format data
243 //
244 // B_ERROR,	if the header data could not be converted to host
245 //			format
246 //
247 // B_OK,	if the data looks like bits data and no errors were
248 //			encountered
249 // ---------------------------------------------------------------
250 status_t
251 identify_tga_header(BPositionIO *inSource, translator_info *outInfo,
252 	TGAFileHeader *pfileheader = NULL, TGAColorMapSpec *pmapspec = NULL,
253 	TGAImageSpec *pimagespec = NULL)
254 {
255 	uint8 buf[TGA_HEADERS_SIZE];
256 
257 	// read in the rest of the TGA headers
258 	ssize_t size = TGA_HEADERS_SIZE;
259 	if (size > 0 && inSource->Read(buf, size) != size)
260 		return B_NO_TRANSLATOR;
261 
262 	// Read in TGA file header
263 	TGAFileHeader fileheader;
264 	fileheader.idlength = buf[0];
265 
266 	fileheader.colormaptype = buf[1];
267 	if (fileheader.colormaptype > 1)
268 		return B_NO_TRANSLATOR;
269 
270 	fileheader.imagetype = buf[2];
271 	if ((fileheader.imagetype > 3 && fileheader.imagetype < 9) ||
272 		fileheader.imagetype > 11)
273 		return B_NO_TRANSLATOR;
274 	if ((fileheader.colormaptype == TGA_NO_COLORMAP &&
275 		fileheader.imagetype == TGA_NOCOMP_COLORMAP) ||
276 		(fileheader.colormaptype == TGA_COLORMAP &&
277 			fileheader.imagetype != TGA_NOCOMP_COLORMAP &&
278 			fileheader.imagetype != TGA_RLE_COLORMAP))
279 		return B_NO_TRANSLATOR;
280 
281 	// Read in TGA color map spec
282 	TGAColorMapSpec mapspec;
283 	memcpy(&mapspec.firstentry, buf + 3, 2);
284 	mapspec.firstentry = B_LENDIAN_TO_HOST_INT16(mapspec.firstentry);
285 	if (fileheader.colormaptype == 0 && mapspec.firstentry != 0)
286 		return B_NO_TRANSLATOR;
287 
288 	memcpy(&mapspec.length, buf + 5, 2);
289 	mapspec.length = B_LENDIAN_TO_HOST_INT16(mapspec.length);
290 	if (fileheader.colormaptype == TGA_NO_COLORMAP &&
291 		mapspec.length != 0)
292 		return B_NO_TRANSLATOR;
293 	if (fileheader.colormaptype == TGA_COLORMAP &&
294 		mapspec.length == 0)
295 		return B_NO_TRANSLATOR;
296 
297 	mapspec.entrysize = buf[7];
298 	if (fileheader.colormaptype == TGA_NO_COLORMAP &&
299 		mapspec.entrysize != 0)
300 		return B_NO_TRANSLATOR;
301 	if (fileheader.colormaptype == TGA_COLORMAP &&
302 		mapspec.entrysize != 15 && mapspec.entrysize != 16 &&
303 		mapspec.entrysize != 24 && mapspec.entrysize != 32)
304 		return B_NO_TRANSLATOR;
305 
306 	// Read in TGA image spec
307 	TGAImageSpec imagespec;
308 	memcpy(&imagespec.xorigin, buf + 8, 2);
309 	imagespec.xorigin = B_LENDIAN_TO_HOST_INT16(imagespec.xorigin);
310 
311 	memcpy(&imagespec.yorigin, buf + 10, 2);
312 	imagespec.yorigin = B_LENDIAN_TO_HOST_INT16(imagespec.yorigin);
313 
314 	memcpy(&imagespec.width, buf + 12, 2);
315 	imagespec.width = B_LENDIAN_TO_HOST_INT16(imagespec.width);
316 	if (imagespec.width == 0)
317 		return B_NO_TRANSLATOR;
318 
319 	memcpy(&imagespec.height, buf + 14, 2);
320 	imagespec.height = B_LENDIAN_TO_HOST_INT16(imagespec.height);
321 	if (imagespec.height == 0)
322 		return B_NO_TRANSLATOR;
323 
324 	imagespec.depth = buf[16];
325 	if (imagespec.depth < 1 || imagespec.depth > 32)
326 		return B_NO_TRANSLATOR;
327 	if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR ||
328 			fileheader.imagetype == TGA_RLE_TRUECOLOR) &&
329 		imagespec.depth != 15 && imagespec.depth != 16 &&
330 		imagespec.depth != 24 && imagespec.depth != 32)
331 		return B_NO_TRANSLATOR;
332 	if ((fileheader.imagetype == TGA_NOCOMP_BW ||
333 			fileheader.imagetype == TGA_RLE_BW) &&
334 		imagespec.depth != 8)
335 		return B_NO_TRANSLATOR;
336 	if (fileheader.colormaptype == TGA_COLORMAP &&
337 		imagespec.depth != 8)
338 		return B_NO_TRANSLATOR;
339 
340 	imagespec.descriptor = buf[17];
341 	// images ordered from Right to Left (rather than Left to Right)
342 	// are not supported
343 	if ((imagespec.descriptor & TGA_ORIGIN_HORZ_BIT) != TGA_ORIGIN_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 
435 status_t
436 TGATranslator::DerivedIdentify(BPositionIO *inSource,
437 	const translation_format *inFormat, BMessage *ioExtension,
438 	translator_info *outInfo, uint32 outType)
439 {
440 	return identify_tga_header(inSource, outInfo);
441 }
442 
443 // Convert width pixels from pbits to TGA format, storing the
444 // result in ptga
445 status_t
446 pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
447 	uint16 width, const color_map *pmap, int32 bitsBytesPerPixel)
448 {
449 	status_t bytescopied = 0;
450 
451 	switch (fromspace) {
452 		case B_RGBA32:
453 			bytescopied = width * 4;
454 			memcpy(ptga, pbits, bytescopied);
455 			break;
456 
457 		case B_RGBA32_BIG:
458 			bytescopied = width * 4;
459 			while (width--) {
460 				ptga[0] = pbits[3];
461 				ptga[1] = pbits[2];
462 				ptga[2] = pbits[1];
463 				ptga[3] = pbits[0];
464 
465 				ptga += 4;
466 				pbits += 4;
467 			}
468 			break;
469 
470 		case B_CMYA32:
471 			bytescopied = width * 4;
472 			while (width--) {
473 				ptga[0] = 255 - pbits[2];
474 				ptga[1] = 255 - pbits[1];
475 				ptga[2] = 255 - pbits[0];
476 				ptga[3] = pbits[3];
477 
478 				ptga += 4;
479 				pbits += 4;
480 			}
481 			break;
482 
483 		case B_RGB32:
484 		case B_RGB24:
485 			bytescopied = width * 3;
486 			while (width--) {
487 				memcpy(ptga, pbits, 3);
488 
489 				ptga += 3;
490 				pbits += bitsBytesPerPixel;
491 			}
492 			break;
493 
494 		case B_CMYK32:
495 		{
496 			int32 comp;
497 			bytescopied = width * 3;
498 			while (width--) {
499 				comp = 255 - pbits[2] - pbits[3];
500 				ptga[0] = (comp < 0) ? 0 : comp;
501 
502 				comp = 255 - pbits[1] - pbits[3];
503 				ptga[1] = (comp < 0) ? 0 : comp;
504 
505 				comp = 255 - pbits[0] - pbits[3];
506 				ptga[2] = (comp < 0) ? 0 : comp;
507 
508 				ptga += 3;
509 				pbits += 4;
510 			}
511 			break;
512 		}
513 
514 		case B_CMY32:
515 		case B_CMY24:
516 			bytescopied = width * 3;
517 			while (width--) {
518 				ptga[0] = 255 - pbits[2];
519 				ptga[1] = 255 - pbits[1];
520 				ptga[2] = 255 - pbits[0];
521 
522 				ptga += 3;
523 				pbits += bitsBytesPerPixel;
524 			}
525 			break;
526 
527 		case B_RGB16:
528 		case B_RGB16_BIG:
529 		{
530 			// Expand to 24 bit because the TGA format handles
531 			// 16 bit images differently than the Be Image Format
532 			// which would cause a loss in quality
533 			uint16 val;
534 			bytescopied = width * 3;
535 			while (width--) {
536 				if (fromspace == B_RGB16)
537 					val = pbits[0] + (pbits[1] << 8);
538 				else
539 					val = pbits[1] + (pbits[0] << 8);
540 
541 				ptga[0] =
542 					((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
543 				ptga[1] =
544 					((val & 0x7e0) >> 3) | ((val & 0x7e0) >> 9);
545 				ptga[2] =
546 					((val & 0xf800) >> 8) | ((val & 0xf800) >> 13);
547 
548 				ptga += 3;
549 				pbits += 2;
550 			}
551 			break;
552 		}
553 
554 		case B_RGBA15:
555 			bytescopied = width * 2;
556 			memcpy(ptga, pbits, bytescopied);
557 			break;
558 
559 		case B_RGBA15_BIG:
560 			bytescopied = width * 2;
561 			while (width--) {
562 				ptga[0] = pbits[1];
563 				ptga[1] = pbits[0];
564 
565 				ptga += 2;
566 				pbits += 2;
567 			}
568 			break;
569 
570 		case B_RGB15:
571 			bytescopied = width * 2;
572 			while (width--) {
573 				ptga[0] = pbits[0];
574 				ptga[1] = pbits[1] | 0x80;
575 					// alpha bit is always 1
576 
577 				ptga += 2;
578 				pbits += 2;
579 			}
580 			break;
581 
582 		case B_RGB15_BIG:
583 			bytescopied = width * 2;
584 			while (width--) {
585 				ptga[0] = pbits[1];
586 				ptga[1] = pbits[0] | 0x80;
587 					// alpha bit is always 1
588 
589 				ptga += 2;
590 				pbits += 2;
591 			}
592 			break;
593 
594 		case B_RGB32_BIG:
595 			bytescopied = width * 3;
596 			while (width--) {
597 				ptga[0] = pbits[3];
598 				ptga[1] = pbits[2];
599 				ptga[2] = pbits[1];
600 
601 				ptga += 3;
602 				pbits += 4;
603 			}
604 			break;
605 
606 		case B_RGB24_BIG:
607 			bytescopied = width * 3;
608 			while (width--) {
609 				ptga[0] = pbits[2];
610 				ptga[1] = pbits[1];
611 				ptga[2] = pbits[0];
612 
613 				ptga += 3;
614 				pbits += 3;
615 			}
616 			break;
617 
618 		case B_CMAP8:
619 		{
620 			rgb_color c;
621 			bytescopied = width * 3;
622 			while (width--) {
623 				c = pmap->color_list[pbits[0]];
624 				ptga[0] = c.blue;
625 				ptga[1] = c.green;
626 				ptga[2] = c.red;
627 
628 				ptga += 3;
629 				pbits++;
630 			}
631 			break;
632 		}
633 
634 		case B_GRAY8:
635 			// NOTE: this code assumes that the
636 			// destination TGA color space is either
637 			// 8 bit indexed color or 8 bit grayscale
638 			bytescopied = width;
639 			memcpy(ptga, pbits, bytescopied);
640 			break;
641 
642 		default:
643 			bytescopied = B_ERROR;
644 			break;
645 	} // switch (fromspace)
646 
647 	return bytescopied;
648 }
649 
650 // create a TGA RLE packet for pixel and copy the
651 // packet header and pixel data to ptga
652 status_t
653 copy_rle_packet(uint8 *ptga, uint32 pixel, uint8 count,
654 	color_space fromspace, const color_map *pmap,
655 	int32 bitsBytesPerPixel)
656 {
657 	// copy packet header
658 	// (made of type and count)
659 	uint8 packethead = (count - 1) | 0x80;
660 	ptga[0] = packethead;
661 	ptga++;
662 
663 	return pix_bits_to_tga(reinterpret_cast<uint8 *> (&pixel),
664 		ptga, fromspace, 1, pmap, bitsBytesPerPixel) + 1;
665 }
666 
667 // create a TGA raw packet for pixel and copy the
668 // packet header and pixel data to ptga
669 status_t
670 copy_raw_packet(uint8 *ptga, uint8 *praw, uint8 count,
671 	color_space fromspace, const color_map *pmap,
672 	int32 bitsBytesPerPixel)
673 {
674 	// copy packet header
675 	// (made of type and count)
676 	uint8 packethead = count - 1;
677 	ptga[0] = packethead;
678 	ptga++;
679 
680 	return pix_bits_to_tga(praw, ptga, fromspace,
681 		count, pmap, bitsBytesPerPixel) + 1;
682 }
683 
684 // convert a row of pixel data from pbits to a
685 // row of pixel data in the TGA format using
686 // Run Length Encoding
687 status_t
688 pix_bits_to_tgarle(uint8 *pbits, uint8 *ptga, color_space fromspace,
689 	uint16 width, const color_map *pmap, int32 bitsBytesPerPixel)
690 {
691 	if (width == 0)
692 		return B_ERROR;
693 
694 	uint32 current = 0, next = 0, aftnext = 0;
695 	uint16 nread = 0;
696 	status_t result, bytescopied = 0;
697 	uint8 *prawbuf, *praw;
698 	prawbuf = new(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(&current, pbits, bitsBytesPerPixel);
707 	pbits += bitsBytesPerPixel;
708 	if (width == 1) {
709 		result = copy_raw_packet(ptga,
710 			reinterpret_cast<uint8 *> (&current), 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, &current, bitsBytesPerPixel);
754 				praw += bitsBytesPerPixel;
755 			}
756 
757 			if (nread == width) {
758 				// if in the last iteration of the loop,
759 				// "next" will be the last pixel in the row,
760 				// and will need to be written out for this
761 				// special case
762 
763 				if (rawcount == 128) {
764 					result = copy_raw_packet(ptga, prawbuf, rawcount,
765 						fromspace, pmap, bitsBytesPerPixel);
766 
767 					ptga += result;
768 					bytescopied += result;
769 					praw = prawbuf;
770 					rawcount = 0;
771 				}
772 
773 				rawcount++;
774 				memcpy(praw, &next, bitsBytesPerPixel);
775 				praw += bitsBytesPerPixel;
776 			}
777 
778 			if ((!bJustWroteRLE && next == aftnext) ||
779 				nread == width || rawcount == 128) {
780 				result = copy_raw_packet(ptga, prawbuf, rawcount,
781 					fromspace, pmap, bitsBytesPerPixel);
782 
783 				ptga += result;
784 				bytescopied += result;
785 				praw = prawbuf;
786 				rawcount = 0;
787 			}
788 
789 			bJustWroteRLE = false;
790 		}
791 
792 		current = next;
793 		next = aftnext;
794 	}
795 
796 	delete[] prawbuf;
797 	prawbuf = NULL;
798 
799 	return bytescopied;
800 }
801 
802 // ---------------------------------------------------------------
803 // translate_from_bits_to_tgatc
804 //
805 // Converts various varieties of the Be Bitmap format ('bits') to
806 // the TGA True Color format (RLE or uncompressed)
807 //
808 // Preconditions:
809 //
810 // Parameters:	inSource,	contains the bits data to convert
811 //
812 //				outDestination,	where the TGA data will be written
813 //
814 //				fromspace,	the format of the data in inSource
815 //
816 //				imagespec,	info about width / height / etc. of
817 //							the image
818 //
819 //				brle,	output using RLE if true, uncompressed
820 //						if false
821 //
822 //
823 // Postconditions:
824 //
825 // Returns: B_ERROR,	if memory couldn't be allocated or another
826 //						error occured
827 //
828 // B_OK,	if no errors occurred
829 // ---------------------------------------------------------------
830 status_t
831 translate_from_bits_to_tgatc(BPositionIO *inSource,
832 	BPositionIO *outDestination, color_space fromspace,
833 	TGAImageSpec &imagespec, bool brle)
834 {
835 	int32 bitsBytesPerPixel = 0;
836 	switch (fromspace) {
837 		case B_RGB32:
838 		case B_RGB32_BIG:
839 		case B_RGBA32:
840 		case B_RGBA32_BIG:
841 		case B_CMY32:
842 		case B_CMYA32:
843 		case B_CMYK32:
844 			bitsBytesPerPixel = 4;
845 			break;
846 
847 		case B_RGB24:
848 		case B_RGB24_BIG:
849 		case B_CMY24:
850 			bitsBytesPerPixel = 3;
851 			break;
852 
853 		case B_RGB16:
854 		case B_RGB16_BIG:
855 		case B_RGBA15:
856 		case B_RGBA15_BIG:
857 		case B_RGB15:
858 		case B_RGB15_BIG:
859 			bitsBytesPerPixel = 2;
860 			break;
861 
862 		case B_CMAP8:
863 		case B_GRAY8:
864 			bitsBytesPerPixel = 1;
865 			break;
866 
867 		default:
868 			return B_ERROR;
869 	}
870 	int32 bitsRowBytes = imagespec.width * bitsBytesPerPixel;
871 	uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
872 		((imagespec.depth % 8) ? 1 : 0);
873 	int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel) +
874 		(imagespec.width / 2);
875 	uint32 tgapixrow = 0;
876 	uint8 *tgaRowData = new(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 // ---------------------------------------------------------------
960 status_t
961 translate_from_bits1_to_tgabw(BPositionIO *inSource,
962 	BPositionIO *outDestination, int32 bitsRowBytes,
963 	TGAImageSpec &imagespec, bool brle)
964 {
965 	uint8 tgaBytesPerPixel = 1;
966 	int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel) +
967 		(imagespec.width / 2);
968 	uint32 tgapixrow = 0;
969 	uint8 *tgaRowData = new(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 // ---------------------------------------------------------------
1067 status_t
1068 write_tga_headers(BPositionIO *outDestination, TGAFileHeader &fileheader,
1069 	TGAColorMapSpec &mapspec, TGAImageSpec &imagespec)
1070 {
1071 	uint8 tgaheaders[TGA_HEADERS_SIZE];
1072 
1073 	// Convert host format headers to Little Endian (Intel) byte order
1074 	TGAFileHeader outFileheader;
1075 	outFileheader.idlength = fileheader.idlength;
1076 	outFileheader.colormaptype = fileheader.colormaptype;
1077 	outFileheader.imagetype = fileheader.imagetype;
1078 
1079 	TGAColorMapSpec outMapspec;
1080 	outMapspec.firstentry = B_HOST_TO_LENDIAN_INT16(mapspec.firstentry);
1081 	outMapspec.length = B_HOST_TO_LENDIAN_INT16(mapspec.length);
1082 	outMapspec.entrysize = mapspec.entrysize;
1083 
1084 	TGAImageSpec outImagespec;
1085 	outImagespec.xorigin = B_HOST_TO_LENDIAN_INT16(imagespec.xorigin);
1086 	outImagespec.yorigin = B_HOST_TO_LENDIAN_INT16(imagespec.yorigin);
1087 	outImagespec.width = B_HOST_TO_LENDIAN_INT16(imagespec.width);
1088 	outImagespec.height = B_HOST_TO_LENDIAN_INT16(imagespec.height);
1089 	outImagespec.depth = imagespec.depth;
1090 	outImagespec.descriptor = imagespec.descriptor;
1091 
1092 	// Copy TGA headers to buffer to be written out
1093 	// all at once
1094 	tgaheaders[0] = outFileheader.idlength;
1095 	tgaheaders[1] = outFileheader.colormaptype;
1096 	tgaheaders[2] = outFileheader.imagetype;
1097 
1098 	memcpy(tgaheaders + 3, &outMapspec.firstentry, 2);
1099 	memcpy(tgaheaders + 5, &outMapspec.length, 2);
1100 	tgaheaders[7] = outMapspec.entrysize;
1101 
1102 	memcpy(tgaheaders + 8, &outImagespec.xorigin, 2);
1103 	memcpy(tgaheaders + 10, &outImagespec.yorigin, 2);
1104 	memcpy(tgaheaders + 12, &outImagespec.width, 2);
1105 	memcpy(tgaheaders + 14, &outImagespec.height, 2);
1106 	tgaheaders[16] = outImagespec.depth;
1107 	tgaheaders[17] = outImagespec.descriptor;
1108 
1109 	ssize_t written;
1110 	written = outDestination->Write(tgaheaders, TGA_HEADERS_SIZE);
1111 
1112 	if (written == TGA_HEADERS_SIZE)
1113 		return B_OK;
1114 	else
1115 		return B_ERROR;
1116 }
1117 
1118 // ---------------------------------------------------------------
1119 // write_tga_footer
1120 //
1121 // Writes the TGA footer.  This information is contant in this
1122 // code because this translator does not output the developer
1123 // information section of the TGA format.
1124 //
1125 // Preconditions:
1126 //
1127 // Parameters:	outDestination,	where the headers are written to
1128 //
1129 //
1130 // Postconditions:
1131 //
1132 // Returns: B_ERROR, if something went wrong
1133 //
1134 // B_OK, if there were no problems writing out the headers
1135 // ---------------------------------------------------------------
1136 status_t
1137 write_tga_footer(BPositionIO *outDestination)
1138 {
1139 	const int32 kfootersize = 26;
1140 	uint8 footer[kfootersize];
1141 
1142 	memset(footer, 0, 8);
1143 		// set the Extension Area Offset and Developer
1144 		// Area Offset to zero (as they are not present)
1145 
1146 	memcpy(footer + 8, "TRUEVISION-XFILE.", 18);
1147 		// copy the string including the '.' and the '\0'
1148 
1149 	ssize_t written;
1150 	written = outDestination->Write(footer, kfootersize);
1151 	if (written == kfootersize)
1152 		return B_OK;
1153 	else
1154 		return B_ERROR;
1155 }
1156 
1157 // ---------------------------------------------------------------
1158 // translate_from_bits
1159 //
1160 // Convert the data in inSource from the Be Bitmap format ('bits')
1161 // to the format specified in outType (either bits or TGA).
1162 //
1163 // Preconditions:
1164 //
1165 // Parameters:	inSource,	the bits data to translate
1166 //
1167 // 				amtread,	the amount of data already read from
1168 //							inSource
1169 //
1170 //				read,		pointer to the data already read from
1171 //							inSource
1172 //
1173 //
1174 //				outType,	the type of data to convert to
1175 //
1176 //				outDestination,	where the output is written to
1177 //
1178 // Postconditions:
1179 //
1180 // Returns: B_NO_TRANSLATOR,	if the data is not in a supported
1181 //								format
1182 //
1183 // B_ERROR, if there was an error allocating memory or some other
1184 //			error
1185 //
1186 // B_OK, if successfully translated the data from the bits format
1187 // ---------------------------------------------------------------
1188 status_t
1189 TGATranslator::translate_from_bits(BPositionIO *inSource, uint32 outType,
1190 	BPositionIO *outDestination)
1191 {
1192 	TranslatorBitmap bitsHeader;
1193 	bool bheaderonly = false, bdataonly = false, brle;
1194 	brle = fSettings->SetGetBool(TGA_SETTING_RLE);
1195 
1196 	status_t result;
1197 	result = identify_bits_header(inSource, NULL, &bitsHeader);
1198 	if (result != B_OK)
1199 		return result;
1200 
1201 	// Translate B_TRANSLATOR_BITMAP to B_TGA_FORMAT
1202 	if (outType == B_TGA_FORMAT) {
1203 		// Set up TGA header
1204 		TGAFileHeader fileheader;
1205 		fileheader.idlength = 0;
1206 		fileheader.colormaptype = TGA_NO_COLORMAP;
1207 		fileheader.imagetype = 0;
1208 
1209 		TGAColorMapSpec mapspec;
1210 		mapspec.firstentry = 0;
1211 		mapspec.length = 0;
1212 		mapspec.entrysize = 0;
1213 
1214 		TGAImageSpec imagespec;
1215 		imagespec.xorigin = 0;
1216 		imagespec.yorigin = 0;
1217 		imagespec.width = static_cast<uint16> (bitsHeader.bounds.Width() + 1);
1218 		imagespec.height = static_cast<uint16> (bitsHeader.bounds.Height() + 1);
1219 		imagespec.depth = 0;
1220 		imagespec.descriptor = TGA_ORIGIN_VERT_BIT;
1221 
1222 		// determine fileSize / imagesize
1223 		switch (bitsHeader.colors) {
1224 
1225 			// Output to 32-bit True Color TGA (8 bits alpha)
1226 			case B_RGBA32:
1227 			case B_RGBA32_BIG:
1228 			case B_CMYA32:
1229 				if (brle)
1230 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1231 				else
1232 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1233 				imagespec.depth = 32;
1234 				imagespec.descriptor |= 8;
1235 					// 8 bits of alpha
1236 				break;
1237 
1238 			// Output to 24-bit True Color TGA (no alpha)
1239 			case B_RGB32:
1240 			case B_RGB32_BIG:
1241 			case B_RGB24:
1242 			case B_RGB24_BIG:
1243 			case B_CMYK32:
1244 			case B_CMY32:
1245 			case B_CMY24:
1246 				if (brle)
1247 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1248 				else
1249 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1250 				imagespec.depth = 24;
1251 				break;
1252 
1253 			// Output to 16-bit True Color TGA (no alpha)
1254 			// (TGA doesn't see 16 bit images as Be does
1255 			// so converting 16 bit Be Image to 16-bit TGA
1256 			// image would result in loss of quality)
1257 			case B_RGB16:
1258 			case B_RGB16_BIG:
1259 				if (brle)
1260 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1261 				else
1262 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1263 				imagespec.depth = 24;
1264 				break;
1265 
1266 			// Output to 15-bit True Color TGA (1 bit alpha)
1267 			case B_RGB15:
1268 			case B_RGB15_BIG:
1269 				if (brle)
1270 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1271 				else
1272 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1273 				imagespec.depth = 16;
1274 				imagespec.descriptor |= 1;
1275 					// 1 bit of alpha (always opaque)
1276 				break;
1277 
1278 			// Output to 16-bit True Color TGA (1 bit alpha)
1279 			case B_RGBA15:
1280 			case B_RGBA15_BIG:
1281 				if (brle)
1282 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1283 				else
1284 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1285 				imagespec.depth = 16;
1286 				imagespec.descriptor |= 1;
1287 					// 1 bit of alpha
1288 				break;
1289 
1290 			// Output to 8-bit Color Mapped TGA 32 bits per color map entry
1291 			case B_CMAP8:
1292 				fileheader.colormaptype = TGA_COLORMAP;
1293 				if (brle)
1294 					fileheader.imagetype = TGA_RLE_COLORMAP;
1295 				else
1296 					fileheader.imagetype = TGA_NOCOMP_COLORMAP;
1297 				mapspec.firstentry = 0;
1298 				mapspec.length = 256;
1299 				mapspec.entrysize = 32;
1300 				imagespec.depth = 8;
1301 				imagespec.descriptor |= 8;
1302 					// the pixel values contain 8 bits of attribute data
1303 				break;
1304 
1305 			// Output to 8-bit Black and White TGA
1306 			case B_GRAY8:
1307 			case B_GRAY1:
1308 				if (brle)
1309 					fileheader.imagetype = TGA_RLE_BW;
1310 				else
1311 					fileheader.imagetype = TGA_NOCOMP_BW;
1312 				imagespec.depth = 8;
1313 				break;
1314 
1315 			default:
1316 				return B_NO_TRANSLATOR;
1317 		}
1318 
1319 		// write out the TGA headers
1320 		if (bheaderonly || (!bheaderonly && !bdataonly)) {
1321 			result = write_tga_headers(outDestination, fileheader,
1322 				mapspec, imagespec);
1323 			if (result != B_OK)
1324 				return result;
1325 		}
1326 		if (bheaderonly)
1327 			// if user only wants the header, bail out
1328 			// before the data is written
1329 			return result;
1330 
1331 		// write out the TGA pixel data
1332 		switch (bitsHeader.colors) {
1333 			case B_RGB32:
1334 			case B_RGB32_BIG:
1335 			case B_RGBA32:
1336 			case B_RGBA32_BIG:
1337 			case B_RGB24:
1338 			case B_RGB24_BIG:
1339 			case B_RGB16:
1340 			case B_RGB16_BIG:
1341 			case B_RGB15:
1342 			case B_RGB15_BIG:
1343 			case B_RGBA15:
1344 			case B_RGBA15_BIG:
1345 			case B_CMYK32:
1346 			case B_CMY32:
1347 			case B_CMYA32:
1348 			case B_CMY24:
1349 				result = translate_from_bits_to_tgatc(inSource, outDestination,
1350 					bitsHeader.colors, imagespec, brle);
1351 				break;
1352 
1353 			case B_CMAP8:
1354 			{
1355 				// write Be's system palette to the TGA file
1356 				uint8 pal[1024];
1357 				const color_map *pmap = system_colors();
1358 				if (!pmap)
1359 					return B_ERROR;
1360 				for (int32 i = 0; i < 256; i++) {
1361 					uint8 *palent = pal + (i * 4);
1362 					rgb_color c = pmap->color_list[i];
1363 					palent[0] = c.blue;
1364 					palent[1] = c.green;
1365 					palent[2] = c.red;
1366 					palent[3] = c.alpha;
1367 				}
1368 				if (outDestination->Write(pal, 1024) != 1024)
1369 					return B_ERROR;
1370 
1371 				result = translate_from_bits_to_tgatc(inSource, outDestination,
1372 					B_GRAY8, imagespec, brle);
1373 				break;
1374 			}
1375 
1376 			case B_GRAY8:
1377 				result = translate_from_bits_to_tgatc(inSource, outDestination,
1378 					B_GRAY8, imagespec, brle);
1379 				break;
1380 
1381 			case B_GRAY1:
1382 				result = translate_from_bits1_to_tgabw(inSource, outDestination,
1383 					bitsHeader.rowBytes, imagespec, brle);
1384 				break;
1385 
1386 			default:
1387 				result = B_NO_TRANSLATOR;
1388 				break;
1389 		}
1390 
1391 		if (result == B_OK)
1392 			result = write_tga_footer(outDestination);
1393 
1394 		return result;
1395 
1396 	} else
1397 		return B_NO_TRANSLATOR;
1398 }
1399 
1400 // convert a row of uncompressed, non-color mapped
1401 // TGA pixels from ptga to pbits
1402 status_t
1403 pix_tganm_to_bits(uint8 *pbits, uint8 *ptga,
1404 	uint16 width, uint8 depth, uint8 tgaBytesPerPixel,
1405 	uint8 nalpha)
1406 {
1407 	status_t result = B_OK;
1408 
1409 	switch (depth) {
1410 		case 32:
1411 			if (nalpha == 8 && tgaBytesPerPixel == 4)
1412 				memcpy(pbits, ptga, 4 * width);
1413 			else if (nalpha == 8) {
1414 				// copy the same 32-bit pixel over and over
1415 				while (width--) {
1416 					memcpy(pbits, ptga, 4);
1417 					pbits += 4;
1418 				}
1419 			} else {
1420 				while (width--) {
1421 					memcpy(pbits, ptga, 3);
1422 
1423 					pbits += 4;
1424 					ptga += tgaBytesPerPixel;
1425 				}
1426 			}
1427 			break;
1428 
1429 		case 24:
1430 			while (width--) {
1431 				memcpy(pbits, ptga, 3);
1432 
1433 				pbits += 4;
1434 				ptga += tgaBytesPerPixel;
1435 			}
1436 			break;
1437 
1438 		case 16:
1439 		{
1440 			uint16 val;
1441 			if (nalpha == 1) {
1442 				while (width--) {
1443 					val = ptga[0] + (ptga[1] << 8);
1444 					pbits[0] =
1445 						((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1446 					pbits[1] =
1447 						((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1448 					pbits[2] =
1449 						((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1450 					pbits[3] = (val & 0x8000) ? 255 : 0;
1451 
1452 					pbits += 4;
1453 					ptga += tgaBytesPerPixel;
1454 				}
1455 			} else {
1456 				while (width--) {
1457 					val = ptga[0] + (ptga[1] << 8);
1458 					pbits[0] =
1459 						((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1460 					pbits[1] =
1461 						((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1462 					pbits[2] =
1463 						((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1464 
1465 					pbits += 4;
1466 					ptga += tgaBytesPerPixel;
1467 				}
1468 			}
1469 			break;
1470 		}
1471 
1472 		case 15:
1473 		{
1474 			uint16 val;
1475 			while (width--) {
1476 				val = ptga[0] + (ptga[1] << 8);
1477 				pbits[0] =
1478 					((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1479 				pbits[1] =
1480 					((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1481 				pbits[2] =
1482 					((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1483 
1484 				pbits += 4;
1485 				ptga += tgaBytesPerPixel;
1486 			}
1487 			break;
1488 		}
1489 
1490 		case 8:
1491 			while (width--) {
1492 				memset(pbits, ptga[0], 3);
1493 
1494 				pbits += 4;
1495 				ptga += tgaBytesPerPixel;
1496 			}
1497 			break;
1498 
1499 		default:
1500 			result = B_ERROR;
1501 			break;
1502 	}
1503 
1504 	return result;
1505 }
1506 
1507 // ---------------------------------------------------------------
1508 // translate_from_tganm_to_bits
1509 //
1510 // Translates a uncompressed, non-palette TGA from inSource
1511 // to the B_RGB32 or B_RGBA32 bits format.
1512 //
1513 // Preconditions:
1514 //
1515 // Parameters: inSource,	the TGA data to be translated
1516 //
1517 // outDestination,	where the bits data will be written to
1518 //
1519 // filehead, image type info
1520 //
1521 // mapspec, color map info
1522 //
1523 // imagespec, width / height info
1524 //
1525 //
1526 //
1527 // Postconditions:
1528 //
1529 // Returns: B_ERROR, if there is an error allocating memory
1530 //
1531 // B_OK, if all went well
1532 // ---------------------------------------------------------------
1533 status_t
1534 TGATranslator::translate_from_tganm_to_bits(BPositionIO *inSource,
1535 	BPositionIO *outDestination, TGAFileHeader &filehead,
1536 	TGAColorMapSpec &mapspec, TGAImageSpec &imagespec)
1537 {
1538 	bool bvflip;
1539 	if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
1540 		bvflip = false;
1541 	else
1542 		bvflip = true;
1543 	uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec);
1544 	int32 bitsRowBytes = imagespec.width * 4;
1545 	uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
1546 		((imagespec.depth % 8) ? 1 : 0);
1547 	int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel);
1548 	uint32 tgapixrow = 0;
1549 
1550 	// Setup outDestination so that it can be written to
1551 	// from the end of the file to the beginning instead of
1552 	// the other way around
1553 	off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
1554 		sizeof(TranslatorBitmap);
1555 	if (outDestination->SetSize(bitsFileSize) != B_OK)
1556 		// This call should work for BFile and BMallocIO objects,
1557 		// but may not work for other BPositionIO based types
1558 		return B_ERROR;
1559 	off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
1560 	if (bvflip)
1561 		outDestination->Seek(bitsoffset, SEEK_CUR);
1562 
1563 	// allocate row buffers
1564 	uint8 *tgaRowData = new(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 // ---------------------------------------------------------------
1629 status_t
1630 TGATranslator::translate_from_tganmrle_to_bits(BPositionIO *inSource,
1631 	BPositionIO *outDestination, TGAFileHeader &filehead,
1632 	TGAColorMapSpec &mapspec, TGAImageSpec &imagespec)
1633 {
1634 	status_t result = B_OK;
1635 
1636 	bool bvflip;
1637 	if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
1638 		bvflip = false;
1639 	else
1640 		bvflip = true;
1641 	uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec);
1642 	int32 bitsRowBytes = imagespec.width * 4;
1643 	uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
1644 		((imagespec.depth % 8) ? 1 : 0);
1645 	uint16 tgapixrow = 0, tgapixcol = 0;
1646 
1647 	// Setup outDestination so that it can be written to
1648 	// from the end of the file to the beginning instead of
1649 	// the other way around
1650 	off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
1651 		sizeof(TranslatorBitmap);
1652 	if (outDestination->SetSize(bitsFileSize) != B_OK)
1653 		// This call should work for BFile and BMallocIO objects,
1654 		// but may not work for other BPositionIO based types
1655 		return B_ERROR;
1656 	off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
1657 	if (bvflip)
1658 		outDestination->Seek(bitsoffset, SEEK_CUR);
1659 
1660 	// allocate row buffers
1661 	uint8 *bitsRowData = new(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
1737 status_t
1738 pix_tgam_to_bits(uint8 *pbits, uint8 *ptgaindices,
1739 	uint16 width, uint8 depth, uint8 *pmap)
1740 {
1741 	status_t result = B_OK;
1742 	uint8 *ptgapixel = NULL;
1743 
1744 	switch (depth) {
1745 		case 32:
1746 			for (uint16 i = 0; i < width; i++) {
1747 				ptgapixel = pmap +
1748 					(ptgaindices[i] * 4);
1749 
1750 				memcpy(pbits, ptgapixel, 4);
1751 
1752 				pbits += 4;
1753 			}
1754 			break;
1755 
1756 		case 24:
1757 			for (uint16 i = 0; i < width; i++) {
1758 				ptgapixel = pmap +
1759 					(ptgaindices[i] * 3);
1760 
1761 				memcpy(pbits, ptgapixel, 3);
1762 
1763 				pbits += 4;
1764 			}
1765 			break;
1766 
1767 		case 16:
1768 			for (uint16 i = 0; i < width; i++) {
1769 				uint16 val;
1770 
1771 				ptgapixel = pmap +
1772 					(ptgaindices[i] * 2);
1773 				val = ptgapixel[0] + (ptgapixel[1] << 8);
1774 				pbits[0] =
1775 					((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1776 				pbits[1] =
1777 					((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1778 				pbits[2] =
1779 					((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1780 				pbits[3] = (val & 0x8000) ? 255 : 0;
1781 
1782 				pbits += 4;
1783 			}
1784 			break;
1785 
1786 		case 15:
1787 			for (uint16 i = 0; i < width; i++) {
1788 				uint16 val;
1789 
1790 				ptgapixel = pmap +
1791 					(ptgaindices[i] * 2);
1792 				val = ptgapixel[0] + (ptgapixel[1] << 8);
1793 				pbits[0] =
1794 					((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1795 				pbits[1] =
1796 					((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1797 				pbits[2] =
1798 					((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1799 
1800 				pbits += 4;
1801 			}
1802 			break;
1803 
1804 		default:
1805 			result = B_ERROR;
1806 			break;
1807 	}
1808 
1809 	return result;
1810 }
1811 
1812 // ---------------------------------------------------------------
1813 // translate_from_tgam_to_bits
1814 //
1815 // Translates a paletted TGA from inSource to the bits format.
1816 //
1817 // Preconditions:
1818 //
1819 // Parameters: inSource,	the TGA data to be translated
1820 //
1821 // outDestination,	where the bits data will be written to
1822 //
1823 // mapspec, info about the color map (palette)
1824 //
1825 // imagespec, width / height info
1826 //
1827 // pmap, color palette
1828 //
1829 //
1830 // Postconditions:
1831 //
1832 // Returns: B_ERROR, if there is an error allocating memory
1833 //
1834 // B_OK, if all went well
1835 // ---------------------------------------------------------------
1836 status_t
1837 translate_from_tgam_to_bits(BPositionIO *inSource,
1838 	BPositionIO *outDestination, TGAColorMapSpec &mapspec,
1839 	TGAImageSpec &imagespec, uint8 *pmap)
1840 {
1841 	bool bvflip;
1842 	if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
1843 		bvflip = false;
1844 	else
1845 		bvflip = true;
1846 
1847 	int32 bitsRowBytes = imagespec.width * 4;
1848 	uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
1849 		((imagespec.depth % 8) ? 1 : 0);
1850 	int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel);
1851 	uint32 tgapixrow = 0;
1852 
1853 	// Setup outDestination so that it can be written to
1854 	// from the end of the file to the beginning instead of
1855 	// the other way around
1856 	off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
1857 		sizeof(TranslatorBitmap);
1858 	if (outDestination->SetSize(bitsFileSize) != B_OK)
1859 		// This call should work for BFile and BMallocIO objects,
1860 		// but may not work for other BPositionIO based types
1861 		return B_ERROR;
1862 	off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
1863 	if (bvflip)
1864 		outDestination->Seek(bitsoffset, SEEK_CUR);
1865 
1866 	// allocate row buffers
1867 	uint8 *tgaRowData = new(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 // ---------------------------------------------------------------
1932 status_t
1933 TGATranslator::translate_from_tgamrle_to_bits(BPositionIO *inSource,
1934 	BPositionIO *outDestination, TGAFileHeader &filehead,
1935 	TGAColorMapSpec &mapspec, TGAImageSpec &imagespec, uint8 *pmap)
1936 {
1937 	status_t result = B_OK;
1938 
1939 	bool bvflip;
1940 	if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
1941 		bvflip = false;
1942 	else
1943 		bvflip = true;
1944 	uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec);
1945 	int32 bitsRowBytes = imagespec.width * 4;
1946 	uint8 tgaPalBytesPerPixel = (mapspec.entrysize / 8) +
1947 		((mapspec.entrysize % 8) ? 1 : 0);
1948 	uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
1949 		((imagespec.depth % 8) ? 1 : 0);
1950 	uint16 tgapixrow = 0, tgapixcol = 0;
1951 
1952 	// Setup outDestination so that it can be written to
1953 	// from the end of the file to the beginning instead of
1954 	// the other way around
1955 	off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
1956 		sizeof(TranslatorBitmap);
1957 	if (outDestination->SetSize(bitsFileSize) != B_OK)
1958 		// This call should work for BFile and BMallocIO objects,
1959 		// but may not work for other BPositionIO based types
1960 		return B_ERROR;
1961 	off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
1962 	if (bvflip)
1963 		outDestination->Seek(bitsoffset, SEEK_CUR);
1964 
1965 	// allocate row buffers
1966 	uint8 *bitsRowData = new(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 // ---------------------------------------------------------------
2072 status_t
2073 TGATranslator::translate_from_tga(BPositionIO *inSource, uint32 outType,
2074 	BPositionIO *outDestination)
2075 {
2076 	TGAFileHeader fileheader;
2077 	TGAColorMapSpec mapspec;
2078 	TGAImageSpec imagespec;
2079 	bool bheaderonly = false, bdataonly = false;
2080 
2081 	status_t result;
2082 	result = identify_tga_header(inSource, NULL, &fileheader, &mapspec,
2083 		&imagespec);
2084 	if (result != B_OK)
2085 		return result;
2086 
2087 	// if the user wants to translate a TGA to a TGA, easy enough :)
2088 	if (outType == B_TGA_FORMAT) {
2089 		// write out the TGA headers
2090 		if (bheaderonly || (!bheaderonly && !bdataonly)) {
2091 			result = write_tga_headers(outDestination, fileheader,
2092 				mapspec, imagespec);
2093 			if (result != B_OK)
2094 				return result;
2095 		}
2096 		if (bheaderonly)
2097 			// if the user only wants the header,
2098 			// bail before it is written
2099 			return result;
2100 
2101 		const int32 kbuflen = 1024;
2102 		uint8 buf[kbuflen];
2103 		ssize_t rd = inSource->Read(buf, kbuflen);
2104 		while (rd > 0) {
2105 			outDestination->Write(buf, rd);
2106 			rd = inSource->Read(buf, kbuflen);
2107 		}
2108 		if (rd == 0)
2109 			return B_OK;
2110 		else
2111 			return B_ERROR;
2112 
2113 	// if translating a TGA to a Be Bitmap
2114 	} else if (outType == B_TRANSLATOR_BITMAP) {
2115 		TranslatorBitmap bitsHeader;
2116 		bitsHeader.magic = B_TRANSLATOR_BITMAP;
2117 		bitsHeader.bounds.left = 0;
2118 		bitsHeader.bounds.top = 0;
2119 		bitsHeader.bounds.right = imagespec.width - 1;
2120 		bitsHeader.bounds.bottom = imagespec.height - 1;
2121 
2122 		// skip over Image ID data (if present)
2123 		if (fileheader.idlength > 0)
2124 			inSource->Seek(fileheader.idlength, SEEK_CUR);
2125 
2126 		// read in palette and/or skip non-TGA data
2127 		uint8 *ptgapalette = NULL;
2128 		if (fileheader.colormaptype == TGA_COLORMAP) {
2129 			uint32 nentrybytes;
2130 			nentrybytes = mapspec.entrysize / 8;
2131 			if (mapspec.entrysize % 8)
2132 				nentrybytes++;
2133 			ptgapalette = new(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 
2197 status_t
2198 TGATranslator::DerivedTranslate(BPositionIO *inSource,
2199 	const translator_info *inInfo, BMessage *ioExtension, uint32 outType,
2200 	BPositionIO *outDestination, int32 baseType)
2201 {
2202 	if (baseType == 1)
2203 		// if inSource is in bits format
2204 		return translate_from_bits(inSource, outType, outDestination);
2205 	else if (baseType == 0)
2206 		// if inSource is NOT in bits format
2207 		return translate_from_tga(inSource, outType, outDestination);
2208 	else
2209 		// if BaseTranslator did not properly identify the data as
2210 		// bits or not bits
2211 		return B_NO_TRANSLATOR;
2212 }
2213 
2214 BView *
2215 TGATranslator::NewConfigView(TranslatorSettings *settings)
2216 {
2217 	return new(std::nothrow) TGAView(B_TRANSLATE("TGATranslator Settings"),
2218 		B_WILL_DRAW, settings);
2219 }
2220 
2221