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