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