#include <string.h>
#include <stdio.h>
#include <Catalog.h>
#include "TGATranslator.h"
#include "TGAView.h"
#include "StreamBuffer.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "TGATranslator"
static const translation_format sInputFormats[] = {
{
B_TRANSLATOR_BITMAP,
B_TRANSLATOR_BITMAP,
BBT_IN_QUALITY,
BBT_IN_CAPABILITY,
"image/x-be-bitmap",
"Be Bitmap Format (TGATranslator)"
},
{
B_TGA_FORMAT,
B_TRANSLATOR_BITMAP,
TGA_IN_QUALITY,
TGA_IN_CAPABILITY,
"image/x-targa",
"Targa image"
}
};
static const translation_format sOutputFormats[] = {
{
B_TRANSLATOR_BITMAP,
B_TRANSLATOR_BITMAP,
BBT_OUT_QUALITY,
BBT_OUT_CAPABILITY,
"image/x-be-bitmap",
"Be Bitmap Format (TGATranslator)"
},
{
B_TGA_FORMAT,
B_TRANSLATOR_BITMAP,
TGA_OUT_QUALITY,
TGA_OUT_CAPABILITY,
"image/x-targa",
"Targa image"
}
};
static const TranSetting sDefaultSettings[] = {
{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false},
{TGA_SETTING_RLE, TRAN_SETTING_BOOL, false},
{TGA_SETTING_IGNORE_ALPHA, TRAN_SETTING_BOOL, false}
};
const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
BTranslator *
make_nth_translator(int32 n, image_id you, uint32 flags, ...)
{
BTranslator *ptranslator = NULL;
if (!n)
ptranslator = new(std::nothrow) TGATranslator();
return ptranslator;
}
TGATranslator::TGATranslator()
: BaseTranslator(B_TRANSLATE("TGA images"),
B_TRANSLATE("TGA image translator"),
TGA_TRANSLATOR_VERSION,
sInputFormats, kNumInputFormats,
sOutputFormats, kNumOutputFormats,
"TGATranslator_Settings",
sDefaultSettings, kNumDefaultSettings,
B_TRANSLATOR_BITMAP, B_TGA_FORMAT)
{
}
TGATranslator::~TGATranslator()
{
}
uint8
TGATranslator::tga_alphabits(TGAFileHeader &filehead, TGAColorMapSpec &mapspec,
TGAImageSpec &imagespec)
{
if (fSettings->SetGetBool(TGA_SETTING_IGNORE_ALPHA))
return 0;
else {
uint8 nalpha;
if (filehead.imagetype == TGA_NOCOMP_COLORMAP ||
filehead.imagetype == TGA_RLE_COLORMAP) {
if (mapspec.entrysize == 32)
nalpha = 8;
else if (mapspec.entrysize == 16)
nalpha = 1;
else
nalpha = 0;
} else {
if (imagespec.depth == 32)
nalpha = 8;
else
nalpha = imagespec.descriptor & TGA_DESC_ALPHABITS;
}
return nalpha;
}
}
status_t
identify_tga_header(BPositionIO *inSource, translator_info *outInfo,
TGAFileHeader *pfileheader = NULL, TGAColorMapSpec *pmapspec = NULL,
TGAImageSpec *pimagespec = NULL)
{
uint8 buf[TGA_HEADERS_SIZE];
ssize_t size = TGA_HEADERS_SIZE;
if (size > 0 && inSource->Read(buf, size) != size)
return B_NO_TRANSLATOR;
TGAFileHeader fileheader;
fileheader.idlength = buf[0];
fileheader.colormaptype = buf[1];
if (fileheader.colormaptype > 1)
return B_NO_TRANSLATOR;
fileheader.imagetype = buf[2];
if ((fileheader.imagetype > 3 && fileheader.imagetype < 9) ||
fileheader.imagetype > 11)
return B_NO_TRANSLATOR;
if ((fileheader.colormaptype == TGA_NO_COLORMAP &&
fileheader.imagetype == TGA_NOCOMP_COLORMAP) ||
(fileheader.colormaptype == TGA_COLORMAP &&
fileheader.imagetype != TGA_NOCOMP_COLORMAP &&
fileheader.imagetype != TGA_RLE_COLORMAP))
return B_NO_TRANSLATOR;
TGAColorMapSpec mapspec;
memcpy(&mapspec.firstentry, buf + 3, 2);
mapspec.firstentry = B_LENDIAN_TO_HOST_INT16(mapspec.firstentry);
if (fileheader.colormaptype == 0 && mapspec.firstentry != 0)
return B_NO_TRANSLATOR;
memcpy(&mapspec.length, buf + 5, 2);
mapspec.length = B_LENDIAN_TO_HOST_INT16(mapspec.length);
if (fileheader.colormaptype == TGA_NO_COLORMAP &&
mapspec.length != 0)
return B_NO_TRANSLATOR;
if (fileheader.colormaptype == TGA_COLORMAP &&
mapspec.length == 0)
return B_NO_TRANSLATOR;
mapspec.entrysize = buf[7];
if (fileheader.colormaptype == TGA_NO_COLORMAP &&
mapspec.entrysize != 0)
return B_NO_TRANSLATOR;
if (fileheader.colormaptype == TGA_COLORMAP &&
mapspec.entrysize != 15 && mapspec.entrysize != 16 &&
mapspec.entrysize != 24 && mapspec.entrysize != 32)
return B_NO_TRANSLATOR;
TGAImageSpec imagespec;
memcpy(&imagespec.xorigin, buf + 8, 2);
imagespec.xorigin = B_LENDIAN_TO_HOST_INT16(imagespec.xorigin);
memcpy(&imagespec.yorigin, buf + 10, 2);
imagespec.yorigin = B_LENDIAN_TO_HOST_INT16(imagespec.yorigin);
memcpy(&imagespec.width, buf + 12, 2);
imagespec.width = B_LENDIAN_TO_HOST_INT16(imagespec.width);
if (imagespec.width == 0)
return B_NO_TRANSLATOR;
memcpy(&imagespec.height, buf + 14, 2);
imagespec.height = B_LENDIAN_TO_HOST_INT16(imagespec.height);
if (imagespec.height == 0)
return B_NO_TRANSLATOR;
imagespec.depth = buf[16];
if (imagespec.depth < 1 || imagespec.depth > 32)
return B_NO_TRANSLATOR;
if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR ||
fileheader.imagetype == TGA_RLE_TRUECOLOR) &&
imagespec.depth != 15 && imagespec.depth != 16 &&
imagespec.depth != 24 && imagespec.depth != 32)
return B_NO_TRANSLATOR;
if ((fileheader.imagetype == TGA_NOCOMP_BW ||
fileheader.imagetype == TGA_RLE_BW) &&
imagespec.depth != 8)
return B_NO_TRANSLATOR;
if (fileheader.colormaptype == TGA_COLORMAP &&
imagespec.depth != 8)
return B_NO_TRANSLATOR;
imagespec.descriptor = buf[17];
if ((imagespec.descriptor & TGA_ORIGIN_HORZ_BIT) != TGA_ORIGIN_LEFT)
return B_NO_TRANSLATOR;
if (imagespec.descriptor & TGA_DESC_BITS76)
return B_NO_TRANSLATOR;
if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR ||
fileheader.imagetype == TGA_RLE_TRUECOLOR) &&
imagespec.depth == 32 &&
(imagespec.descriptor & TGA_DESC_ALPHABITS) != 8 &&
(imagespec.descriptor & TGA_DESC_ALPHABITS) != 0)
return B_NO_TRANSLATOR;
if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR ||
fileheader.imagetype == TGA_RLE_TRUECOLOR) &&
imagespec.depth == 24 &&
(imagespec.descriptor & TGA_DESC_ALPHABITS) != 0)
return B_NO_TRANSLATOR;
if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR ||
fileheader.imagetype == TGA_RLE_TRUECOLOR) &&
imagespec.depth == 16 &&
(imagespec.descriptor & TGA_DESC_ALPHABITS) != 1 &&
(imagespec.descriptor & TGA_DESC_ALPHABITS) != 0)
if ((fileheader.imagetype == TGA_NOCOMP_TRUECOLOR ||
fileheader.imagetype == TGA_RLE_TRUECOLOR) &&
imagespec.depth == 15 &&
(imagespec.descriptor & TGA_DESC_ALPHABITS) != 0)
return B_NO_TRANSLATOR;
if (pfileheader) {
pfileheader->idlength = fileheader.idlength;
pfileheader->colormaptype = fileheader.colormaptype;
pfileheader->imagetype = fileheader.imagetype;
}
if (pmapspec) {
pmapspec->firstentry = mapspec.firstentry;
pmapspec->length = mapspec.length;
pmapspec->entrysize = mapspec.entrysize;
}
if (pimagespec) {
pimagespec->xorigin = imagespec.xorigin;
pimagespec->yorigin = imagespec.yorigin;
pimagespec->width = imagespec.width;
pimagespec->height = imagespec.height;
pimagespec->depth = imagespec.depth;
pimagespec->descriptor = imagespec.descriptor;
}
if (outInfo) {
outInfo->type = B_TGA_FORMAT;
outInfo->group = B_TRANSLATOR_BITMAP;
outInfo->quality = TGA_IN_QUALITY;
outInfo->capability = TGA_IN_CAPABILITY;
switch (fileheader.imagetype) {
case TGA_NOCOMP_COLORMAP:
snprintf(outInfo->name, sizeof(outInfo->name),
B_TRANSLATE("Targa image (%d bits colormap)"),
imagespec.depth);
break;
case TGA_NOCOMP_TRUECOLOR:
snprintf(outInfo->name, sizeof(outInfo->name),
B_TRANSLATE("Targa image (%d bits truecolor)"),
imagespec.depth);
break;
case TGA_RLE_COLORMAP:
snprintf(outInfo->name, sizeof(outInfo->name),
B_TRANSLATE("Targa image (%d bits RLE colormap)"),
imagespec.depth);
break;
case TGA_RLE_TRUECOLOR:
snprintf(outInfo->name, sizeof(outInfo->name),
B_TRANSLATE("Targa image (%d bits RLE truecolor)"),
imagespec.depth);
break;
case TGA_RLE_BW:
snprintf(outInfo->name, sizeof(outInfo->name),
B_TRANSLATE("Targa image (%d bits RLE gray)"),
imagespec.depth);
break;
case TGA_NOCOMP_BW:
default:
snprintf(outInfo->name, sizeof(outInfo->name),
B_TRANSLATE("Targa image (%d bits gray)"),
imagespec.depth);
break;
}
strcpy(outInfo->MIME, "image/x-targa");
}
return B_OK;
}
status_t
TGATranslator::DerivedIdentify(BPositionIO *inSource,
const translation_format *inFormat, BMessage *ioExtension,
translator_info *outInfo, uint32 outType)
{
return identify_tga_header(inSource, outInfo);
}
status_t
pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
uint16 width, const color_map *pmap, int32 bitsBytesPerPixel)
{
status_t bytescopied = 0;
switch (fromspace) {
case B_RGBA32:
bytescopied = width * 4;
memcpy(ptga, pbits, bytescopied);
break;
case B_RGBA32_BIG:
bytescopied = width * 4;
while (width--) {
ptga[0] = pbits[3];
ptga[1] = pbits[2];
ptga[2] = pbits[1];
ptga[3] = pbits[0];
ptga += 4;
pbits += 4;
}
break;
case B_CMYA32:
bytescopied = width * 4;
while (width--) {
ptga[0] = 255 - pbits[2];
ptga[1] = 255 - pbits[1];
ptga[2] = 255 - pbits[0];
ptga[3] = pbits[3];
ptga += 4;
pbits += 4;
}
break;
case B_RGB32:
case B_RGB24:
bytescopied = width * 3;
while (width--) {
memcpy(ptga, pbits, 3);
ptga += 3;
pbits += bitsBytesPerPixel;
}
break;
case B_CMYK32:
{
int32 comp;
bytescopied = width * 3;
while (width--) {
comp = 255 - pbits[2] - pbits[3];
ptga[0] = (comp < 0) ? 0 : comp;
comp = 255 - pbits[1] - pbits[3];
ptga[1] = (comp < 0) ? 0 : comp;
comp = 255 - pbits[0] - pbits[3];
ptga[2] = (comp < 0) ? 0 : comp;
ptga += 3;
pbits += 4;
}
break;
}
case B_CMY32:
case B_CMY24:
bytescopied = width * 3;
while (width--) {
ptga[0] = 255 - pbits[2];
ptga[1] = 255 - pbits[1];
ptga[2] = 255 - pbits[0];
ptga += 3;
pbits += bitsBytesPerPixel;
}
break;
case B_RGB16:
case B_RGB16_BIG:
{
uint16 val;
bytescopied = width * 3;
while (width--) {
if (fromspace == B_RGB16)
val = pbits[0] + (pbits[1] << 8);
else
val = pbits[1] + (pbits[0] << 8);
ptga[0] =
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
ptga[1] =
((val & 0x7e0) >> 3) | ((val & 0x7e0) >> 9);
ptga[2] =
((val & 0xf800) >> 8) | ((val & 0xf800) >> 13);
ptga += 3;
pbits += 2;
}
break;
}
case B_RGBA15:
bytescopied = width * 2;
memcpy(ptga, pbits, bytescopied);
break;
case B_RGBA15_BIG:
bytescopied = width * 2;
while (width--) {
ptga[0] = pbits[1];
ptga[1] = pbits[0];
ptga += 2;
pbits += 2;
}
break;
case B_RGB15:
bytescopied = width * 2;
while (width--) {
ptga[0] = pbits[0];
ptga[1] = pbits[1] | 0x80;
ptga += 2;
pbits += 2;
}
break;
case B_RGB15_BIG:
bytescopied = width * 2;
while (width--) {
ptga[0] = pbits[1];
ptga[1] = pbits[0] | 0x80;
ptga += 2;
pbits += 2;
}
break;
case B_RGB32_BIG:
bytescopied = width * 3;
while (width--) {
ptga[0] = pbits[3];
ptga[1] = pbits[2];
ptga[2] = pbits[1];
ptga += 3;
pbits += 4;
}
break;
case B_RGB24_BIG:
bytescopied = width * 3;
while (width--) {
ptga[0] = pbits[2];
ptga[1] = pbits[1];
ptga[2] = pbits[0];
ptga += 3;
pbits += 3;
}
break;
case B_CMAP8:
{
rgb_color c;
bytescopied = width * 3;
while (width--) {
c = pmap->color_list[pbits[0]];
ptga[0] = c.blue;
ptga[1] = c.green;
ptga[2] = c.red;
ptga += 3;
pbits++;
}
break;
}
case B_GRAY8:
bytescopied = width;
memcpy(ptga, pbits, bytescopied);
break;
default:
bytescopied = B_ERROR;
break;
}
return bytescopied;
}
status_t
copy_rle_packet(uint8 *ptga, uint32 pixel, uint8 count,
color_space fromspace, const color_map *pmap,
int32 bitsBytesPerPixel)
{
uint8 packethead = (count - 1) | 0x80;
ptga[0] = packethead;
ptga++;
return pix_bits_to_tga(reinterpret_cast<uint8 *> (&pixel),
ptga, fromspace, 1, pmap, bitsBytesPerPixel) + 1;
}
status_t
copy_raw_packet(uint8 *ptga, uint8 *praw, uint8 count,
color_space fromspace, const color_map *pmap,
int32 bitsBytesPerPixel)
{
uint8 packethead = count - 1;
ptga[0] = packethead;
ptga++;
return pix_bits_to_tga(praw, ptga, fromspace,
count, pmap, bitsBytesPerPixel) + 1;
}
status_t
pix_bits_to_tgarle(uint8 *pbits, uint8 *ptga, color_space fromspace,
uint16 width, const color_map *pmap, int32 bitsBytesPerPixel)
{
if (width == 0)
return B_ERROR;
uint32 current = 0, next = 0, aftnext = 0;
uint16 nread = 0;
status_t result, bytescopied = 0;
uint8 *prawbuf, *praw;
prawbuf = new(std::nothrow) uint8[bitsBytesPerPixel * 128];
praw = prawbuf;
if (!prawbuf)
return B_ERROR;
uint8 rlecount = 1, rawcount = 0;
bool bJustWroteRLE = false;
memcpy(¤t, pbits, bitsBytesPerPixel);
pbits += bitsBytesPerPixel;
if (width == 1) {
result = copy_raw_packet(ptga,
reinterpret_cast<uint8 *> (¤t), 1,
fromspace, pmap, bitsBytesPerPixel);
ptga += result;
bytescopied += result;
nread++;
} else {
memcpy(&next, pbits, bitsBytesPerPixel);
pbits += bitsBytesPerPixel;
nread++;
}
while (nread < width) {
if (nread < width - 1) {
memcpy(&aftnext, pbits, bitsBytesPerPixel);
pbits += bitsBytesPerPixel;
}
nread++;
if (current == next && !bJustWroteRLE) {
rlecount++;
if (next != aftnext || nread == width || rlecount == 128) {
result = copy_rle_packet(ptga, current, rlecount,
fromspace, pmap, bitsBytesPerPixel);
ptga += result;
bytescopied += result;
rlecount = 1;
bJustWroteRLE = true;
}
} else {
if (!bJustWroteRLE) {
rawcount++;
memcpy(praw, ¤t, bitsBytesPerPixel);
praw += bitsBytesPerPixel;
}
if (nread == width) {
if (rawcount == 128) {
result = copy_raw_packet(ptga, prawbuf, rawcount,
fromspace, pmap, bitsBytesPerPixel);
ptga += result;
bytescopied += result;
praw = prawbuf;
rawcount = 0;
}
rawcount++;
memcpy(praw, &next, bitsBytesPerPixel);
praw += bitsBytesPerPixel;
}
if ((!bJustWroteRLE && next == aftnext) ||
nread == width || rawcount == 128) {
result = copy_raw_packet(ptga, prawbuf, rawcount,
fromspace, pmap, bitsBytesPerPixel);
ptga += result;
bytescopied += result;
praw = prawbuf;
rawcount = 0;
}
bJustWroteRLE = false;
}
current = next;
next = aftnext;
}
delete[] prawbuf;
prawbuf = NULL;
return bytescopied;
}
status_t
translate_from_bits_to_tgatc(BPositionIO *inSource,
BPositionIO *outDestination, color_space fromspace,
TGAImageSpec &imagespec, bool brle)
{
int32 bitsBytesPerPixel = 0;
switch (fromspace) {
case B_RGB32:
case B_RGB32_BIG:
case B_RGBA32:
case B_RGBA32_BIG:
case B_CMY32:
case B_CMYA32:
case B_CMYK32:
bitsBytesPerPixel = 4;
break;
case B_RGB24:
case B_RGB24_BIG:
case B_CMY24:
bitsBytesPerPixel = 3;
break;
case B_RGB16:
case B_RGB16_BIG:
case B_RGBA15:
case B_RGBA15_BIG:
case B_RGB15:
case B_RGB15_BIG:
bitsBytesPerPixel = 2;
break;
case B_CMAP8:
case B_GRAY8:
bitsBytesPerPixel = 1;
break;
default:
return B_ERROR;
}
int32 bitsRowBytes = imagespec.width * bitsBytesPerPixel;
uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
((imagespec.depth % 8) ? 1 : 0);
int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel) +
(imagespec.width / 2);
uint32 tgapixrow = 0;
uint8 *tgaRowData = new(std::nothrow) uint8[tgaRowBytes];
if (!tgaRowData)
return B_ERROR;
uint8 *bitsRowData = new(std::nothrow) uint8[bitsRowBytes];
if (!bitsRowData) {
delete[] tgaRowData;
tgaRowData = NULL;
return B_ERROR;
}
status_t (*convert_to_tga)(uint8 *pbits, uint8 *ptga,
color_space fromspace, uint16 width, const color_map *pmap,
int32 bitsBytesPerPixel);
if (brle)
convert_to_tga = pix_bits_to_tgarle;
else
convert_to_tga = pix_bits_to_tga;
ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes);
const color_map *pmap = NULL;
if (fromspace == B_CMAP8) {
pmap = system_colors();
if (!pmap) {
delete[] tgaRowData;
delete[] bitsRowData;
return B_ERROR;
}
}
while (rd == bitsRowBytes) {
status_t bytescopied;
bytescopied = convert_to_tga(bitsRowData, tgaRowData, fromspace,
imagespec.width, pmap, bitsBytesPerPixel);
outDestination->Write(tgaRowData, bytescopied);
tgapixrow++;
if (tgapixrow == imagespec.height)
break;
rd = inSource->Read(bitsRowData, bitsRowBytes);
}
delete[] bitsRowData;
bitsRowData = NULL;
delete[] tgaRowData;
tgaRowData = NULL;
return B_OK;
}
status_t
translate_from_bits1_to_tgabw(BPositionIO *inSource,
BPositionIO *outDestination, int32 bitsRowBytes,
TGAImageSpec &imagespec, bool brle)
{
uint8 tgaBytesPerPixel = 1;
int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel) +
(imagespec.width / 2);
uint32 tgapixrow = 0;
uint8 *tgaRowData = new(std::nothrow) uint8[tgaRowBytes];
if (!tgaRowData)
return B_ERROR;
uint8 *medRowData = new(std::nothrow) uint8[imagespec.width];
if (!medRowData) {
delete[] tgaRowData;
tgaRowData = NULL;
return B_ERROR;
}
uint8 *bitsRowData = new(std::nothrow) uint8[bitsRowBytes];
if (!bitsRowData) {
delete[] medRowData;
medRowData = NULL;
delete[] tgaRowData;
tgaRowData = NULL;
return B_ERROR;
}
status_t (*convert_to_tga)(uint8 *pbits, uint8 *ptga,
color_space fromspace, uint16 width, const color_map *pmap,
int32 bitsBytesPerPixel);
if (brle)
convert_to_tga = pix_bits_to_tgarle;
else
convert_to_tga = pix_bits_to_tga;
ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes);
while (rd == bitsRowBytes) {
uint32 tgapixcol = 0;
for (int32 i = 0; (tgapixcol < imagespec.width) &&
(i < bitsRowBytes); i++) {
uint8 pixels = bitsRowData[i];
for (uint8 compbit = 128; (tgapixcol < imagespec.width) &&
compbit; compbit >>= 1) {
if (pixels & compbit)
medRowData[tgapixcol] = 0;
else
medRowData[tgapixcol] = 255;
tgapixcol++;
}
}
status_t bytescopied;
bytescopied = convert_to_tga(medRowData, tgaRowData, B_GRAY8,
imagespec.width, NULL, 1);
outDestination->Write(tgaRowData, bytescopied);
tgapixrow++;
if (tgapixrow == imagespec.height)
break;
rd = inSource->Read(bitsRowData, bitsRowBytes);
}
delete[] bitsRowData;
bitsRowData = NULL;
delete[] medRowData;
medRowData = NULL;
delete[] tgaRowData;
tgaRowData = NULL;
return B_OK;
}
status_t
write_tga_headers(BPositionIO *outDestination, TGAFileHeader &fileheader,
TGAColorMapSpec &mapspec, TGAImageSpec &imagespec)
{
uint8 tgaheaders[TGA_HEADERS_SIZE];
TGAFileHeader outFileheader;
outFileheader.idlength = fileheader.idlength;
outFileheader.colormaptype = fileheader.colormaptype;
outFileheader.imagetype = fileheader.imagetype;
TGAColorMapSpec outMapspec;
outMapspec.firstentry = B_HOST_TO_LENDIAN_INT16(mapspec.firstentry);
outMapspec.length = B_HOST_TO_LENDIAN_INT16(mapspec.length);
outMapspec.entrysize = mapspec.entrysize;
TGAImageSpec outImagespec;
outImagespec.xorigin = B_HOST_TO_LENDIAN_INT16(imagespec.xorigin);
outImagespec.yorigin = B_HOST_TO_LENDIAN_INT16(imagespec.yorigin);
outImagespec.width = B_HOST_TO_LENDIAN_INT16(imagespec.width);
outImagespec.height = B_HOST_TO_LENDIAN_INT16(imagespec.height);
outImagespec.depth = imagespec.depth;
outImagespec.descriptor = imagespec.descriptor;
tgaheaders[0] = outFileheader.idlength;
tgaheaders[1] = outFileheader.colormaptype;
tgaheaders[2] = outFileheader.imagetype;
memcpy(tgaheaders + 3, &outMapspec.firstentry, 2);
memcpy(tgaheaders + 5, &outMapspec.length, 2);
tgaheaders[7] = outMapspec.entrysize;
memcpy(tgaheaders + 8, &outImagespec.xorigin, 2);
memcpy(tgaheaders + 10, &outImagespec.yorigin, 2);
memcpy(tgaheaders + 12, &outImagespec.width, 2);
memcpy(tgaheaders + 14, &outImagespec.height, 2);
tgaheaders[16] = outImagespec.depth;
tgaheaders[17] = outImagespec.descriptor;
ssize_t written;
written = outDestination->Write(tgaheaders, TGA_HEADERS_SIZE);
if (written == TGA_HEADERS_SIZE)
return B_OK;
else
return B_ERROR;
}
status_t
write_tga_footer(BPositionIO *outDestination)
{
const int32 kfootersize = 26;
uint8 footer[kfootersize];
memset(footer, 0, 8);
memcpy(footer + 8, "TRUEVISION-XFILE.", 18);
ssize_t written;
written = outDestination->Write(footer, kfootersize);
if (written == kfootersize)
return B_OK;
else
return B_ERROR;
}
status_t
TGATranslator::translate_from_bits(BPositionIO *inSource, uint32 outType,
BPositionIO *outDestination)
{
TranslatorBitmap bitsHeader;
bool bheaderonly = false, bdataonly = false, brle;
brle = fSettings->SetGetBool(TGA_SETTING_RLE);
status_t result;
result = identify_bits_header(inSource, NULL, &bitsHeader);
if (result != B_OK)
return result;
if (outType == B_TGA_FORMAT) {
TGAFileHeader fileheader;
fileheader.idlength = 0;
fileheader.colormaptype = TGA_NO_COLORMAP;
fileheader.imagetype = 0;
TGAColorMapSpec mapspec;
mapspec.firstentry = 0;
mapspec.length = 0;
mapspec.entrysize = 0;
TGAImageSpec imagespec;
imagespec.xorigin = 0;
imagespec.yorigin = 0;
imagespec.width = static_cast<uint16> (bitsHeader.bounds.Width() + 1);
imagespec.height = static_cast<uint16> (bitsHeader.bounds.Height() + 1);
imagespec.depth = 0;
imagespec.descriptor = TGA_ORIGIN_VERT_BIT;
switch (bitsHeader.colors) {
case B_RGBA32:
case B_RGBA32_BIG:
case B_CMYA32:
if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 32;
imagespec.descriptor |= 8;
break;
case B_RGB32:
case B_RGB32_BIG:
case B_RGB24:
case B_RGB24_BIG:
case B_CMYK32:
case B_CMY32:
case B_CMY24:
if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 24;
break;
case B_RGB16:
case B_RGB16_BIG:
if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 24;
break;
case B_RGB15:
case B_RGB15_BIG:
if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 16;
imagespec.descriptor |= 1;
break;
case B_RGBA15:
case B_RGBA15_BIG:
if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 16;
imagespec.descriptor |= 1;
break;
case B_CMAP8:
fileheader.colormaptype = TGA_COLORMAP;
if (brle)
fileheader.imagetype = TGA_RLE_COLORMAP;
else
fileheader.imagetype = TGA_NOCOMP_COLORMAP;
mapspec.firstentry = 0;
mapspec.length = 256;
mapspec.entrysize = 32;
imagespec.depth = 8;
imagespec.descriptor |= 8;
break;
case B_GRAY8:
case B_GRAY1:
if (brle)
fileheader.imagetype = TGA_RLE_BW;
else
fileheader.imagetype = TGA_NOCOMP_BW;
imagespec.depth = 8;
break;
default:
return B_NO_TRANSLATOR;
}
if (bheaderonly || (!bheaderonly && !bdataonly)) {
result = write_tga_headers(outDestination, fileheader,
mapspec, imagespec);
if (result != B_OK)
return result;
}
if (bheaderonly)
return result;
switch (bitsHeader.colors) {
case B_RGB32:
case B_RGB32_BIG:
case B_RGBA32:
case B_RGBA32_BIG:
case B_RGB24:
case B_RGB24_BIG:
case B_RGB16:
case B_RGB16_BIG:
case B_RGB15:
case B_RGB15_BIG:
case B_RGBA15:
case B_RGBA15_BIG:
case B_CMYK32:
case B_CMY32:
case B_CMYA32:
case B_CMY24:
result = translate_from_bits_to_tgatc(inSource, outDestination,
bitsHeader.colors, imagespec, brle);
break;
case B_CMAP8:
{
uint8 pal[1024];
const color_map *pmap = system_colors();
if (!pmap)
return B_ERROR;
for (int32 i = 0; i < 256; i++) {
uint8 *palent = pal + (i * 4);
rgb_color c = pmap->color_list[i];
palent[0] = c.blue;
palent[1] = c.green;
palent[2] = c.red;
palent[3] = c.alpha;
}
if (outDestination->Write(pal, 1024) != 1024)
return B_ERROR;
result = translate_from_bits_to_tgatc(inSource, outDestination,
B_GRAY8, imagespec, brle);
break;
}
case B_GRAY8:
result = translate_from_bits_to_tgatc(inSource, outDestination,
B_GRAY8, imagespec, brle);
break;
case B_GRAY1:
result = translate_from_bits1_to_tgabw(inSource, outDestination,
bitsHeader.rowBytes, imagespec, brle);
break;
default:
result = B_NO_TRANSLATOR;
break;
}
if (result == B_OK)
result = write_tga_footer(outDestination);
return result;
} else
return B_NO_TRANSLATOR;
}
status_t
pix_tganm_to_bits(uint8 *pbits, uint8 *ptga,
uint16 width, uint8 depth, uint8 tgaBytesPerPixel,
uint8 nalpha)
{
status_t result = B_OK;
switch (depth) {
case 32:
if (nalpha == 8 && tgaBytesPerPixel == 4)
memcpy(pbits, ptga, 4 * width);
else if (nalpha == 8) {
while (width--) {
memcpy(pbits, ptga, 4);
pbits += 4;
}
} else {
while (width--) {
memcpy(pbits, ptga, 3);
pbits += 4;
ptga += tgaBytesPerPixel;
}
}
break;
case 24:
while (width--) {
memcpy(pbits, ptga, 3);
pbits += 4;
ptga += tgaBytesPerPixel;
}
break;
case 16:
{
uint16 val;
if (nalpha == 1) {
while (width--) {
val = ptga[0] + (ptga[1] << 8);
pbits[0] =
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
pbits[1] =
((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
pbits[2] =
((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
pbits[3] = (val & 0x8000) ? 255 : 0;
pbits += 4;
ptga += tgaBytesPerPixel;
}
} else {
while (width--) {
val = ptga[0] + (ptga[1] << 8);
pbits[0] =
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
pbits[1] =
((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
pbits[2] =
((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
pbits += 4;
ptga += tgaBytesPerPixel;
}
}
break;
}
case 15:
{
uint16 val;
while (width--) {
val = ptga[0] + (ptga[1] << 8);
pbits[0] =
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
pbits[1] =
((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
pbits[2] =
((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
pbits += 4;
ptga += tgaBytesPerPixel;
}
break;
}
case 8:
while (width--) {
memset(pbits, ptga[0], 3);
pbits += 4;
ptga += tgaBytesPerPixel;
}
break;
default:
result = B_ERROR;
break;
}
return result;
}
status_t
TGATranslator::translate_from_tganm_to_bits(BPositionIO *inSource,
BPositionIO *outDestination, TGAFileHeader &filehead,
TGAColorMapSpec &mapspec, TGAImageSpec &imagespec)
{
bool bvflip;
if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
bvflip = false;
else
bvflip = true;
uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec);
int32 bitsRowBytes = imagespec.width * 4;
uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
((imagespec.depth % 8) ? 1 : 0);
int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel);
uint32 tgapixrow = 0;
off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
sizeof(TranslatorBitmap);
if (outDestination->SetSize(bitsFileSize) != B_OK)
return B_ERROR;
off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
if (bvflip)
outDestination->Seek(bitsoffset, SEEK_CUR);
uint8 *tgaRowData = new(std::nothrow) uint8[tgaRowBytes];
if (!tgaRowData)
return B_ERROR;
uint8 *bitsRowData = new(std::nothrow) uint8[bitsRowBytes];
if (!bitsRowData) {
delete[] tgaRowData;
tgaRowData = NULL;
return B_ERROR;
}
memset(bitsRowData, 0xff, bitsRowBytes);
ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes);
while (rd == tgaRowBytes) {
pix_tganm_to_bits(bitsRowData, tgaRowData,
imagespec.width, imagespec.depth,
tgaBytesPerPixel, nalpha);
outDestination->Write(bitsRowData, bitsRowBytes);
tgapixrow++;
if (tgapixrow == imagespec.height)
break;
if (bvflip)
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
rd = inSource->Read(tgaRowData, tgaRowBytes);
}
delete[] tgaRowData;
tgaRowData = NULL;
delete[] bitsRowData;
bitsRowData = NULL;
return B_OK;
}
status_t
TGATranslator::translate_from_tganmrle_to_bits(BPositionIO *inSource,
BPositionIO *outDestination, TGAFileHeader &filehead,
TGAColorMapSpec &mapspec, TGAImageSpec &imagespec)
{
status_t result = B_OK;
bool bvflip;
if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
bvflip = false;
else
bvflip = true;
uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec);
int32 bitsRowBytes = imagespec.width * 4;
uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
((imagespec.depth % 8) ? 1 : 0);
uint16 tgapixrow = 0, tgapixcol = 0;
off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
sizeof(TranslatorBitmap);
if (outDestination->SetSize(bitsFileSize) != B_OK)
return B_ERROR;
off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
if (bvflip)
outDestination->Seek(bitsoffset, SEEK_CUR);
uint8 *bitsRowData = new(std::nothrow) uint8[bitsRowBytes];
if (!bitsRowData)
return B_ERROR;
memset(bitsRowData, 0xff, bitsRowBytes);
uint8 *pbitspixel = bitsRowData;
uint8 packethead;
StreamBuffer sbuf(inSource, TGA_STREAM_BUFFER_SIZE);
ssize_t rd = 0;
if (sbuf.InitCheck() == B_OK)
rd = sbuf.Read(&packethead, 1);
while (rd == 1) {
if (packethead & TGA_RLE_PACKET_TYPE_BIT) {
uint8 tgapixel[4], rlecount;
rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
if (tgapixcol + rlecount > imagespec.width) {
result = B_NO_TRANSLATOR;
break;
}
rd = sbuf.Read(tgapixel, tgaBytesPerPixel);
if (rd == tgaBytesPerPixel) {
pix_tganm_to_bits(pbitspixel, tgapixel,
rlecount, imagespec.depth, 0, nalpha);
pbitspixel += 4 * rlecount;
tgapixcol += rlecount;
} else {
result = B_NO_TRANSLATOR;
break;
}
} else {
uint8 tgaPixelBuf[512], rawcount;
uint16 rawbytes;
rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
if (tgapixcol + rawcount > imagespec.width) {
result = B_NO_TRANSLATOR;
break;
}
rawbytes = tgaBytesPerPixel * rawcount;
rd = sbuf.Read(tgaPixelBuf, rawbytes);
if (rd == rawbytes) {
pix_tganm_to_bits(pbitspixel, tgaPixelBuf,
rawcount, imagespec.depth, tgaBytesPerPixel, nalpha);
pbitspixel += 4 * rawcount;
tgapixcol += rawcount;
} else {
result = B_NO_TRANSLATOR;
break;
}
}
if (tgapixcol == imagespec.width) {
outDestination->Write(bitsRowData, bitsRowBytes);
tgapixcol = 0;
tgapixrow++;
if (tgapixrow == imagespec.height)
break;
if (bvflip)
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
pbitspixel = bitsRowData;
}
rd = sbuf.Read(&packethead, 1);
}
delete[] bitsRowData;
bitsRowData = NULL;
return result;
}
status_t
pix_tgam_to_bits(uint8 *pbits, uint8 *ptgaindices,
uint16 width, uint8 depth, uint8 *pmap)
{
status_t result = B_OK;
uint8 *ptgapixel = NULL;
switch (depth) {
case 32:
for (uint16 i = 0; i < width; i++) {
ptgapixel = pmap +
(ptgaindices[i] * 4);
memcpy(pbits, ptgapixel, 4);
pbits += 4;
}
break;
case 24:
for (uint16 i = 0; i < width; i++) {
ptgapixel = pmap +
(ptgaindices[i] * 3);
memcpy(pbits, ptgapixel, 3);
pbits += 4;
}
break;
case 16:
for (uint16 i = 0; i < width; i++) {
uint16 val;
ptgapixel = pmap +
(ptgaindices[i] * 2);
val = ptgapixel[0] + (ptgapixel[1] << 8);
pbits[0] =
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
pbits[1] =
((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
pbits[2] =
((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
pbits[3] = (val & 0x8000) ? 255 : 0;
pbits += 4;
}
break;
case 15:
for (uint16 i = 0; i < width; i++) {
uint16 val;
ptgapixel = pmap +
(ptgaindices[i] * 2);
val = ptgapixel[0] + (ptgapixel[1] << 8);
pbits[0] =
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
pbits[1] =
((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
pbits[2] =
((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
pbits += 4;
}
break;
default:
result = B_ERROR;
break;
}
return result;
}
status_t
translate_from_tgam_to_bits(BPositionIO *inSource,
BPositionIO *outDestination, TGAColorMapSpec &mapspec,
TGAImageSpec &imagespec, uint8 *pmap)
{
bool bvflip;
if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
bvflip = false;
else
bvflip = true;
int32 bitsRowBytes = imagespec.width * 4;
uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
((imagespec.depth % 8) ? 1 : 0);
int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel);
uint32 tgapixrow = 0;
off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
sizeof(TranslatorBitmap);
if (outDestination->SetSize(bitsFileSize) != B_OK)
return B_ERROR;
off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
if (bvflip)
outDestination->Seek(bitsoffset, SEEK_CUR);
uint8 *tgaRowData = new(std::nothrow) uint8[tgaRowBytes];
if (!tgaRowData)
return B_ERROR;
uint8 *bitsRowData = new(std::nothrow) uint8[bitsRowBytes];
if (!bitsRowData) {
delete[] tgaRowData;
tgaRowData = NULL;
return B_ERROR;
}
memset(bitsRowData, 0xff, bitsRowBytes);
ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes);
while (rd == tgaRowBytes) {
pix_tgam_to_bits(bitsRowData, tgaRowData,
imagespec.width, mapspec.entrysize, pmap);
outDestination->Write(bitsRowData, bitsRowBytes);
tgapixrow++;
if (tgapixrow == imagespec.height)
break;
if (bvflip)
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
rd = inSource->Read(tgaRowData, tgaRowBytes);
}
delete[] tgaRowData;
tgaRowData = NULL;
delete[] bitsRowData;
bitsRowData = NULL;
return B_OK;
}
status_t
TGATranslator::translate_from_tgamrle_to_bits(BPositionIO *inSource,
BPositionIO *outDestination, TGAFileHeader &filehead,
TGAColorMapSpec &mapspec, TGAImageSpec &imagespec, uint8 *pmap)
{
status_t result = B_OK;
bool bvflip;
if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
bvflip = false;
else
bvflip = true;
uint8 nalpha = tga_alphabits(filehead, mapspec, imagespec);
int32 bitsRowBytes = imagespec.width * 4;
uint8 tgaPalBytesPerPixel = (mapspec.entrysize / 8) +
((mapspec.entrysize % 8) ? 1 : 0);
uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
((imagespec.depth % 8) ? 1 : 0);
uint16 tgapixrow = 0, tgapixcol = 0;
off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
sizeof(TranslatorBitmap);
if (outDestination->SetSize(bitsFileSize) != B_OK)
return B_ERROR;
off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
if (bvflip)
outDestination->Seek(bitsoffset, SEEK_CUR);
uint8 *bitsRowData = new(std::nothrow) uint8[bitsRowBytes];
if (!bitsRowData)
return B_ERROR;
memset(bitsRowData, 0xff, bitsRowBytes);
uint8 *pbitspixel = bitsRowData;
uint8 packethead;
StreamBuffer sbuf(inSource, TGA_STREAM_BUFFER_SIZE);
ssize_t rd = 0;
if (sbuf.InitCheck() == B_OK)
rd = sbuf.Read(&packethead, 1);
while (rd == 1) {
if (packethead & TGA_RLE_PACKET_TYPE_BIT) {
uint8 tgaindex, rlecount;
rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
if (tgapixcol + rlecount > imagespec.width) {
result = B_NO_TRANSLATOR;
break;
}
rd = sbuf.Read(&tgaindex, 1);
if (rd == tgaBytesPerPixel) {
uint8 *ptgapixel;
ptgapixel = pmap + (tgaindex * tgaPalBytesPerPixel);
pix_tganm_to_bits(pbitspixel, ptgapixel, rlecount,
mapspec.entrysize, 0, nalpha);
pbitspixel += 4 * rlecount;
tgapixcol += rlecount;
} else {
result = B_NO_TRANSLATOR;
break;
}
} else {
uint8 tgaIndexBuf[128], rawcount;
rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
if (tgapixcol + rawcount > imagespec.width) {
result = B_NO_TRANSLATOR;
break;
}
rd = sbuf.Read(tgaIndexBuf, rawcount);
if (rd == rawcount) {
pix_tgam_to_bits(pbitspixel, tgaIndexBuf,
rawcount, mapspec.entrysize, pmap);
pbitspixel += 4 * rawcount;
tgapixcol += rawcount;
} else {
result = B_NO_TRANSLATOR;
break;
}
}
if (tgapixcol == imagespec.width) {
outDestination->Write(bitsRowData, bitsRowBytes);
tgapixcol = 0;
tgapixrow++;
if (tgapixrow == imagespec.height)
break;
if (bvflip)
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
pbitspixel = bitsRowData;
}
rd = sbuf.Read(&packethead, 1);
}
delete[] bitsRowData;
bitsRowData = NULL;
return result;
}
status_t
TGATranslator::translate_from_tga(BPositionIO *inSource, uint32 outType,
BPositionIO *outDestination)
{
TGAFileHeader fileheader;
TGAColorMapSpec mapspec;
TGAImageSpec imagespec;
bool bheaderonly = false, bdataonly = false;
status_t result;
result = identify_tga_header(inSource, NULL, &fileheader, &mapspec,
&imagespec);
if (result != B_OK)
return result;
if (outType == B_TGA_FORMAT) {
if (bheaderonly || (!bheaderonly && !bdataonly)) {
result = write_tga_headers(outDestination, fileheader,
mapspec, imagespec);
if (result != B_OK)
return result;
}
if (bheaderonly)
return result;
const int32 kbuflen = 1024;
uint8 buf[kbuflen];
ssize_t rd = inSource->Read(buf, kbuflen);
while (rd > 0) {
outDestination->Write(buf, rd);
rd = inSource->Read(buf, kbuflen);
}
if (rd == 0)
return B_OK;
else
return B_ERROR;
} else if (outType == B_TRANSLATOR_BITMAP) {
TranslatorBitmap bitsHeader;
bitsHeader.magic = B_TRANSLATOR_BITMAP;
bitsHeader.bounds.left = 0;
bitsHeader.bounds.top = 0;
bitsHeader.bounds.right = imagespec.width - 1;
bitsHeader.bounds.bottom = imagespec.height - 1;
if (fileheader.idlength > 0)
inSource->Seek(fileheader.idlength, SEEK_CUR);
uint8 *ptgapalette = NULL;
if (fileheader.colormaptype == TGA_COLORMAP) {
uint32 nentrybytes;
nentrybytes = mapspec.entrysize / 8;
if (mapspec.entrysize % 8)
nentrybytes++;
ptgapalette = new(std::nothrow) uint8[nentrybytes * mapspec.length];
inSource->Read(ptgapalette, nentrybytes * mapspec.length);
}
bitsHeader.rowBytes = imagespec.width * 4;
if (fileheader.imagetype != TGA_NOCOMP_BW &&
fileheader.imagetype != TGA_RLE_BW &&
tga_alphabits(fileheader, mapspec, imagespec))
bitsHeader.colors = B_RGBA32;
else
bitsHeader.colors = B_RGB32;
int32 datasize = bitsHeader.rowBytes * imagespec.height;
bitsHeader.dataSize = datasize;
if (bheaderonly || (!bheaderonly && !bdataonly)) {
if (swap_data(B_UINT32_TYPE, &bitsHeader,
sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK)
return B_ERROR;
outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap));
}
if (bheaderonly)
return B_OK;
switch (fileheader.imagetype) {
case TGA_NOCOMP_TRUECOLOR:
case TGA_NOCOMP_BW:
result = translate_from_tganm_to_bits(inSource,
outDestination, fileheader, mapspec, imagespec);
break;
case TGA_NOCOMP_COLORMAP:
result = translate_from_tgam_to_bits(inSource,
outDestination, mapspec, imagespec, ptgapalette);
break;
case TGA_RLE_TRUECOLOR:
case TGA_RLE_BW:
result = translate_from_tganmrle_to_bits(inSource,
outDestination, fileheader, mapspec, imagespec);
break;
case TGA_RLE_COLORMAP:
result = translate_from_tgamrle_to_bits(inSource, outDestination,
fileheader, mapspec, imagespec, ptgapalette);
break;
default:
result = B_NO_TRANSLATOR;
break;
}
delete[] ptgapalette;
ptgapalette = NULL;
return result;
} else
return B_NO_TRANSLATOR;
}
status_t
TGATranslator::DerivedTranslate(BPositionIO *inSource,
const translator_info *inInfo, BMessage *ioExtension, uint32 outType,
BPositionIO *outDestination, int32 baseType)
{
if (baseType == 1)
return translate_from_bits(inSource, outType, outDestination);
else if (baseType == 0)
return translate_from_tga(inSource, outType, outDestination);
else
return B_NO_TRANSLATOR;
}
BView *
TGATranslator::NewConfigView(TranslatorSettings *settings)
{
return new(std::nothrow) TGAView(B_TRANSLATE("TGATranslator Settings"),
B_WILL_DRAW, settings);
}