added support for saving as RLE comrpessed TGA images for some types of Be Bitmap Images

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1303 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Matthew Wilber
2002-09-30 02:15:01 +00:00
parent 74708d31ce
commit 5d4da381b0
@@ -649,16 +649,18 @@ TGATranslator::Identify(BPositionIO *inSource,
status_t status_t
pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace, pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
uint16 width, const color_map *pmap) uint16 width, const color_map *pmap, int32 bitsBytesPerPixel)
{ {
status_t result = B_OK; status_t bytescopied = 0;
switch (fromspace) { switch (fromspace) {
case B_RGBA32: case B_RGBA32:
memcpy(ptga, pbits, width * 4); bytescopied = width * 4;
memcpy(ptga, pbits, bytescopied);
break; break;
case B_RGBA32_BIG: case B_RGBA32_BIG:
bytescopied = width * 4;
while (width--) { while (width--) {
ptga[0] = pbits[3]; ptga[0] = pbits[3];
ptga[1] = pbits[2]; ptga[1] = pbits[2];
@@ -671,6 +673,7 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
break; break;
case B_CMYA32: case B_CMYA32:
bytescopied = width * 4;
while (width--) { while (width--) {
ptga[0] = 255 - pbits[2]; ptga[0] = 255 - pbits[2];
ptga[1] = 255 - pbits[1]; ptga[1] = 255 - pbits[1];
@@ -684,25 +687,19 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
case B_RGB32: case B_RGB32:
case B_RGB24: case B_RGB24:
{ bytescopied = width * 3;
int32 bytes;
if (fromspace == B_RGB32)
bytes = 4;
else
bytes = 3;
while (width--) { while (width--) {
memcpy(ptga, pbits, 3); memcpy(ptga, pbits, 3);
ptga += 3; ptga += 3;
pbits += bytes; pbits += bitsBytesPerPixel;
} }
break; break;
}
case B_CMYK32: case B_CMYK32:
{ {
int32 comp; int32 comp;
bytescopied = width * 3;
while (width--) { while (width--) {
comp = 255 - pbits[2] - pbits[3]; comp = 255 - pbits[2] - pbits[3];
ptga[0] = (comp < 0) ? 0 : comp; ptga[0] = (comp < 0) ? 0 : comp;
@@ -721,23 +718,16 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
case B_CMY32: case B_CMY32:
case B_CMY24: case B_CMY24:
{ bytescopied = width * 3;
int32 bytes;
if (fromspace == B_CMY32)
bytes = 4;
else
bytes = 3;
while (width--) { while (width--) {
ptga[0] = 255 - pbits[2]; ptga[0] = 255 - pbits[2];
ptga[1] = 255 - pbits[1]; ptga[1] = 255 - pbits[1];
ptga[2] = 255 - pbits[0]; ptga[2] = 255 - pbits[0];
ptga += 3; ptga += 3;
pbits += bytes; pbits += bitsBytesPerPixel;
} }
break; break;
}
case B_RGB16: case B_RGB16:
case B_RGB16_BIG: case B_RGB16_BIG:
@@ -746,6 +736,7 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
// 16 bit images differently than the Be Image Format // 16 bit images differently than the Be Image Format
// which would cause a loss in quality // which would cause a loss in quality
uint16 val; uint16 val;
bytescopied = width * 3;
while (width--) { while (width--) {
if (fromspace == B_RGB16) if (fromspace == B_RGB16)
val = pbits[0] + (pbits[1] << 8); val = pbits[0] + (pbits[1] << 8);
@@ -766,10 +757,12 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
} }
case B_RGBA15: case B_RGBA15:
memcpy(ptga, pbits, 2 * width); bytescopied = width * 2;
memcpy(ptga, pbits, bytescopied);
break; break;
case B_RGBA15_BIG: case B_RGBA15_BIG:
bytescopied = width * 2;
while (width--) { while (width--) {
ptga[0] = pbits[1]; ptga[0] = pbits[1];
ptga[1] = pbits[0]; ptga[1] = pbits[0];
@@ -780,6 +773,7 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
break; break;
case B_RGB15: case B_RGB15:
bytescopied = width * 2;
while (width--) { while (width--) {
ptga[0] = pbits[0]; ptga[0] = pbits[0];
ptga[1] = pbits[1] | 0x80; ptga[1] = pbits[1] | 0x80;
@@ -791,6 +785,7 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
break; break;
case B_RGB15_BIG: case B_RGB15_BIG:
bytescopied = width * 2;
while (width--) { while (width--) {
ptga[0] = pbits[1]; ptga[0] = pbits[1];
ptga[1] = pbits[0] | 0x80; ptga[1] = pbits[0] | 0x80;
@@ -802,6 +797,7 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
break; break;
case B_RGB32_BIG: case B_RGB32_BIG:
bytescopied = width * 3;
while (width--) { while (width--) {
ptga[0] = pbits[3]; ptga[0] = pbits[3];
ptga[1] = pbits[2]; ptga[1] = pbits[2];
@@ -813,6 +809,7 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
break; break;
case B_RGB24_BIG: case B_RGB24_BIG:
bytescopied = width * 3;
while (width--) { while (width--) {
ptga[0] = pbits[2]; ptga[0] = pbits[2];
ptga[1] = pbits[1]; ptga[1] = pbits[1];
@@ -826,6 +823,7 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
case B_CMAP8: case B_CMAP8:
{ {
rgb_color c; rgb_color c;
bytescopied = width * 3;
while (width--) { while (width--) {
c = pmap->color_list[pbits[0]]; c = pmap->color_list[pbits[0]];
ptga[0] = c.blue; ptga[0] = c.blue;
@@ -839,6 +837,7 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
} }
case B_GRAY8: case B_GRAY8:
bytescopied = width * 3;
while (width--) { while (width--) {
ptga[0] = pbits[0]; ptga[0] = pbits[0];
ptga[1] = pbits[0]; ptga[1] = pbits[0];
@@ -850,12 +849,159 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
break; break;
default: default:
result = B_ERROR; bytescopied = B_ERROR;
break; break;
} // switch (fromspace) } // switch (fromspace)
return result; return bytescopied;
} }
status_t
copy_rle_packet(uint8 *ptga, uint32 pixel, uint8 count,
color_space fromspace, const color_map *pmap,
int32 bitsBytesPerPixel)
{
// copy packet header
// (made of type and count)
uint8 packethead = (count - 1) | 0x80;
memcpy(ptga, &packethead, 1);
ptga++;
return pix_bits_to_tga((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)
{
// copy packet header
// (made of type and count)
uint8 packethead = (count - 1);
memcpy(ptga, &packethead, 1);
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 keypixel = 0, pixel = 0;
uint16 nread = 0;
status_t result, bytescopied = 0;
uint8 *prawbuf, *praw;
prawbuf = new uint8[bitsBytesPerPixel * 128];
if (!prawbuf)
return B_ERROR;
memcpy(&keypixel, pbits, bitsBytesPerPixel);
pbits += bitsBytesPerPixel;
nread++;
// special case
if (width == 1) {
result = copy_raw_packet(ptga,
(uint8 *) &keypixel, 1, fromspace,
pmap, bitsBytesPerPixel);
ptga += result;
bytescopied += result;
}
uint8 count = 1;
while (nread < width) {
memcpy(&pixel, pbits, bitsBytesPerPixel);
pbits += bitsBytesPerPixel;
nread++;
//////
// RLE
//////
// Read while string of pixels is identical
while (keypixel == pixel && count < 128) {
count++;
if (nread == width)
break;
memcpy(&pixel, pbits, bitsBytesPerPixel);
pbits += bitsBytesPerPixel;
nread++;
}
// if there are some adjacent identical pixels
if (count > 1) {
result = copy_rle_packet(ptga, keypixel,
count, fromspace, pmap, bitsBytesPerPixel);
ptga += result;
bytescopied += result;
// If last pixel in row does not match
// with current RLE packet, write out
// RAW packet for the last pixel on the line
if (nread == width && keypixel != pixel) {
result = copy_raw_packet(ptga, (uint8 *) &pixel,
1, fromspace, pmap, bitsBytesPerPixel);
ptga += result;
bytescopied += result;
}
count = 1;
keypixel = pixel;
}
//////
// RAW
//////
praw = prawbuf;
memcpy(praw, &keypixel, bitsBytesPerPixel);
praw += bitsBytesPerPixel;
// Read while adjacent pixels do not match
while (keypixel != pixel && count < 128) {
memcpy(praw, &pixel, bitsBytesPerPixel);
praw += bitsBytesPerPixel;
count++;
if (nread == width)
break;
keypixel = pixel;
memcpy(&pixel, pbits, bitsBytesPerPixel);
pbits += bitsBytesPerPixel;
nread++;
}
if (count > 1) {
if (keypixel == pixel)
count--;
result = copy_raw_packet(ptga, prawbuf, count,
fromspace, pmap, bitsBytesPerPixel);
ptga += result;
bytescopied += result;
if (keypixel == pixel)
count = 2;
else {
count = 1;
keypixel = pixel;
}
}
}
delete[] prawbuf;
prawbuf = NULL;
return bytescopied;
}
// --------------------------------------------------------------- // ---------------------------------------------------------------
// translate_from_bits_to_tgatc // translate_from_bits_to_tgatc
// //
@@ -879,8 +1025,9 @@ pix_bits_to_tga(uint8 *pbits, uint8 *ptga, color_space fromspace,
// B_OK, if no errors occurred // B_OK, if no errors occurred
// --------------------------------------------------------------- // ---------------------------------------------------------------
status_t status_t
translate_from_bits_to_tgatc(BPositionIO *inSource, translate_from_bits_to_tgatc(BPositionIO *inSource,
BPositionIO *outDestination, color_space fromspace, TGAImageSpec &imagespec) BPositionIO *outDestination, color_space fromspace,
TGAImageSpec &imagespec, bool brle)
{ {
int32 bitsBytesPerPixel = 0; int32 bitsBytesPerPixel = 0;
switch (fromspace) { switch (fromspace) {
@@ -920,7 +1067,8 @@ BPositionIO *outDestination, color_space fromspace, TGAImageSpec &imagespec)
int32 bitsRowBytes = imagespec.width * bitsBytesPerPixel; int32 bitsRowBytes = imagespec.width * bitsBytesPerPixel;
uint8 tgaBytesPerPixel = (imagespec.depth / 8) + uint8 tgaBytesPerPixel = (imagespec.depth / 8) +
((imagespec.depth % 8) ? 1 : 0); ((imagespec.depth % 8) ? 1 : 0);
int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel); int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel) +
(imagespec.width / 128) + ((imagespec.width % 128) ? 1 : 0);
uint32 tgapixrow = 0; uint32 tgapixrow = 0;
uint8 *tgaRowData = new uint8[tgaRowBytes]; uint8 *tgaRowData = new uint8[tgaRowBytes];
if (!tgaRowData) if (!tgaRowData)
@@ -930,15 +1078,26 @@ BPositionIO *outDestination, color_space fromspace, TGAImageSpec &imagespec)
delete[] tgaRowData; delete[] tgaRowData;
return B_ERROR; return B_ERROR;
} }
// conversion function pointer, points to either
// RLE or normal TGA conversion function
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); ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes);
const color_map *pmap = system_colors(); const color_map *pmap = system_colors();
while (rd == bitsRowBytes) { while (rd == bitsRowBytes) {
status_t bytescopied;
pix_bits_to_tga(bitsRowData, tgaRowData, fromspace, bytescopied = convert_to_tga(bitsRowData, tgaRowData, fromspace,
imagespec.width, pmap); imagespec.width, pmap, bitsBytesPerPixel);
// convert bits row to tga row
outDestination->Write(tgaRowData, tgaRowBytes); outDestination->Write(tgaRowData, bytescopied);
tgapixrow++; tgapixrow++;
// if I've read all of the pixel data, break // if I've read all of the pixel data, break
// out of the loop so I don't try to read // out of the loop so I don't try to read
@@ -978,7 +1137,8 @@ BPositionIO *outDestination, color_space fromspace, TGAImageSpec &imagespec)
// --------------------------------------------------------------- // ---------------------------------------------------------------
status_t status_t
translate_from_bits8_to_tga8(BPositionIO *inSource, translate_from_bits8_to_tga8(BPositionIO *inSource,
BPositionIO *outDestination, int32 bitsRowBytes, uint16 height) BPositionIO *outDestination, int32 bitsRowBytes,
uint16 height, bool brle)
{ {
uint32 tgapixrow = 0; uint32 tgapixrow = 0;
uint8 *bitsRowData = new uint8[bitsRowBytes]; uint8 *bitsRowData = new uint8[bitsRowBytes];
@@ -1028,7 +1188,8 @@ translate_from_bits8_to_tga8(BPositionIO *inSource,
// --------------------------------------------------------------- // ---------------------------------------------------------------
status_t status_t
translate_from_bits1_to_tgabw(BPositionIO *inSource, translate_from_bits1_to_tgabw(BPositionIO *inSource,
BPositionIO *outDestination, int32 bitsRowBytes, TGAImageSpec &imagespec) BPositionIO *outDestination, int32 bitsRowBytes,
TGAImageSpec &imagespec, bool brle)
{ {
int32 tgaRowBytes = imagespec.width; int32 tgaRowBytes = imagespec.width;
uint32 tgapixrow = 0; uint32 tgapixrow = 0;
@@ -1222,7 +1383,7 @@ write_tga_footer(BPositionIO *outDestination)
// --------------------------------------------------------------- // ---------------------------------------------------------------
status_t status_t
translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read, translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
bool bheaderonly, bool bdataonly, uint32 outType, bool bheaderonly, bool bdataonly, bool brle, uint32 outType,
BPositionIO *outDestination) BPositionIO *outDestination)
{ {
TranslatorBitmap bitsHeader; TranslatorBitmap bitsHeader;
@@ -1288,7 +1449,10 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
case B_RGBA32: case B_RGBA32:
case B_RGBA32_BIG: case B_RGBA32_BIG:
case B_CMYA32: case B_CMYA32:
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 32; imagespec.depth = 32;
imagespec.descriptor |= 8; imagespec.descriptor |= 8;
// 8 bits of alpha // 8 bits of alpha
@@ -1302,7 +1466,10 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
case B_CMYK32: case B_CMYK32:
case B_CMY32: case B_CMY32:
case B_CMY24: case B_CMY24:
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 24; imagespec.depth = 24;
break; break;
@@ -1312,14 +1479,20 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
// image would result in loss of quality) // image would result in loss of quality)
case B_RGB16: case B_RGB16:
case B_RGB16_BIG: case B_RGB16_BIG:
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 24; imagespec.depth = 24;
break; break;
// Output to 15-bit True Color TGA (1 bit alpha) // Output to 15-bit True Color TGA (1 bit alpha)
case B_RGB15: case B_RGB15:
case B_RGB15_BIG: case B_RGB15_BIG:
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 16; imagespec.depth = 16;
imagespec.descriptor |= 1; imagespec.descriptor |= 1;
// 1 bit of alpha (always opaque) // 1 bit of alpha (always opaque)
@@ -1328,7 +1501,10 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
// Output to 16-bit True Color TGA (1 bit alpha) // Output to 16-bit True Color TGA (1 bit alpha)
case B_RGBA15: case B_RGBA15:
case B_RGBA15_BIG: case B_RGBA15_BIG:
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR; if (brle)
fileheader.imagetype = TGA_RLE_TRUECOLOR;
else
fileheader.imagetype = TGA_NOCOMP_TRUECOLOR;
imagespec.depth = 16; imagespec.depth = 16;
imagespec.descriptor |= 1; imagespec.descriptor |= 1;
// 1 bit of alpha // 1 bit of alpha
@@ -1337,7 +1513,10 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
// Output to 8-bit Color Mapped TGA 32 bits per color map entry // Output to 8-bit Color Mapped TGA 32 bits per color map entry
case B_CMAP8: case B_CMAP8:
fileheader.colormaptype = TGA_COLORMAP; fileheader.colormaptype = TGA_COLORMAP;
fileheader.imagetype = TGA_NOCOMP_COLORMAP; if (brle)
fileheader.imagetype = TGA_RLE_COLORMAP;
else
fileheader.imagetype = TGA_NOCOMP_COLORMAP;
mapspec.firstentry = 0; mapspec.firstentry = 0;
mapspec.length = 256; mapspec.length = 256;
mapspec.entrysize = 32; mapspec.entrysize = 32;
@@ -1349,7 +1528,10 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
// Output to 8-bit Black and White TGA // Output to 8-bit Black and White TGA
case B_GRAY8: case B_GRAY8:
case B_GRAY1: case B_GRAY1:
fileheader.imagetype = TGA_NOCOMP_BW; if (brle)
fileheader.imagetype = TGA_RLE_BW;
else
fileheader.imagetype = TGA_NOCOMP_BW;
imagespec.depth = 8; imagespec.depth = 8;
break; break;
@@ -1388,7 +1570,7 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
case B_CMYA32: case B_CMYA32:
case B_CMY24: case B_CMY24:
result = translate_from_bits_to_tgatc(inSource, outDestination, result = translate_from_bits_to_tgatc(inSource, outDestination,
bitsHeader.colors, imagespec); bitsHeader.colors, imagespec, brle);
break; break;
case B_CMAP8: case B_CMAP8:
@@ -1408,18 +1590,18 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
return B_ERROR; return B_ERROR;
result = translate_from_bits8_to_tga8(inSource, outDestination, result = translate_from_bits8_to_tga8(inSource, outDestination,
bitsHeader.rowBytes, imagespec.height); bitsHeader.rowBytes, imagespec.height, brle);
break; break;
} }
case B_GRAY8: case B_GRAY8:
result = translate_from_bits8_to_tga8(inSource, outDestination, result = translate_from_bits8_to_tga8(inSource, outDestination,
bitsHeader.rowBytes, imagespec.height); bitsHeader.rowBytes, imagespec.height, brle);
break; break;
case B_GRAY1: case B_GRAY1:
result = translate_from_bits1_to_tgabw(inSource, outDestination, result = translate_from_bits1_to_tgabw(inSource, outDestination,
bitsHeader.rowBytes, imagespec); bitsHeader.rowBytes, imagespec, brle);
break; break;
default: default:
@@ -1631,6 +1813,8 @@ status_t
translate_from_tganmrle_to_bits(BPositionIO *inSource, translate_from_tganmrle_to_bits(BPositionIO *inSource,
BPositionIO *outDestination, TGAImageSpec &imagespec) BPositionIO *outDestination, TGAImageSpec &imagespec)
{ {
status_t result = B_OK;
bool bvflip; bool bvflip;
if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
bvflip = false; bvflip = false;
@@ -1674,6 +1858,10 @@ translate_from_tganmrle_to_bits(BPositionIO *inSource,
if (packethead & TGA_RLE_PACKET_TYPE_BIT) { if (packethead & TGA_RLE_PACKET_TYPE_BIT) {
uint8 tgapixel[4], rlecount; uint8 tgapixel[4], rlecount;
rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
if (tgapixcol + rlecount > imagespec.width) {
result = B_NO_TRANSLATOR;
break;
}
rd = sbuf.Read(tgapixel, tgaBytesPerPixel); rd = sbuf.Read(tgapixel, tgaBytesPerPixel);
if (rd == tgaBytesPerPixel) { if (rd == tgaBytesPerPixel) {
pix_tganm_to_bits(pbitspixel, tgapixel, pix_tganm_to_bits(pbitspixel, tgapixel,
@@ -1681,14 +1869,20 @@ translate_from_tganmrle_to_bits(BPositionIO *inSource,
pbitspixel += 4 * rlecount; pbitspixel += 4 * rlecount;
tgapixcol += rlecount; tgapixcol += rlecount;
} else } else {
result = B_NO_TRANSLATOR;
break; // error break; // error
}
// Raw Packet // Raw Packet
} else { } else {
uint8 tgaPixelBuf[512], rawcount; uint8 tgaPixelBuf[512], rawcount;
uint16 rawbytes; uint16 rawbytes;
rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
if (tgapixcol + rawcount > imagespec.width) {
result = B_NO_TRANSLATOR;
break;
}
rawbytes = tgaBytesPerPixel * rawcount; rawbytes = tgaBytesPerPixel * rawcount;
rd = sbuf.Read(tgaPixelBuf, rawbytes); rd = sbuf.Read(tgaPixelBuf, rawbytes);
if (rd == rawbytes) { if (rd == rawbytes) {
@@ -1697,8 +1891,10 @@ translate_from_tganmrle_to_bits(BPositionIO *inSource,
pbitspixel += 4 * rawcount; pbitspixel += 4 * rawcount;
tgapixcol += rawcount; tgapixcol += rawcount;
} else } else {
result = B_NO_TRANSLATOR;
break; break;
}
} }
if (tgapixcol == imagespec.width) { if (tgapixcol == imagespec.width) {
@@ -1716,7 +1912,7 @@ translate_from_tganmrle_to_bits(BPositionIO *inSource,
delete[] bitsRowData; delete[] bitsRowData;
return B_OK; return result;
} }
status_t status_t
@@ -1884,6 +2080,8 @@ translate_from_tgamrle_to_bits(BPositionIO *inSource,
BPositionIO *outDestination, TGAColorMapSpec &mapspec, BPositionIO *outDestination, TGAColorMapSpec &mapspec,
TGAImageSpec &imagespec, uint8 *pmap) TGAImageSpec &imagespec, uint8 *pmap)
{ {
status_t result = B_OK;
bool bvflip; bool bvflip;
if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT) if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
bvflip = false; bvflip = false;
@@ -1940,6 +2138,10 @@ translate_from_tgamrle_to_bits(BPositionIO *inSource,
if (packethead & TGA_RLE_PACKET_TYPE_BIT) { if (packethead & TGA_RLE_PACKET_TYPE_BIT) {
uint8 tgaindex, rlecount; uint8 tgaindex, rlecount;
rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; rlecount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
if (tgapixcol + rlecount > imagespec.width) {
result = B_NO_TRANSLATOR;
break;
}
rd = sbuf.Read(&tgaindex, 1); rd = sbuf.Read(&tgaindex, 1);
if (rd == tgaBytesPerPixel) { if (rd == tgaBytesPerPixel) {
uint8 *ptgapixel; uint8 *ptgapixel;
@@ -1950,13 +2152,19 @@ translate_from_tgamrle_to_bits(BPositionIO *inSource,
pbitspixel += 4 * rlecount; pbitspixel += 4 * rlecount;
tgapixcol += rlecount; tgapixcol += rlecount;
} else } else {
result = B_NO_TRANSLATOR;
break; // error break; // error
}
// Raw Packet // Raw Packet
} else { } else {
uint8 tgaIndexBuf[128], rawcount; uint8 tgaIndexBuf[128], rawcount;
rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1; rawcount = (packethead & ~TGA_RLE_PACKET_TYPE_BIT) + 1;
if (tgapixcol + rawcount > imagespec.width) {
result = B_NO_TRANSLATOR;
break;
}
rd = sbuf.Read(tgaIndexBuf, rawcount); rd = sbuf.Read(tgaIndexBuf, rawcount);
if (rd == rawcount) { if (rd == rawcount) {
pix_tgam_to_bits(pbitspixel, tgaIndexBuf, pix_tgam_to_bits(pbitspixel, tgaIndexBuf,
@@ -1964,8 +2172,10 @@ translate_from_tgamrle_to_bits(BPositionIO *inSource,
pbitspixel += 4 * rawcount; pbitspixel += 4 * rawcount;
tgapixcol += rawcount; tgapixcol += rawcount;
} else } else {
result = B_NO_TRANSLATOR;
break; break;
}
} }
if (tgapixcol == imagespec.width) { if (tgapixcol == imagespec.width) {
@@ -1983,7 +2193,7 @@ translate_from_tgamrle_to_bits(BPositionIO *inSource,
delete[] bitsRowData; delete[] bitsRowData;
return B_OK; return result;
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -2024,7 +2234,7 @@ translate_from_tgamrle_to_bits(BPositionIO *inSource,
// --------------------------------------------------------------- // ---------------------------------------------------------------
status_t status_t
translate_from_tga(BPositionIO *inSource, ssize_t amtread, uint8 *read, translate_from_tga(BPositionIO *inSource, ssize_t amtread, uint8 *read,
bool bheaderonly, bool bdataonly, uint32 outType, bool bheaderonly, bool bdataonly, bool brle, uint32 outType,
BPositionIO *outDestination) BPositionIO *outDestination)
{ {
TGAFileHeader fileheader; TGAFileHeader fileheader;
@@ -2205,7 +2415,7 @@ TGATranslator::Translate(BPositionIO *inSource,
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
// Read settings from ioExtension // Read settings from ioExtension
bool bheaderonly = false, bdataonly = false; bool bheaderonly = false, bdataonly = false, brle = true;
if (ioExtension) { if (ioExtension) {
if (ioExtension->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderonly)) if (ioExtension->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &bheaderonly))
// if failed, make sure bool is default value // if failed, make sure bool is default value
@@ -2225,12 +2435,12 @@ TGATranslator::Translate(BPositionIO *inSource,
// if B_TRANSLATOR_BITMAP type // if B_TRANSLATOR_BITMAP type
if (n32ch == nbits) if (n32ch == nbits)
return translate_from_bits(inSource, 4, ch, bheaderonly, bdataonly, return translate_from_bits(inSource, 4, ch, bheaderonly, bdataonly,
outType, outDestination); brle, outType, outDestination);
// If NOT B_TRANSLATOR_BITMAP type, // If NOT B_TRANSLATOR_BITMAP type,
// it could be the TGA format // it could be the TGA format
else else
return translate_from_tga(inSource, 4, ch, bheaderonly, bdataonly, return translate_from_tga(inSource, 4, ch, bheaderonly, bdataonly,
outType, outDestination); brle, outType, outDestination);
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------