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