xref: /haiku/src/add-ons/translators/tga/TGATranslator.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
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  Haiku, Inc.
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 			return B_ERROR;
880 	}
881 	while (rd == bitsRowBytes) {
882 		status_t bytescopied;
883 		bytescopied = convert_to_tga(bitsRowData, tgaRowData, fromspace,
884 			imagespec.width, pmap, bitsBytesPerPixel);
885 
886 		outDestination->Write(tgaRowData, bytescopied);
887 		tgapixrow++;
888 		// if I've read all of the pixel data, break
889 		// out of the loop so I don't try to read
890 		// non-pixel data
891 		if (tgapixrow == imagespec.height)
892 			break;
893 
894 		rd = inSource->Read(bitsRowData, bitsRowBytes);
895 	} // while (rd == bitsRowBytes)
896 
897 	delete[] bitsRowData;
898 	bitsRowData = NULL;
899 	delete[] tgaRowData;
900 	tgaRowData = NULL;
901 
902 	return B_OK;
903 }
904 
905 // ---------------------------------------------------------------
906 // translate_from_bits1_to_tgabw
907 //
908 // Converts 1-bit Be Bitmaps ('bits') to the
909 // black and white (8-bit grayscale) TGA format
910 //
911 // Preconditions:
912 //
913 // Parameters:	inSource,	contains the bits data to convert
914 //
915 //				outDestination,	where the TGA data will be written
916 //
917 //				bitsRowBytes,	number of bytes in one row of
918 //								bits data
919 //
920 //				imagespec,	info about width / height / etc. of
921 //							the image
922 //
923 //				brle,	output using RLE if true, uncompressed
924 //						if false
925 //
926 //
927 // Postconditions:
928 //
929 // Returns: B_ERROR,	if memory couldn't be allocated or another
930 //						error occured
931 //
932 // B_OK,	if no errors occurred
933 // ---------------------------------------------------------------
934 status_t
935 translate_from_bits1_to_tgabw(BPositionIO *inSource,
936 	BPositionIO *outDestination, int32 bitsRowBytes,
937 	TGAImageSpec &imagespec, bool brle)
938 {
939 	uint8 tgaBytesPerPixel = 1;
940 	int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel) +
941 		(imagespec.width / 2);
942 	uint32 tgapixrow = 0;
943 	uint8 *tgaRowData = new uint8[tgaRowBytes];
944 	if (!tgaRowData)
945 		return B_ERROR;
946 
947 	uint8 *medRowData = new uint8[imagespec.width];
948 	if (!medRowData) {
949 		delete[] tgaRowData;
950 		tgaRowData = NULL;
951 		return B_ERROR;
952 	}
953 	uint8 *bitsRowData = new uint8[bitsRowBytes];
954 	if (!bitsRowData) {
955 		delete[] medRowData;
956 		medRowData = NULL;
957 		delete[] tgaRowData;
958 		tgaRowData = NULL;
959 		return B_ERROR;
960 	}
961 
962 	// conversion function pointer, points to either
963 	// RLE or normal TGA conversion function
964 	status_t (*convert_to_tga)(uint8 *pbits, uint8 *ptga,
965 		color_space fromspace, uint16 width, const color_map *pmap,
966 		int32 bitsBytesPerPixel);
967 
968 	if (brle)
969 		convert_to_tga = pix_bits_to_tgarle;
970 	else
971 		convert_to_tga = pix_bits_to_tga;
972 
973 	ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes);
974 	while (rd == bitsRowBytes) {
975 		uint32 tgapixcol = 0;
976 		for (int32 i = 0; (tgapixcol < imagespec.width) &&
977 			(i < bitsRowBytes); i++) {
978 			// process each byte in the row
979 			uint8 pixels = bitsRowData[i];
980 			for (uint8 compbit = 128; (tgapixcol < imagespec.width) &&
981 				compbit; compbit >>= 1) {
982 				// for each bit in the current byte, convert to a TGA palette
983 				// index and store that in the tgaRowData
984 				if (pixels & compbit)
985 					// black
986 					medRowData[tgapixcol] = 0;
987 				else
988 					// white
989 					medRowData[tgapixcol] = 255;
990 				tgapixcol++;
991 			}
992 		}
993 
994 		status_t bytescopied;
995 		bytescopied = convert_to_tga(medRowData, tgaRowData, B_GRAY8,
996 			imagespec.width, NULL, 1);
997 
998 		outDestination->Write(tgaRowData, bytescopied);
999 		tgapixrow++;
1000 		// if I've read all of the pixel data, break
1001 		// out of the loop so I don't try to read
1002 		// non-pixel data
1003 		if (tgapixrow == imagespec.height)
1004 			break;
1005 
1006 		rd = inSource->Read(bitsRowData, bitsRowBytes);
1007 	} // while (rd == bitsRowBytes)
1008 
1009 	delete[] bitsRowData;
1010 	bitsRowData = NULL;
1011 	delete[] medRowData;
1012 	medRowData = NULL;
1013 	delete[] tgaRowData;
1014 	tgaRowData = NULL;
1015 
1016 	return B_OK;
1017 }
1018 
1019 // ---------------------------------------------------------------
1020 // write_tga_headers
1021 //
1022 // Writes the TGA headers to outDestination.
1023 //
1024 // Preconditions:
1025 //
1026 // Parameters:	outDestination,	where the headers are written to
1027 //
1028 //				fileheader, TGA file header
1029 //
1030 //				mapspec,	color map information
1031 //
1032 //				imagespec,	width / height / etc. info
1033 //
1034 //
1035 // Postconditions:
1036 //
1037 // Returns: B_ERROR, if something went wrong
1038 //
1039 // B_OK, if there were no problems writing out the headers
1040 // ---------------------------------------------------------------
1041 status_t
1042 write_tga_headers(BPositionIO *outDestination, TGAFileHeader &fileheader,
1043 	TGAColorMapSpec &mapspec, TGAImageSpec &imagespec)
1044 {
1045 	uint8 tgaheaders[TGA_HEADERS_SIZE];
1046 
1047 	// Convert host format headers to Little Endian (Intel) byte order
1048 	TGAFileHeader outFileheader;
1049 	outFileheader.idlength = fileheader.idlength;
1050 	outFileheader.colormaptype = fileheader.colormaptype;
1051 	outFileheader.imagetype = fileheader.imagetype;
1052 
1053 	TGAColorMapSpec outMapspec;
1054 	outMapspec.firstentry = B_HOST_TO_LENDIAN_INT16(mapspec.firstentry);
1055 	outMapspec.length = B_HOST_TO_LENDIAN_INT16(mapspec.length);
1056 	outMapspec.entrysize = mapspec.entrysize;
1057 
1058 	TGAImageSpec outImagespec;
1059 	outImagespec.xorigin = B_HOST_TO_LENDIAN_INT16(imagespec.xorigin);
1060 	outImagespec.yorigin = B_HOST_TO_LENDIAN_INT16(imagespec.yorigin);
1061 	outImagespec.width = B_HOST_TO_LENDIAN_INT16(imagespec.width);
1062 	outImagespec.height = B_HOST_TO_LENDIAN_INT16(imagespec.height);
1063 	outImagespec.depth = imagespec.depth;
1064 	outImagespec.descriptor = imagespec.descriptor;
1065 
1066 	// Copy TGA headers to buffer to be written out
1067 	// all at once
1068 	tgaheaders[0] = outFileheader.idlength;
1069 	tgaheaders[1] = outFileheader.colormaptype;
1070 	tgaheaders[2] = outFileheader.imagetype;
1071 
1072 	memcpy(tgaheaders + 3, &outMapspec.firstentry, 2);
1073 	memcpy(tgaheaders + 5, &outMapspec.length, 2);
1074 	tgaheaders[7] = outMapspec.entrysize;
1075 
1076 	memcpy(tgaheaders + 8, &outImagespec.xorigin, 2);
1077 	memcpy(tgaheaders + 10, &outImagespec.yorigin, 2);
1078 	memcpy(tgaheaders + 12, &outImagespec.width, 2);
1079 	memcpy(tgaheaders + 14, &outImagespec.height, 2);
1080 	tgaheaders[16] = outImagespec.depth;
1081 	tgaheaders[17] = outImagespec.descriptor;
1082 
1083 	ssize_t written;
1084 	written = outDestination->Write(tgaheaders, TGA_HEADERS_SIZE);
1085 
1086 	if (written == TGA_HEADERS_SIZE)
1087 		return B_OK;
1088 	else
1089 		return B_ERROR;
1090 }
1091 
1092 // ---------------------------------------------------------------
1093 // write_tga_footer
1094 //
1095 // Writes the TGA footer.  This information is contant in this
1096 // code because this translator does not output the developer
1097 // information section of the TGA format.
1098 //
1099 // Preconditions:
1100 //
1101 // Parameters:	outDestination,	where the headers are written to
1102 //
1103 //
1104 // Postconditions:
1105 //
1106 // Returns: B_ERROR, if something went wrong
1107 //
1108 // B_OK, if there were no problems writing out the headers
1109 // ---------------------------------------------------------------
1110 status_t
1111 write_tga_footer(BPositionIO *outDestination)
1112 {
1113 	const int32 kfootersize = 26;
1114 	uint8 footer[kfootersize];
1115 
1116 	memset(footer, 0, 8);
1117 		// set the Extension Area Offset and Developer
1118 		// Area Offset to zero (as they are not present)
1119 
1120 	memcpy(footer + 8, "TRUEVISION-XFILE.", 18);
1121 		// copy the string including the '.' and the '\0'
1122 
1123 	ssize_t written;
1124 	written = outDestination->Write(footer, kfootersize);
1125 	if (written == kfootersize)
1126 		return B_OK;
1127 	else
1128 		return B_ERROR;
1129 }
1130 
1131 // ---------------------------------------------------------------
1132 // translate_from_bits
1133 //
1134 // Convert the data in inSource from the Be Bitmap format ('bits')
1135 // to the format specified in outType (either bits or TGA).
1136 //
1137 // Preconditions:
1138 //
1139 // Parameters:	inSource,	the bits data to translate
1140 //
1141 // 				amtread,	the amount of data already read from
1142 //							inSource
1143 //
1144 //				read,		pointer to the data already read from
1145 //							inSource
1146 //
1147 //
1148 //				outType,	the type of data to convert to
1149 //
1150 //				outDestination,	where the output is written to
1151 //
1152 // Postconditions:
1153 //
1154 // Returns: B_NO_TRANSLATOR,	if the data is not in a supported
1155 //								format
1156 //
1157 // B_ERROR, if there was an error allocating memory or some other
1158 //			error
1159 //
1160 // B_OK, if successfully translated the data from the bits format
1161 // ---------------------------------------------------------------
1162 status_t
1163 TGATranslator::translate_from_bits(BPositionIO *inSource, uint32 outType,
1164 	BPositionIO *outDestination)
1165 {
1166 	TranslatorBitmap bitsHeader;
1167 	bool bheaderonly = false, bdataonly = false, brle;
1168 	brle = fSettings->SetGetBool(TGA_SETTING_RLE);
1169 
1170 	status_t result;
1171 	result = identify_bits_header(inSource, NULL, &bitsHeader);
1172 	if (result != B_OK)
1173 		return result;
1174 
1175 	// Translate B_TRANSLATOR_BITMAP to B_TGA_FORMAT
1176 	if (outType == B_TGA_FORMAT) {
1177 		// Set up TGA header
1178 		TGAFileHeader fileheader;
1179 		fileheader.idlength = 0;
1180 		fileheader.colormaptype = TGA_NO_COLORMAP;
1181 		fileheader.imagetype = 0;
1182 
1183 		TGAColorMapSpec mapspec;
1184 		mapspec.firstentry = 0;
1185 		mapspec.length = 0;
1186 		mapspec.entrysize = 0;
1187 
1188 		TGAImageSpec imagespec;
1189 		imagespec.xorigin = 0;
1190 		imagespec.yorigin = 0;
1191 		imagespec.width = static_cast<uint16> (bitsHeader.bounds.Width() + 1);
1192 		imagespec.height = static_cast<uint16> (bitsHeader.bounds.Height() + 1);
1193 		imagespec.depth = 0;
1194 		imagespec.descriptor = TGA_ORIGIN_VERT_BIT;
1195 
1196 		// determine fileSize / imagesize
1197 		switch (bitsHeader.colors) {
1198 
1199 			// Output to 32-bit True Color TGA (8 bits alpha)
1200 			case B_RGBA32:
1201 			case B_RGBA32_BIG:
1202 			case B_CMYA32:
1203 				if (brle)
1204 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1205 				else
1206 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1207 				imagespec.depth = 32;
1208 				imagespec.descriptor |= 8;
1209 					// 8 bits of alpha
1210 				break;
1211 
1212 			// Output to 24-bit True Color TGA (no alpha)
1213 			case B_RGB32:
1214 			case B_RGB32_BIG:
1215 			case B_RGB24:
1216 			case B_RGB24_BIG:
1217 			case B_CMYK32:
1218 			case B_CMY32:
1219 			case B_CMY24:
1220 				if (brle)
1221 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1222 				else
1223 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1224 				imagespec.depth = 24;
1225 				break;
1226 
1227 			// Output to 16-bit True Color TGA (no alpha)
1228 			// (TGA doesn't see 16 bit images as Be does
1229 			// so converting 16 bit Be Image to 16-bit TGA
1230 			// image would result in loss of quality)
1231 			case B_RGB16:
1232 			case B_RGB16_BIG:
1233 				if (brle)
1234 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1235 				else
1236 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1237 				imagespec.depth = 24;
1238 				break;
1239 
1240 			// Output to 15-bit True Color TGA (1 bit alpha)
1241 			case B_RGB15:
1242 			case B_RGB15_BIG:
1243 				if (brle)
1244 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1245 				else
1246 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1247 				imagespec.depth = 16;
1248 				imagespec.descriptor |= 1;
1249 					// 1 bit of alpha (always opaque)
1250 				break;
1251 
1252 			// Output to 16-bit True Color TGA (1 bit alpha)
1253 			case B_RGBA15:
1254 			case B_RGBA15_BIG:
1255 				if (brle)
1256 					fileheader.imagetype = TGA_RLE_TRUECOLOR;
1257 				else
1258 					fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
1259 				imagespec.depth = 16;
1260 				imagespec.descriptor |= 1;
1261 					// 1 bit of alpha
1262 				break;
1263 
1264 			// Output to 8-bit Color Mapped TGA 32 bits per color map entry
1265 			case B_CMAP8:
1266 				fileheader.colormaptype = TGA_COLORMAP;
1267 				if (brle)
1268 					fileheader.imagetype = TGA_RLE_COLORMAP;
1269 				else
1270 					fileheader.imagetype = TGA_NOCOMP_COLORMAP;
1271 				mapspec.firstentry = 0;
1272 				mapspec.length = 256;
1273 				mapspec.entrysize = 32;
1274 				imagespec.depth = 8;
1275 				imagespec.descriptor |= 8;
1276 					// the pixel values contain 8 bits of attribute data
1277 				break;
1278 
1279 			// Output to 8-bit Black and White TGA
1280 			case B_GRAY8:
1281 			case B_GRAY1:
1282 				if (brle)
1283 					fileheader.imagetype = TGA_RLE_BW;
1284 				else
1285 					fileheader.imagetype = TGA_NOCOMP_BW;
1286 				imagespec.depth = 8;
1287 				break;
1288 
1289 			default:
1290 				return B_NO_TRANSLATOR;
1291 		}
1292 
1293 		// write out the TGA headers
1294 		if (bheaderonly || (!bheaderonly && !bdataonly)) {
1295 			result = write_tga_headers(outDestination, fileheader,
1296 				mapspec, imagespec);
1297 			if (result != B_OK)
1298 				return result;
1299 		}
1300 		if (bheaderonly)
1301 			// if user only wants the header, bail out
1302 			// before the data is written
1303 			return result;
1304 
1305 		// write out the TGA pixel data
1306 		switch (bitsHeader.colors) {
1307 			case B_RGB32:
1308 			case B_RGB32_BIG:
1309 			case B_RGBA32:
1310 			case B_RGBA32_BIG:
1311 			case B_RGB24:
1312 			case B_RGB24_BIG:
1313 			case B_RGB16:
1314 			case B_RGB16_BIG:
1315 			case B_RGB15:
1316 			case B_RGB15_BIG:
1317 			case B_RGBA15:
1318 			case B_RGBA15_BIG:
1319 			case B_CMYK32:
1320 			case B_CMY32:
1321 			case B_CMYA32:
1322 			case B_CMY24:
1323 				result = translate_from_bits_to_tgatc(inSource, outDestination,
1324 					bitsHeader.colors, imagespec, brle);
1325 				break;
1326 
1327 			case B_CMAP8:
1328 			{
1329 				// write Be's system palette to the TGA file
1330 				uint8 pal[1024];
1331 				const color_map *pmap = system_colors();
1332 				if (!pmap)
1333 					return B_ERROR;
1334 				for (int32 i = 0; i < 256; i++) {
1335 					uint8 *palent = pal + (i * 4);
1336 					rgb_color c = pmap->color_list[i];
1337 					palent[0] = c.blue;
1338 					palent[1] = c.green;
1339 					palent[2] = c.red;
1340 					palent[3] = c.alpha;
1341 				}
1342 				if (outDestination->Write(pal, 1024) != 1024)
1343 					return B_ERROR;
1344 
1345 				result = translate_from_bits_to_tgatc(inSource, outDestination,
1346 					B_GRAY8, imagespec, brle);
1347 				break;
1348 			}
1349 
1350 			case B_GRAY8:
1351 				result = translate_from_bits_to_tgatc(inSource, outDestination,
1352 					B_GRAY8, imagespec, brle);
1353 				break;
1354 
1355 			case B_GRAY1:
1356 				result = translate_from_bits1_to_tgabw(inSource, outDestination,
1357 					bitsHeader.rowBytes, imagespec, brle);
1358 				break;
1359 
1360 			default:
1361 				result = B_NO_TRANSLATOR;
1362 				break;
1363 		}
1364 
1365 		if (result == B_OK)
1366 			result = write_tga_footer(outDestination);
1367 
1368 		return result;
1369 
1370 	} else
1371 		return B_NO_TRANSLATOR;
1372 }
1373 
1374 // convert a row of uncompressed, non-color mapped
1375 // TGA pixels from ptga to pbits
1376 status_t
1377 pix_tganm_to_bits(uint8 *pbits, uint8 *ptga,
1378 	uint16 width, uint8 depth, uint8 tgaBytesPerPixel,
1379 	uint8 nalpha)
1380 {
1381 	status_t result = B_OK;
1382 
1383 	switch (depth) {
1384 		case 32:
1385 			if (nalpha == 8 && tgaBytesPerPixel == 4)
1386 				memcpy(pbits, ptga, 4 * width);
1387 			else if (nalpha == 8) {
1388 				// copy the same 32-bit pixel over and over
1389 				while (width--) {
1390 					memcpy(pbits, ptga, 4);
1391 					pbits += 4;
1392 				}
1393 			} else {
1394 				while (width--) {
1395 					memcpy(pbits, ptga, 3);
1396 
1397 					pbits += 4;
1398 					ptga += tgaBytesPerPixel;
1399 				}
1400 			}
1401 			break;
1402 
1403 		case 24:
1404 			while (width--) {
1405 				memcpy(pbits, ptga, 3);
1406 
1407 				pbits += 4;
1408 				ptga += tgaBytesPerPixel;
1409 			}
1410 			break;
1411 
1412 		case 16:
1413 		{
1414 			uint16 val;
1415 			if (nalpha == 1) {
1416 				while (width--) {
1417 					val = ptga[0] + (ptga[1] << 8);
1418 					pbits[0] =
1419 						((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1420 					pbits[1] =
1421 						((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1422 					pbits[2] =
1423 						((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1424 					pbits[3] = (val & 0x8000) ? 255 : 0;
1425 
1426 					pbits += 4;
1427 					ptga += tgaBytesPerPixel;
1428 				}
1429 			} else {
1430 				while (width--) {
1431 					val = ptga[0] + (ptga[1] << 8);
1432 					pbits[0] =
1433 						((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1434 					pbits[1] =
1435 						((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1436 					pbits[2] =
1437 						((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1438 
1439 					pbits += 4;
1440 					ptga += tgaBytesPerPixel;
1441 				}
1442 			}
1443 			break;
1444 		}
1445 
1446 		case 15:
1447 		{
1448 			uint16 val;
1449 			while (width--) {
1450 				val = ptga[0] + (ptga[1] << 8);
1451 				pbits[0] =
1452 					((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1453 				pbits[1] =
1454 					((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1455 				pbits[2] =
1456 					((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1457 
1458 				pbits += 4;
1459 				ptga += tgaBytesPerPixel;
1460 			}
1461 			break;
1462 		}
1463 
1464 		case 8:
1465 			while (width--) {
1466 				memset(pbits, ptga[0], 3);
1467 
1468 				pbits += 4;
1469 				ptga += tgaBytesPerPixel;
1470 			}
1471 			break;
1472 
1473 		default:
1474 			result = B_ERROR;
1475 			break;
1476 	}
1477 
1478 	return result;
1479 }
1480 
1481 // ---------------------------------------------------------------
1482 // translate_from_tganm_to_bits
1483 //
1484 // Translates a uncompressed, non-palette TGA from inSource
1485 // to the B_RGB32 or B_RGBA32 bits format.
1486 //
1487 // Preconditions:
1488 //
1489 // Parameters: inSource,	the TGA data to be translated
1490 //
1491 // outDestination,	where the bits data will be written to
1492 //
1493 // filehead, image type info
1494 //
1495 // mapspec, color map info
1496 //
1497 // imagespec, width / height info
1498 //
1499 //
1500 //
1501 // Postconditions:
1502 //
1503 // Returns: B_ERROR, if there is an error allocating memory
1504 //
1505 // B_OK, if all went well
1506 // ---------------------------------------------------------------
1507 status_t
1508 TGATranslator::translate_from_tganm_to_bits(BPositionIO *inSource,
1509 	BPositionIO *outDestination, TGAFileHeader &filehead,
1510 	TGAColorMapSpec &mapspec, TGAImageSpec &imagespec)
1511 {
1512 	bool bvflip;
1513 	if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
1514 		bvflip = false;
1515 	else
1516 		bvflip = true;
1517 	uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec);
1518 	int32 bitsRowBytes = imagespec.width * 4;
1519 	uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
1520 		((imagespec.depth % 8) ? 1 : 0);
1521 	int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel);
1522 	uint32 tgapixrow = 0;
1523 
1524 	// Setup outDestination so that it can be written to
1525 	// from the end of the file to the beginning instead of
1526 	// the other way around
1527 	off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
1528 		sizeof(TranslatorBitmap);
1529 	if (outDestination->SetSize(bitsFileSize) != B_OK)
1530 		// This call should work for BFile and BMallocIO objects,
1531 		// but may not work for other BPositionIO based types
1532 		return B_ERROR;
1533 	off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
1534 	if (bvflip)
1535 		outDestination->Seek(bitsoffset, SEEK_CUR);
1536 
1537 	// allocate row buffers
1538 	uint8 *tgaRowData = new uint8[tgaRowBytes];
1539 	if (!tgaRowData)
1540 		return B_ERROR;
1541 	uint8 *bitsRowData = new uint8[bitsRowBytes];
1542 	if (!bitsRowData) {
1543 		delete[] tgaRowData;
1544 		tgaRowData = NULL;
1545 		return B_ERROR;
1546 	}
1547 
1548 	// perform the actual translation
1549 	memset(bitsRowData, 0xff, bitsRowBytes);
1550 	ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes);
1551 	while (rd == tgaRowBytes) {
1552 		pix_tganm_to_bits(bitsRowData, tgaRowData,
1553 			imagespec.width, imagespec.depth,
1554 			tgaBytesPerPixel, nalpha);
1555 
1556 		outDestination->Write(bitsRowData, bitsRowBytes);
1557 		tgapixrow++;
1558 		// if I've read all of the pixel data, break
1559 		// out of the loop so I don't try to read
1560 		// non-pixel data
1561 		if (tgapixrow == imagespec.height)
1562 			break;
1563 
1564 		if (bvflip)
1565 			outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
1566 		rd = inSource->Read(tgaRowData, tgaRowBytes);
1567 	}
1568 
1569 	delete[] tgaRowData;
1570 	tgaRowData = NULL;
1571 	delete[] bitsRowData;
1572 	bitsRowData = NULL;
1573 
1574 	return B_OK;
1575 }
1576 
1577 // ---------------------------------------------------------------
1578 // translate_from_tganmrle_to_bits
1579 //
1580 // Convert non color map, RLE TGA to Be bitmap format
1581 // and write results to outDestination
1582 //
1583 // Preconditions:
1584 //
1585 // Parameters: inSource,	the TGA data to be translated
1586 //
1587 // outDestination,	where the bits data will be written to
1588 //
1589 // filehead, image type info
1590 //
1591 // mapspec, color map info
1592 //
1593 // imagespec, width / height info
1594 //
1595 //
1596 //
1597 // Postconditions:
1598 //
1599 // Returns: B_ERROR, if there is an error allocating memory
1600 //
1601 // B_OK, if all went well
1602 // ---------------------------------------------------------------
1603 status_t
1604 TGATranslator::translate_from_tganmrle_to_bits(BPositionIO *inSource,
1605 	BPositionIO *outDestination, TGAFileHeader &filehead,
1606 	TGAColorMapSpec &mapspec, TGAImageSpec &imagespec)
1607 {
1608 	status_t result = B_OK;
1609 
1610 	bool bvflip;
1611 	if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
1612 		bvflip = false;
1613 	else
1614 		bvflip = true;
1615 	uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec);
1616 	int32 bitsRowBytes = imagespec.width * 4;
1617 	uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
1618 		((imagespec.depth % 8) ? 1 : 0);
1619 	uint16 tgapixrow = 0, tgapixcol = 0;
1620 
1621 	// Setup outDestination so that it can be written to
1622 	// from the end of the file to the beginning instead of
1623 	// the other way around
1624 	off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
1625 		sizeof(TranslatorBitmap);
1626 	if (outDestination->SetSize(bitsFileSize) != B_OK)
1627 		// This call should work for BFile and BMallocIO objects,
1628 		// but may not work for other BPositionIO based types
1629 		return B_ERROR;
1630 	off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
1631 	if (bvflip)
1632 		outDestination->Seek(bitsoffset, SEEK_CUR);
1633 
1634 	// allocate row buffers
1635 	uint8 *bitsRowData = new uint8[bitsRowBytes];
1636 	if (!bitsRowData)
1637 		return B_ERROR;
1638 
1639 	// perform the actual translation
1640 	memset(bitsRowData, 0xff, bitsRowBytes);
1641 	uint8 *pbitspixel = bitsRowData;
1642 	uint8 packethead;
1643 	StreamBuffer sbuf(inSource, TGA_STREAM_BUFFER_SIZE, true);
1644 	ssize_t rd = 0;
1645 	if (sbuf.InitCheck() == B_OK)
1646 		rd = sbuf.Read(&packethead, 1);
1647 	while (rd == 1) {
1648 		// Run Length Packet
1649 		if (packethead & TGA_RLE_PACKET_TYPE_BIT) {
1650 			uint8 tgapixel[4], rlecount;
1651 			rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
1652 			if (tgapixcol + rlecount > imagespec.width) {
1653 				result = B_NO_TRANSLATOR;
1654 				break;
1655 			}
1656 			rd = sbuf.Read(tgapixel, tgaBytesPerPixel);
1657 			if (rd == tgaBytesPerPixel) {
1658 				pix_tganm_to_bits(pbitspixel, tgapixel,
1659 					rlecount, imagespec.depth, 0, nalpha);
1660 
1661 				pbitspixel += 4 * rlecount;
1662 				tgapixcol += rlecount;
1663 			} else {
1664 				result = B_NO_TRANSLATOR;
1665 				break; // error
1666 			}
1667 
1668 		// Raw Packet
1669 		} else {
1670 			uint8 tgaPixelBuf[512], rawcount;
1671 			uint16 rawbytes;
1672 			rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
1673 			if (tgapixcol + rawcount > imagespec.width) {
1674 				result = B_NO_TRANSLATOR;
1675 				break;
1676 			}
1677 			rawbytes = tgaBytesPerPixel * rawcount;
1678 			rd = sbuf.Read(tgaPixelBuf, rawbytes);
1679 			if (rd == rawbytes) {
1680 				pix_tganm_to_bits(pbitspixel, tgaPixelBuf,
1681 					rawcount, imagespec.depth, tgaBytesPerPixel, nalpha);
1682 
1683 				pbitspixel += 4 * rawcount;
1684 				tgapixcol += rawcount;
1685 			} else {
1686 				result = B_NO_TRANSLATOR;
1687 				break;
1688 			}
1689 		}
1690 
1691 		if (tgapixcol == imagespec.width) {
1692 			outDestination->Write(bitsRowData, bitsRowBytes);
1693 			tgapixcol = 0;
1694 			tgapixrow++;
1695 			if (tgapixrow == imagespec.height)
1696 				break;
1697 			if (bvflip)
1698 				outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
1699 			pbitspixel = bitsRowData;
1700 		}
1701 		rd = sbuf.Read(&packethead, 1);
1702 	}
1703 
1704 	delete[] bitsRowData;
1705 	bitsRowData = NULL;
1706 
1707 	return result;
1708 }
1709 
1710 // convert a row of color mapped pixels to pbits
1711 status_t
1712 pix_tgam_to_bits(uint8 *pbits, uint8 *ptgaindices,
1713 	uint16 width, uint8 depth, uint8 *pmap)
1714 {
1715 	status_t result = B_OK;
1716 	uint8 *ptgapixel = NULL;
1717 
1718 	switch (depth) {
1719 		case 32:
1720 			for (uint16 i = 0; i < width; i++) {
1721 				ptgapixel = pmap +
1722 					(ptgaindices[i] * 4);
1723 
1724 				memcpy(pbits, ptgapixel, 4);
1725 
1726 				pbits += 4;
1727 			}
1728 			break;
1729 
1730 		case 24:
1731 			for (uint16 i = 0; i < width; i++) {
1732 				ptgapixel = pmap +
1733 					(ptgaindices[i] * 3);
1734 
1735 				memcpy(pbits, ptgapixel, 3);
1736 
1737 				pbits += 4;
1738 			}
1739 			break;
1740 
1741 		case 16:
1742 			for (uint16 i = 0; i < width; i++) {
1743 				uint16 val;
1744 
1745 				ptgapixel = pmap +
1746 					(ptgaindices[i] * 2);
1747 				val = ptgapixel[0] + (ptgapixel[1] << 8);
1748 				pbits[0] =
1749 					((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1750 				pbits[1] =
1751 					((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1752 				pbits[2] =
1753 					((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1754 				pbits[3] = (val & 0x8000) ? 255 : 0;
1755 
1756 				pbits += 4;
1757 			}
1758 			break;
1759 
1760 		case 15:
1761 			for (uint16 i = 0; i < width; i++) {
1762 				uint16 val;
1763 
1764 				ptgapixel = pmap +
1765 					(ptgaindices[i] * 2);
1766 				val = ptgapixel[0] + (ptgapixel[1] << 8);
1767 				pbits[0] =
1768 					((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
1769 				pbits[1] =
1770 					((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
1771 				pbits[2] =
1772 					((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
1773 
1774 				pbits += 4;
1775 			}
1776 			break;
1777 
1778 		default:
1779 			result = B_ERROR;
1780 			break;
1781 	}
1782 
1783 	return result;
1784 }
1785 
1786 // ---------------------------------------------------------------
1787 // translate_from_tgam_to_bits
1788 //
1789 // Translates a paletted TGA from inSource to the bits format.
1790 //
1791 // Preconditions:
1792 //
1793 // Parameters: inSource,	the TGA data to be translated
1794 //
1795 // outDestination,	where the bits data will be written to
1796 //
1797 // mapspec, info about the color map (palette)
1798 //
1799 // imagespec, width / height info
1800 //
1801 // pmap, color palette
1802 //
1803 //
1804 // Postconditions:
1805 //
1806 // Returns: B_ERROR, if there is an error allocating memory
1807 //
1808 // B_OK, if all went well
1809 // ---------------------------------------------------------------
1810 status_t
1811 translate_from_tgam_to_bits(BPositionIO *inSource,
1812 	BPositionIO *outDestination, TGAColorMapSpec &mapspec,
1813 	TGAImageSpec &imagespec, uint8 *pmap)
1814 {
1815 	bool bvflip;
1816 	if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
1817 		bvflip = false;
1818 	else
1819 		bvflip = true;
1820 
1821 	int32 bitsRowBytes = imagespec.width * 4;
1822 	uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
1823 		((imagespec.depth % 8) ? 1 : 0);
1824 	int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel);
1825 	uint32 tgapixrow = 0;
1826 
1827 	// Setup outDestination so that it can be written to
1828 	// from the end of the file to the beginning instead of
1829 	// the other way around
1830 	off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
1831 		sizeof(TranslatorBitmap);
1832 	if (outDestination->SetSize(bitsFileSize) != B_OK)
1833 		// This call should work for BFile and BMallocIO objects,
1834 		// but may not work for other BPositionIO based types
1835 		return B_ERROR;
1836 	off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
1837 	if (bvflip)
1838 		outDestination->Seek(bitsoffset, SEEK_CUR);
1839 
1840 	// allocate row buffers
1841 	uint8 *tgaRowData = new uint8[tgaRowBytes];
1842 	if (!tgaRowData)
1843 		return B_ERROR;
1844 	uint8 *bitsRowData = new uint8[bitsRowBytes];
1845 	if (!bitsRowData) {
1846 		delete[] tgaRowData;
1847 		tgaRowData = NULL;
1848 		return B_ERROR;
1849 	}
1850 
1851 	// perform the actual translation
1852 	memset(bitsRowData, 0xff, bitsRowBytes);
1853 	ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes);
1854 	while (rd == tgaRowBytes) {
1855 		pix_tgam_to_bits(bitsRowData, tgaRowData,
1856 			imagespec.width, mapspec.entrysize, pmap);
1857 
1858 		outDestination->Write(bitsRowData, bitsRowBytes);
1859 		tgapixrow++;
1860 		// if I've read all of the pixel data, break
1861 		// out of the loop so I don't try to read
1862 		// non-pixel data
1863 		if (tgapixrow == imagespec.height)
1864 			break;
1865 
1866 		if (bvflip)
1867 			outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
1868 		rd = inSource->Read(tgaRowData, tgaRowBytes);
1869 	}
1870 
1871 	delete[] tgaRowData;
1872 	tgaRowData = NULL;
1873 	delete[] bitsRowData;
1874 	bitsRowData = NULL;
1875 
1876 	return B_OK;
1877 }
1878 
1879 // ---------------------------------------------------------------
1880 // translate_from_tgamrle_to_bits
1881 //
1882 // Translates a color mapped or non color mapped RLE TGA from
1883 // inSource to the bits format.
1884 //
1885 // Preconditions:
1886 //
1887 // Parameters: inSource,	the TGA data to be translated
1888 //
1889 // outDestination,	where the bits data will be written to
1890 //
1891 // filehead, image type info
1892 //
1893 // mapspec, info about the color map (palette)
1894 //
1895 // imagespec, width / height info
1896 //
1897 // pmap, color palette
1898 //
1899 //
1900 // Postconditions:
1901 //
1902 // Returns: B_ERROR, if there is an error allocating memory
1903 //
1904 // B_OK, if all went well
1905 // ---------------------------------------------------------------
1906 status_t
1907 TGATranslator::translate_from_tgamrle_to_bits(BPositionIO *inSource,
1908 	BPositionIO *outDestination, TGAFileHeader &filehead,
1909 	TGAColorMapSpec &mapspec, TGAImageSpec &imagespec, uint8 *pmap)
1910 {
1911 	status_t result = B_OK;
1912 
1913 	bool bvflip;
1914 	if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
1915 		bvflip = false;
1916 	else
1917 		bvflip = true;
1918 	uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec);
1919 	int32 bitsRowBytes = imagespec.width * 4;
1920 	uint8 tgaPalBytesPerPixel = (mapspec.entrysize / 8) +
1921 		((mapspec.entrysize % 8) ? 1 : 0);
1922 	uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
1923 		((imagespec.depth % 8) ? 1 : 0);
1924 	uint16 tgapixrow = 0, tgapixcol = 0;
1925 
1926 	// Setup outDestination so that it can be written to
1927 	// from the end of the file to the beginning instead of
1928 	// the other way around
1929 	off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
1930 		sizeof(TranslatorBitmap);
1931 	if (outDestination->SetSize(bitsFileSize) != B_OK)
1932 		// This call should work for BFile and BMallocIO objects,
1933 		// but may not work for other BPositionIO based types
1934 		return B_ERROR;
1935 	off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
1936 	if (bvflip)
1937 		outDestination->Seek(bitsoffset, SEEK_CUR);
1938 
1939 	// allocate row buffers
1940 	uint8 *bitsRowData = new uint8[bitsRowBytes];
1941 	if (!bitsRowData)
1942 		return B_ERROR;
1943 
1944 	// perform the actual translation
1945 	memset(bitsRowData, 0xff, bitsRowBytes);
1946 	uint8 *pbitspixel = bitsRowData;
1947 	uint8 packethead;
1948 	StreamBuffer sbuf(inSource, TGA_STREAM_BUFFER_SIZE, true);
1949 	ssize_t rd = 0;
1950 	if (sbuf.InitCheck() == B_OK)
1951 		rd = sbuf.Read(&packethead, 1);
1952 	while (rd == 1) {
1953 		// Run Length Packet
1954 		if (packethead & TGA_RLE_PACKET_TYPE_BIT) {
1955 			uint8 tgaindex, rlecount;
1956 			rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
1957 			if (tgapixcol + rlecount > imagespec.width) {
1958 				result = B_NO_TRANSLATOR;
1959 				break;
1960 			}
1961 			rd = sbuf.Read(&tgaindex, 1);
1962 			if (rd == tgaBytesPerPixel) {
1963 				uint8 *ptgapixel;
1964 				ptgapixel = pmap + (tgaindex * tgaPalBytesPerPixel);
1965 
1966 				pix_tganm_to_bits(pbitspixel, ptgapixel, rlecount,
1967 					mapspec.entrysize, 0, nalpha);
1968 
1969 				pbitspixel += 4 * rlecount;
1970 				tgapixcol += rlecount;
1971 			} else {
1972 				result = B_NO_TRANSLATOR;
1973 				break; // error
1974 			}
1975 
1976 		// Raw Packet
1977 		} else {
1978 			uint8 tgaIndexBuf[128], rawcount;
1979 			rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
1980 			if (tgapixcol + rawcount > imagespec.width) {
1981 				result = B_NO_TRANSLATOR;
1982 				break;
1983 			}
1984 			rd = sbuf.Read(tgaIndexBuf, rawcount);
1985 			if (rd == rawcount) {
1986 				pix_tgam_to_bits(pbitspixel, tgaIndexBuf,
1987 					rawcount, mapspec.entrysize, pmap);
1988 
1989 				pbitspixel += 4 * rawcount;
1990 				tgapixcol += rawcount;
1991 			} else {
1992 				result = B_NO_TRANSLATOR;
1993 				break;
1994 			}
1995 		}
1996 
1997 		if (tgapixcol == imagespec.width) {
1998 			outDestination->Write(bitsRowData, bitsRowBytes);
1999 			tgapixcol = 0;
2000 			tgapixrow++;
2001 			if (tgapixrow == imagespec.height)
2002 				break;
2003 			if (bvflip)
2004 				outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
2005 			pbitspixel = bitsRowData;
2006 		}
2007 		rd = sbuf.Read(&packethead, 1);
2008 	}
2009 
2010 	delete[] bitsRowData;
2011 	bitsRowData = NULL;
2012 
2013 	return result;
2014 }
2015 
2016 // ---------------------------------------------------------------
2017 // translate_from_tga
2018 //
2019 // Convert the data in inSource from the TGA format
2020 // to the format specified in outType (either bits or TGA).
2021 //
2022 // Preconditions:
2023 //
2024 // Parameters:	inSource,	the bits data to translate
2025 //
2026 // 				amtread,	the amount of data already read from
2027 //							inSource
2028 //
2029 //				read,		pointer to the data already read from
2030 //							inSource
2031 //
2032 //				outType,	the type of data to convert to
2033 //
2034 //				outDestination,	where the output is written to
2035 //
2036 // Postconditions:
2037 //
2038 // Returns: B_NO_TRANSLATOR,	if the data is not in a supported
2039 //								format
2040 //
2041 // B_ERROR, if there was an error allocating memory or some other
2042 //			error
2043 //
2044 // B_OK, if successfully translated the data from the bits format
2045 // ---------------------------------------------------------------
2046 status_t
2047 TGATranslator::translate_from_tga(BPositionIO *inSource, uint32 outType,
2048 	BPositionIO *outDestination)
2049 {
2050 	TGAFileHeader fileheader;
2051 	TGAColorMapSpec mapspec;
2052 	TGAImageSpec imagespec;
2053 	bool bheaderonly = false, bdataonly = false;
2054 
2055 	status_t result;
2056 	result = identify_tga_header(inSource, NULL, &fileheader, &mapspec,
2057 		&imagespec);
2058 	if (result != B_OK)
2059 		return result;
2060 
2061 	// if the user wants to translate a TGA to a TGA, easy enough :)
2062 	if (outType == B_TGA_FORMAT) {
2063 		// write out the TGA headers
2064 		if (bheaderonly || (!bheaderonly && !bdataonly)) {
2065 			result = write_tga_headers(outDestination, fileheader,
2066 				mapspec, imagespec);
2067 			if (result != B_OK)
2068 				return result;
2069 		}
2070 		if (bheaderonly)
2071 			// if the user only wants the header,
2072 			// bail before it is written
2073 			return result;
2074 
2075 		const int32 kbuflen = 1024;
2076 		uint8 buf[kbuflen];
2077 		ssize_t rd = inSource->Read(buf, kbuflen);
2078 		while (rd > 0) {
2079 			outDestination->Write(buf, rd);
2080 			rd = inSource->Read(buf, kbuflen);
2081 		}
2082 		if (rd == 0)
2083 			return B_OK;
2084 		else
2085 			return B_ERROR;
2086 
2087 	// if translating a TGA to a Be Bitmap
2088 	} else if (outType == B_TRANSLATOR_BITMAP) {
2089 		TranslatorBitmap bitsHeader;
2090 		bitsHeader.magic = B_TRANSLATOR_BITMAP;
2091 		bitsHeader.bounds.left = 0;
2092 		bitsHeader.bounds.top = 0;
2093 		bitsHeader.bounds.right = imagespec.width - 1;
2094 		bitsHeader.bounds.bottom = imagespec.height - 1;
2095 
2096 		// skip over Image ID data (if present)
2097 		if (fileheader.idlength > 0)
2098 			inSource->Seek(fileheader.idlength, SEEK_CUR);
2099 
2100 		// read in palette and/or skip non-TGA data
2101 		uint8 *ptgapalette = NULL;
2102 		if (fileheader.colormaptype == TGA_COLORMAP) {
2103 			uint32 nentrybytes;
2104 			nentrybytes = mapspec.entrysize / 8;
2105 			if (mapspec.entrysize % 8)
2106 				nentrybytes++;
2107 			ptgapalette = new uint8[nentrybytes * mapspec.length];
2108 			inSource->Read(ptgapalette, nentrybytes * mapspec.length);
2109 		}
2110 
2111 		bitsHeader.rowBytes = imagespec.width * 4;
2112 		if (fileheader.imagetype != TGA_NOCOMP_BW &&
2113 			fileheader.imagetype != TGA_RLE_BW &&
2114 			tga_alphabits(fileheader, mapspec, imagespec))
2115 			bitsHeader.colors = B_RGBA32;
2116 		else
2117 			bitsHeader.colors = B_RGB32;
2118 		int32 datasize = bitsHeader.rowBytes * imagespec.height;
2119 		bitsHeader.dataSize = datasize;
2120 
2121 		// write out Be's Bitmap header
2122 		if (bheaderonly || (!bheaderonly && !bdataonly)) {
2123 			if (swap_data(B_UINT32_TYPE, &bitsHeader,
2124 				sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK)
2125 				return B_ERROR;
2126 			outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap));
2127 		}
2128 		if (bheaderonly)
2129 			// if the user only wants the header,
2130 			// bail before the data is written
2131 			return B_OK;
2132 
2133 		// write out the actual image data
2134 		switch (fileheader.imagetype) {
2135 			case TGA_NOCOMP_TRUECOLOR:
2136 			case TGA_NOCOMP_BW:
2137 				result = translate_from_tganm_to_bits(inSource,
2138 					outDestination, fileheader, mapspec, imagespec);
2139 				break;
2140 
2141 			case TGA_NOCOMP_COLORMAP:
2142 				result = translate_from_tgam_to_bits(inSource,
2143 					outDestination, mapspec, imagespec, ptgapalette);
2144 				break;
2145 
2146 			case TGA_RLE_TRUECOLOR:
2147 			case TGA_RLE_BW:
2148 				result = translate_from_tganmrle_to_bits(inSource,
2149 					outDestination, fileheader, mapspec, imagespec);
2150 				break;
2151 
2152 			case TGA_RLE_COLORMAP:
2153 				result = translate_from_tgamrle_to_bits(inSource, outDestination,
2154 					fileheader, mapspec, imagespec, ptgapalette);
2155 				break;
2156 
2157 			default:
2158 				result = B_NO_TRANSLATOR;
2159 				break;
2160 		}
2161 
2162 		delete[] ptgapalette;
2163 		ptgapalette = NULL;
2164 
2165 		return result;
2166 
2167 	} else
2168 		return B_NO_TRANSLATOR;
2169 }
2170 
2171 status_t
2172 TGATranslator::DerivedTranslate(BPositionIO *inSource,
2173 	const translator_info *inInfo, BMessage *ioExtension, uint32 outType,
2174 	BPositionIO *outDestination, int32 baseType)
2175 {
2176 	if (baseType == 1)
2177 		// if inSource is in bits format
2178 		return translate_from_bits(inSource, outType, outDestination);
2179 	else if (baseType == 0)
2180 		// if inSource is NOT in bits format
2181 		return translate_from_tga(inSource, outType, outDestination);
2182 	else
2183 		// if BaseTranslator did not properly identify the data as
2184 		// bits or not bits
2185 		return B_NO_TRANSLATOR;
2186 }
2187 
2188 BView *
2189 TGATranslator::NewConfigView(TranslatorSettings *settings)
2190 {
2191 	return new TGAView(BRect(0, 0, 225, 175), "TGATranslator Settings",
2192 		B_FOLLOW_ALL, B_WILL_DRAW, settings);
2193 }
2194 
2195