added capability to open 15, 16, 24 and 32 bit "true color" TGA images and 8-bit color mapped TGA images
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1052 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -50,7 +50,7 @@ translation_format gInputFormats[] = {
|
|||||||
TGA_IN_QUALITY,
|
TGA_IN_QUALITY,
|
||||||
TGA_IN_CAPABILITY,
|
TGA_IN_CAPABILITY,
|
||||||
"image/x-targa",
|
"image/x-targa",
|
||||||
"TGA image"
|
"Targa image"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ translation_format gOutputFormats[] = {
|
|||||||
TGA_OUT_QUALITY,
|
TGA_OUT_QUALITY,
|
||||||
TGA_OUT_CAPABILITY,
|
TGA_OUT_CAPABILITY,
|
||||||
"image/x-targa",
|
"image/x-targa",
|
||||||
"TGA image"
|
"Targa image"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -409,6 +409,12 @@ identify_tga_header(BPositionIO *inSource, translator_info *outInfo,
|
|||||||
if ((fileheader.imagetype > 3 && fileheader.imagetype < 9) ||
|
if ((fileheader.imagetype > 3 && fileheader.imagetype < 9) ||
|
||||||
fileheader.imagetype > 11)
|
fileheader.imagetype > 11)
|
||||||
return B_NO_TRANSLATOR;
|
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;
|
||||||
|
|
||||||
// Read in TGA color map spec
|
// Read in TGA color map spec
|
||||||
TGAColorMapSpec mapspec;
|
TGAColorMapSpec mapspec;
|
||||||
@@ -419,11 +425,20 @@ identify_tga_header(BPositionIO *inSource, translator_info *outInfo,
|
|||||||
|
|
||||||
memcpy(&mapspec.length, buf + 5, 2);
|
memcpy(&mapspec.length, buf + 5, 2);
|
||||||
mapspec.length = B_LENDIAN_TO_HOST_INT16(mapspec.length);
|
mapspec.length = B_LENDIAN_TO_HOST_INT16(mapspec.length);
|
||||||
if (fileheader.colormaptype == 0 && mapspec.length != 0)
|
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;
|
return B_NO_TRANSLATOR;
|
||||||
|
|
||||||
memcpy(&mapspec.entrysize, buf + 7, 1);
|
memcpy(&mapspec.entrysize, buf + 7, 1);
|
||||||
if (fileheader.colormaptype == 0 && mapspec.entrysize != 0)
|
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;
|
return B_NO_TRANSLATOR;
|
||||||
|
|
||||||
// Read in TGA image spec
|
// Read in TGA image spec
|
||||||
@@ -435,7 +450,7 @@ identify_tga_header(BPositionIO *inSource, translator_info *outInfo,
|
|||||||
imagespec.yorigin = B_LENDIAN_TO_HOST_INT16(imagespec.yorigin);
|
imagespec.yorigin = B_LENDIAN_TO_HOST_INT16(imagespec.yorigin);
|
||||||
|
|
||||||
memcpy(&imagespec.width, buf + 12, 2);
|
memcpy(&imagespec.width, buf + 12, 2);
|
||||||
imagespec.width = B_LENDIAN_TO_HOST_INT16(imagepsec.width);
|
imagespec.width = B_LENDIAN_TO_HOST_INT16(imagespec.width);
|
||||||
if (imagespec.width == 0)
|
if (imagespec.width == 0)
|
||||||
return B_NO_TRANSLATOR;
|
return B_NO_TRANSLATOR;
|
||||||
|
|
||||||
@@ -447,10 +462,48 @@ identify_tga_header(BPositionIO *inSource, translator_info *outInfo,
|
|||||||
memcpy(&imagespec.depth, buf + 16, 1);
|
memcpy(&imagespec.depth, buf + 16, 1);
|
||||||
if (imagespec.depth < 1 || imagespec.depth > 32)
|
if (imagespec.depth < 1 || imagespec.depth > 32)
|
||||||
return B_NO_TRANSLATOR;
|
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;
|
||||||
|
|
||||||
memcpy(&imagespec.descriptor, buf + 17, 1);
|
memcpy(&imagespec.descriptor, buf + 17, 1);
|
||||||
|
// images ordered from Right to Left (rather than Left to Right)
|
||||||
|
// are not supported
|
||||||
if (imagespec.descriptor & TGA_ORIGIN_HORZ_BIT == TGA_ORIGIN_RIGHT)
|
if (imagespec.descriptor & TGA_ORIGIN_HORZ_BIT == TGA_ORIGIN_RIGHT)
|
||||||
return B_NO_TRANSLATOR;
|
return B_NO_TRANSLATOR;
|
||||||
|
// unused descriptor bits, these bits must be zero
|
||||||
|
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;
|
||||||
|
|
||||||
// Fill in headers passed to this function
|
// Fill in headers passed to this function
|
||||||
if (pfileheader) {
|
if (pfileheader) {
|
||||||
@@ -471,6 +524,37 @@ identify_tga_header(BPositionIO *inSource, translator_info *outInfo,
|
|||||||
pimagespec->depth = imagespec.depth;
|
pimagespec->depth = imagespec.depth;
|
||||||
pimagespec->descriptor = imagespec.descriptor;
|
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;
|
||||||
|
sprintf(outInfo->name, "Targa image (%d bits",
|
||||||
|
imagespec.depth);
|
||||||
|
switch (fileheader.imagetype) {
|
||||||
|
case TGA_NOCOMP_COLORMAP:
|
||||||
|
strcat(outInfo->name, " colormap");
|
||||||
|
break;
|
||||||
|
case TGA_NOCOMP_TRUECOLOR:
|
||||||
|
strcat(outInfo->name, " truecolor");
|
||||||
|
break;
|
||||||
|
case TGA_NOCOMP_BW:
|
||||||
|
strcat(outInfo->name, " gray");
|
||||||
|
break;
|
||||||
|
case TGA_RLE_COLORMAP:
|
||||||
|
strcat(outInfo->name, " RLE colormap");
|
||||||
|
break;
|
||||||
|
case TGA_RLE_TRUECOLOR:
|
||||||
|
strcat(outInfo->name, " RLE truecolor");
|
||||||
|
break;
|
||||||
|
case TGA_RLE_BW:
|
||||||
|
strcat(outInfo->name, " RLE gray");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strcat(outInfo->name, ")");
|
||||||
|
strcpy(outInfo->MIME, "image/x-targa");
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -889,15 +973,14 @@ translate_from_bits1_to_tgabw(BPositionIO *inSource,
|
|||||||
ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes);
|
ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes);
|
||||||
while (rd == bitsRowBytes) {
|
while (rd == bitsRowBytes) {
|
||||||
uint32 tgapixcol = 0;
|
uint32 tgapixcol = 0;
|
||||||
for (int32 i = 0; (tgapixcol < msheader.width) &&
|
for (int32 i = 0; (tgapixcol < imagespec.width) &&
|
||||||
(i < bitsRowBytes); i++) {
|
(i < bitsRowBytes); i++) {
|
||||||
// process each byte in the row
|
// process each byte in the row
|
||||||
uint8 pixels = bitsRowData[i];
|
uint8 pixels = bitsRowData[i];
|
||||||
for (uint8 compbit = 128; (tgapixcol < msheader.width) &&
|
for (uint8 compbit = 128; (tgapixcol < imagespec.width) &&
|
||||||
compbit; compbit >>= 1) {
|
compbit; compbit >>= 1) {
|
||||||
// for each bit in the current byte, convert to a TGA palette
|
// for each bit in the current byte, convert to a TGA palette
|
||||||
// index and store that in the tgaRowData
|
// index and store that in the tgaRowData
|
||||||
uint8 index;
|
|
||||||
if (pixels & compbit)
|
if (pixels & compbit)
|
||||||
// black
|
// black
|
||||||
tgaRowData[tgapixcol] = 0;
|
tgaRowData[tgapixcol] = 0;
|
||||||
@@ -913,7 +996,7 @@ translate_from_bits1_to_tgabw(BPositionIO *inSource,
|
|||||||
// 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
|
||||||
// non-pixel data
|
// non-pixel data
|
||||||
if (tgapixrow == msheader.height)
|
if (tgapixrow == imagespec.height)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rd = inSource->Read(bitsRowData, bitsRowBytes);
|
rd = inSource->Read(bitsRowData, bitsRowBytes);
|
||||||
@@ -969,20 +1052,20 @@ write_tga_headers(BPositionIO *outDestination, TGAFileHeader &fileheader,
|
|||||||
|
|
||||||
// Copy TGA headers to buffer to be written out
|
// Copy TGA headers to buffer to be written out
|
||||||
// all at once
|
// all at once
|
||||||
memcpy(tgaheaders, outFileheader.idlength, 1);
|
memcpy(tgaheaders, &outFileheader.idlength, 1);
|
||||||
memcpy(tgaheaders + 1, outFileheader.colormaptype, 1);
|
memcpy(tgaheaders + 1, &outFileheader.colormaptype, 1);
|
||||||
memcpy(tgaheaders + 2, outFileheader.imagetype, 1);
|
memcpy(tgaheaders + 2, &outFileheader.imagetype, 1);
|
||||||
|
|
||||||
memcpy(tgaheaders + 3, outMapspec.firstentry, 2);
|
memcpy(tgaheaders + 3, &outMapspec.firstentry, 2);
|
||||||
memcpy(tgaheaders + 5, outMapspec.length, 2);
|
memcpy(tgaheaders + 5, &outMapspec.length, 2);
|
||||||
memcpy(tgaheaders + 7, outMapspec.entrysize, 1);
|
memcpy(tgaheaders + 7, &outMapspec.entrysize, 1);
|
||||||
|
|
||||||
memcpy(tgaheaders + 8, outImagespec.xorigin, 2);
|
memcpy(tgaheaders + 8, &outImagespec.xorigin, 2);
|
||||||
memcpy(tgaheaders + 10, outImagespec.yorigin, 2);
|
memcpy(tgaheaders + 10, &outImagespec.yorigin, 2);
|
||||||
memcpy(tgaheaders + 12, outImagespec.width, 2);
|
memcpy(tgaheaders + 12, &outImagespec.width, 2);
|
||||||
memcpy(tgaheaders + 14, outImagespec.height, 2);
|
memcpy(tgaheaders + 14, &outImagespec.height, 2);
|
||||||
memcpy(tgaheaders + 16, outImagespec.depth, 1);
|
memcpy(tgaheaders + 16, &outImagespec.depth, 1);
|
||||||
memcpy(tgaheaders + 17, outImagespec.descriptor, 1);
|
memcpy(tgaheaders + 17, &outImagespec.descriptor, 1);
|
||||||
|
|
||||||
ssize_t written;
|
ssize_t written;
|
||||||
written = outDestination->Write(tgaheaders, TGA_HEADERS_SIZE);
|
written = outDestination->Write(tgaheaders, TGA_HEADERS_SIZE);
|
||||||
@@ -1203,7 +1286,8 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
|
|||||||
|
|
||||||
// write out the TGA headers
|
// write out the TGA headers
|
||||||
if (bheaderonly || (!bheaderonly && !bdataonly)) {
|
if (bheaderonly || (!bheaderonly && !bdataonly)) {
|
||||||
result = write_tga_headers(outDestination, fileHeader, msheader);
|
result = write_tga_headers(outDestination, fileheader,
|
||||||
|
mapspec, imagespec);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1280,7 +1364,7 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// translate_from_tganpal_to_bits
|
// translate_from_tgatc_to_bits
|
||||||
//
|
//
|
||||||
// Translates a non-palette TGA from inSource to the B_RGB32
|
// Translates a non-palette TGA from inSource to the B_RGB32
|
||||||
// bits format.
|
// bits format.
|
||||||
@@ -1291,7 +1375,6 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
|
|||||||
//
|
//
|
||||||
// outDestination, where the bits data will be written to
|
// outDestination, where the bits data will be written to
|
||||||
//
|
//
|
||||||
// msheader, header information about the TGA to be written
|
|
||||||
//
|
//
|
||||||
// Postconditions:
|
// Postconditions:
|
||||||
//
|
//
|
||||||
@@ -1300,28 +1383,35 @@ translate_from_bits(BPositionIO *inSource, ssize_t amtread, uint8 *read,
|
|||||||
// B_OK, if all went well
|
// B_OK, if all went well
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
status_t
|
status_t
|
||||||
translate_from_tganpal_to_bits(BPositionIO *inSource,
|
translate_from_tgatc_to_bits(BPositionIO *inSource,
|
||||||
BPositionIO *outDestination, MSInfoHeader &msheader)
|
BPositionIO *outDestination, TGAImageSpec &imagespec)
|
||||||
{
|
{
|
||||||
int32 bitsRowBytes = msheader.width * 4;
|
bool bvflip;
|
||||||
int32 tgaBytesPerPixel = msheader.bitsperpixel / 8;
|
if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
|
||||||
int32 padding = (msheader.width * tgaBytesPerPixel) % 4;
|
bvflip = false;
|
||||||
if (padding)
|
else
|
||||||
padding = 4 - padding;
|
bvflip = true;
|
||||||
int32 tgaRowBytes = (msheader.width * tgaBytesPerPixel) + padding;
|
uint8 nalpha = imagespec.descriptor & TGA_DESC_ALPHABITS;
|
||||||
|
|
||||||
|
int32 bitsRowBytes = imagespec.width * 4;
|
||||||
|
int32 tgaBytesPerPixel = imagespec.depth / 8;
|
||||||
|
if (imagespec.depth % 8)
|
||||||
|
tgaBytesPerPixel++;
|
||||||
|
int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel);
|
||||||
uint32 tgapixrow = 0;
|
uint32 tgapixrow = 0;
|
||||||
|
|
||||||
// Setup outDestination so that it can be written to
|
// Setup outDestination so that it can be written to
|
||||||
// from the end of the file to the beginning instead of
|
// from the end of the file to the beginning instead of
|
||||||
// the other way around
|
// the other way around
|
||||||
off_t bitsFileSize = (bitsRowBytes * msheader.height) +
|
off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
|
||||||
sizeof(TranslatorBitmap);
|
sizeof(TranslatorBitmap);
|
||||||
if (outDestination->SetSize(bitsFileSize) != B_OK)
|
if (outDestination->SetSize(bitsFileSize) != B_OK)
|
||||||
// This call should work for BFile and BMallocIO objects,
|
// This call should work for BFile and BMallocIO objects,
|
||||||
// but may not work for other BPositionIO based types
|
// but may not work for other BPositionIO based types
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
off_t bitsoffset = (msheader.height - 1) * bitsRowBytes;
|
off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
|
||||||
outDestination->Seek(bitsoffset, SEEK_CUR);
|
if (bvflip)
|
||||||
|
outDestination->Seek(bitsoffset, SEEK_CUR);
|
||||||
|
|
||||||
// allocate row buffers
|
// allocate row buffers
|
||||||
uint8 *tgaRowData = new uint8[tgaRowBytes];
|
uint8 *tgaRowData = new uint8[tgaRowBytes];
|
||||||
@@ -1337,12 +1427,51 @@ translate_from_tganpal_to_bits(BPositionIO *inSource,
|
|||||||
memset(bitsRowData, 0xff, bitsRowBytes);
|
memset(bitsRowData, 0xff, bitsRowBytes);
|
||||||
ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes);
|
ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes);
|
||||||
while (rd == tgaRowBytes) {
|
while (rd == tgaRowBytes) {
|
||||||
uint8 *pBitsPixel = bitsRowData;
|
uint8 *pbitspixel = bitsRowData;
|
||||||
uint8 *pBmpPixel = tgaRowData;
|
uint8 *ptgapixel = tgaRowData;
|
||||||
for (uint32 i = 0; i < msheader.width; i++) {
|
uint16 val;
|
||||||
memcpy(pBitsPixel, pBmpPixel, 3);
|
for (uint32 i = 0; i < imagespec.width; i++) {
|
||||||
pBitsPixel += 4;
|
switch (imagespec.depth) {
|
||||||
pBmpPixel += tgaBytesPerPixel;
|
case 32:
|
||||||
|
if (nalpha == 8)
|
||||||
|
memcpy(pbitspixel, ptgapixel, 4);
|
||||||
|
else {
|
||||||
|
memcpy(pbitspixel, ptgapixel, 3);
|
||||||
|
pbitspixel[3] = 255;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
memcpy(pbitspixel, ptgapixel, 3);
|
||||||
|
pbitspixel[3] = 255;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
val = ptgapixel[0] + (ptgapixel[1] << 8);
|
||||||
|
pbitspixel[0] =
|
||||||
|
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
|
||||||
|
pbitspixel[1] =
|
||||||
|
((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
|
||||||
|
pbitspixel[2] =
|
||||||
|
((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
|
||||||
|
if (nalpha == 1)
|
||||||
|
pbitspixel[3] = (val & 0x8000) ? 255 : 0;
|
||||||
|
else
|
||||||
|
pbitspixel[3] = 255;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
val = ptgapixel[0] + (ptgapixel[1] << 8);
|
||||||
|
pbitspixel[0] =
|
||||||
|
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
|
||||||
|
pbitspixel[1] =
|
||||||
|
((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
|
||||||
|
pbitspixel[2] =
|
||||||
|
((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
|
||||||
|
pbitspixel[3] = 255;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pbitspixel += 4;
|
||||||
|
ptgapixel += tgaBytesPerPixel;
|
||||||
}
|
}
|
||||||
|
|
||||||
outDestination->Write(bitsRowData, bitsRowBytes);
|
outDestination->Write(bitsRowData, bitsRowBytes);
|
||||||
@@ -1350,10 +1479,11 @@ translate_from_tganpal_to_bits(BPositionIO *inSource,
|
|||||||
// 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
|
||||||
// non-pixel data
|
// non-pixel data
|
||||||
if (tgapixrow == msheader.height)
|
if (tgapixrow == imagespec.height)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
|
if (bvflip)
|
||||||
|
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
|
||||||
rd = inSource->Read(tgaRowData, tgaRowBytes);
|
rd = inSource->Read(tgaRowData, tgaRowBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1364,10 +1494,10 @@ translate_from_tganpal_to_bits(BPositionIO *inSource,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// translate_from_tgapal_to_bits
|
// translate_from_tgacm_to_bits
|
||||||
//
|
//
|
||||||
// Translates an uncompressed, palette TGA from inSource to
|
// Translates a non-palette TGA from inSource to the B_RGB32
|
||||||
// the B_RGB32 bits format.
|
// bits format.
|
||||||
//
|
//
|
||||||
// Preconditions:
|
// Preconditions:
|
||||||
//
|
//
|
||||||
@@ -1375,12 +1505,6 @@ translate_from_tganpal_to_bits(BPositionIO *inSource,
|
|||||||
//
|
//
|
||||||
// outDestination, where the bits data will be written to
|
// outDestination, where the bits data will be written to
|
||||||
//
|
//
|
||||||
// msheader, header information about the TGA to be written
|
|
||||||
//
|
|
||||||
// palette, TGA palette for the TGA image
|
|
||||||
//
|
|
||||||
// frommsformat, true if TGA in inSource is in MS format,
|
|
||||||
// false if it is in OS/2 format
|
|
||||||
//
|
//
|
||||||
// Postconditions:
|
// Postconditions:
|
||||||
//
|
//
|
||||||
@@ -1389,47 +1513,40 @@ translate_from_tganpal_to_bits(BPositionIO *inSource,
|
|||||||
// B_OK, if all went well
|
// B_OK, if all went well
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
status_t
|
status_t
|
||||||
translate_from_tgapal_to_bits(BPositionIO *inSource,
|
translate_from_tgacm_to_bits(BPositionIO *inSource,
|
||||||
BPositionIO *outDestination, MSInfoHeader &msheader,
|
BPositionIO *outDestination, TGAColorMapSpec &mapspec,
|
||||||
const uint8 *palette, bool frommsformat)
|
TGAImageSpec &imagespec, uint8 *pmap)
|
||||||
{
|
{
|
||||||
uint16 pixelsPerByte = 8 / msheader.bitsperpixel;
|
bool bvflip;
|
||||||
uint16 bitsPerPixel = msheader.bitsperpixel;
|
if (imagespec.descriptor & TGA_ORIGIN_VERT_BIT)
|
||||||
uint8 palBytesPerPixel;
|
bvflip = false;
|
||||||
if (frommsformat)
|
|
||||||
palBytesPerPixel = 4;
|
|
||||||
else
|
else
|
||||||
palBytesPerPixel = 3;
|
bvflip = true;
|
||||||
|
uint8 nalpha = imagespec.descriptor & TGA_DESC_ALPHABITS;
|
||||||
uint8 mask = 1;
|
|
||||||
mask = (mask << bitsPerPixel) - 1;
|
|
||||||
|
|
||||||
int32 padding;
|
|
||||||
if (!(msheader.width % pixelsPerByte))
|
|
||||||
padding = (msheader.width / pixelsPerByte) % 4;
|
|
||||||
else
|
|
||||||
padding = ((msheader.width + pixelsPerByte -
|
|
||||||
(msheader.width % pixelsPerByte)) / pixelsPerByte) % 4;
|
|
||||||
if (padding)
|
|
||||||
padding = 4 - padding;
|
|
||||||
|
|
||||||
int32 tgaRowBytes = (msheader.width / pixelsPerByte) +
|
int32 bitsRowBytes = imagespec.width * 4;
|
||||||
((msheader.width % pixelsPerByte) ? 1 : 0) + padding;
|
int32 tgaPalBytesPerPixel = mapspec.entrysize / 8;
|
||||||
|
if (mapspec.entrysize % 8)
|
||||||
|
tgaPalBytesPerPixel++;
|
||||||
|
int32 tgaBytesPerPixel = imagespec.depth / 8;
|
||||||
|
if (imagespec.depth % 8)
|
||||||
|
tgaBytesPerPixel++;
|
||||||
|
int32 tgaRowBytes = (imagespec.width * tgaBytesPerPixel);
|
||||||
uint32 tgapixrow = 0;
|
uint32 tgapixrow = 0;
|
||||||
|
|
||||||
// Setup outDestination so that it can be written to
|
// Setup outDestination so that it can be written to
|
||||||
// from the end of the file to the beginning instead of
|
// from the end of the file to the beginning instead of
|
||||||
// the other way around
|
// the other way around
|
||||||
int32 bitsRowBytes = msheader.width * 4;
|
off_t bitsFileSize = (bitsRowBytes * imagespec.height) +
|
||||||
off_t bitsFileSize = (bitsRowBytes * msheader.height) +
|
|
||||||
sizeof(TranslatorBitmap);
|
sizeof(TranslatorBitmap);
|
||||||
if (outDestination->SetSize(bitsFileSize) != B_OK)
|
if (outDestination->SetSize(bitsFileSize) != B_OK)
|
||||||
// This call should work for BFile and BMallocIO objects,
|
// This call should work for BFile and BMallocIO objects,
|
||||||
// but may not work for other BPositionIO based types
|
// but may not work for other BPositionIO based types
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
off_t bitsoffset = ((msheader.height - 1) * bitsRowBytes);
|
off_t bitsoffset = (imagespec.height - 1) * bitsRowBytes;
|
||||||
outDestination->Seek(bitsoffset, SEEK_CUR);
|
if (bvflip)
|
||||||
|
outDestination->Seek(bitsoffset, SEEK_CUR);
|
||||||
|
|
||||||
// allocate row buffers
|
// allocate row buffers
|
||||||
uint8 *tgaRowData = new uint8[tgaRowBytes];
|
uint8 *tgaRowData = new uint8[tgaRowBytes];
|
||||||
if (!tgaRowData)
|
if (!tgaRowData)
|
||||||
@@ -1439,17 +1556,56 @@ translate_from_tgapal_to_bits(BPositionIO *inSource,
|
|||||||
delete[] tgaRowData;
|
delete[] tgaRowData;
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// perform the actual translation
|
||||||
memset(bitsRowData, 0xff, bitsRowBytes);
|
memset(bitsRowData, 0xff, bitsRowBytes);
|
||||||
ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes);
|
ssize_t rd = inSource->Read(tgaRowData, tgaRowBytes);
|
||||||
while (rd == tgaRowBytes) {
|
while (rd == tgaRowBytes) {
|
||||||
for (uint32 i = 0; i < msheader.width; i++) {
|
uint8 *pbitspixel = bitsRowData;
|
||||||
uint8 indices = (tgaRowData + (i / pixelsPerByte))[0];
|
uint8 *ptgapixel = NULL;
|
||||||
uint8 index;
|
uint16 val;
|
||||||
index = (indices >>
|
for (uint32 i = 0; i < imagespec.width; i++) {
|
||||||
(bitsPerPixel * ((pixelsPerByte - 1) -
|
ptgapixel = pmap +
|
||||||
(i % pixelsPerByte)))) & mask;
|
(tgaRowData[i] * tgaPalBytesPerPixel);
|
||||||
memcpy(bitsRowData + (i * 4),
|
switch (mapspec.entrysize) {
|
||||||
palette + (index * palBytesPerPixel), 3);
|
case 32:
|
||||||
|
memcpy(pbitspixel, ptgapixel, 4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 24:
|
||||||
|
memcpy(pbitspixel, ptgapixel, 3);
|
||||||
|
pbitspixel[3] = 255;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
val = ptgapixel[0] + (ptgapixel[1] << 8);
|
||||||
|
pbitspixel[0] =
|
||||||
|
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
|
||||||
|
pbitspixel[1] =
|
||||||
|
((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
|
||||||
|
pbitspixel[2] =
|
||||||
|
((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
|
||||||
|
if (nalpha == 1)
|
||||||
|
pbitspixel[3] = (val & 0x8000) ? 255 : 0;
|
||||||
|
else
|
||||||
|
pbitspixel[3] = 255;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 15:
|
||||||
|
val = ptgapixel[0] + (ptgapixel[1] << 8);
|
||||||
|
pbitspixel[0] =
|
||||||
|
((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
|
||||||
|
pbitspixel[1] =
|
||||||
|
((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
|
||||||
|
pbitspixel[2] =
|
||||||
|
((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
|
||||||
|
pbitspixel[3] = 255;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pbitspixel += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
outDestination->Write(bitsRowData, bitsRowBytes);
|
outDestination->Write(bitsRowData, bitsRowBytes);
|
||||||
@@ -1457,10 +1613,11 @@ translate_from_tgapal_to_bits(BPositionIO *inSource,
|
|||||||
// 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
|
||||||
// non-pixel data
|
// non-pixel data
|
||||||
if (tgapixrow == msheader.height)
|
if (tgapixrow == imagespec.height)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
|
if (bvflip)
|
||||||
|
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
|
||||||
rd = inSource->Read(tgaRowData, tgaRowBytes);
|
rd = inSource->Read(tgaRowData, tgaRowBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1470,267 +1627,6 @@ translate_from_tgapal_to_bits(BPositionIO *inSource,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
// pixelcpy
|
|
||||||
//
|
|
||||||
// Copies count 32-bit pixels with a color value of pixel to dest.
|
|
||||||
//
|
|
||||||
// Preconditions:
|
|
||||||
//
|
|
||||||
// Parameters: dest, where the pixel data will be copied to
|
|
||||||
//
|
|
||||||
// pixel, the 32-bit color value to copy to dest
|
|
||||||
// count times
|
|
||||||
//
|
|
||||||
// count, the number of times pixel is copied to
|
|
||||||
// dest
|
|
||||||
//
|
|
||||||
// Postconditions:
|
|
||||||
//
|
|
||||||
// Returns:
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
void
|
|
||||||
pixelcpy(uint8 *dest, uint32 pixel, uint32 count)
|
|
||||||
{
|
|
||||||
for (uint32 i = 0; i < count; i++) {
|
|
||||||
memcpy(dest, &pixel, 3);
|
|
||||||
dest += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
// translate_from_tgapalr_to_bits
|
|
||||||
//
|
|
||||||
// Translates an RLE compressed, palette TGA from inSource to
|
|
||||||
// the B_RGB32 bits format. Currently, this code is not as
|
|
||||||
// memory effcient as it could be. It assumes that the TGA
|
|
||||||
// from inSource is relatively small.
|
|
||||||
//
|
|
||||||
// Preconditions:
|
|
||||||
//
|
|
||||||
// Parameters: inSource, the TGA data to be translated
|
|
||||||
//
|
|
||||||
// outDestination, where the bits data will be written to
|
|
||||||
//
|
|
||||||
// datasize, number of bytes of data needed for the bits output
|
|
||||||
//
|
|
||||||
// msheader, header information about the TGA to be written
|
|
||||||
//
|
|
||||||
// palette, TGA palette for data in inSource
|
|
||||||
//
|
|
||||||
// Postconditions:
|
|
||||||
//
|
|
||||||
// Returns: B_ERROR, if there is an error allocating memory
|
|
||||||
//
|
|
||||||
// B_OK, if all went well
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
status_t
|
|
||||||
translate_from_tgapalr_to_bits(BPositionIO *inSource,
|
|
||||||
BPositionIO *outDestination, int32 datasize, MSInfoHeader &msheader,
|
|
||||||
const uint8 *palette)
|
|
||||||
{
|
|
||||||
uint16 pixelsPerByte = 8 / msheader.bitsperpixel;
|
|
||||||
uint16 bitsPerPixel = msheader.bitsperpixel;
|
|
||||||
uint8 mask = (1 << bitsPerPixel) - 1;
|
|
||||||
|
|
||||||
uint8 count, indices, index;
|
|
||||||
// Setup outDestination so that it can be written to
|
|
||||||
// from the end of the file to the beginning instead of
|
|
||||||
// the other way around
|
|
||||||
int32 bitsRowBytes = msheader.width * 4;
|
|
||||||
off_t bitsFileSize = (bitsRowBytes * msheader.height) +
|
|
||||||
sizeof(TranslatorBitmap);
|
|
||||||
if (outDestination->SetSize(bitsFileSize) != B_OK)
|
|
||||||
// This call should work for BFile and BMallocIO objects,
|
|
||||||
// but may not work for other BPositionIO based types
|
|
||||||
return B_ERROR;
|
|
||||||
uint8 *bitsRowData = new uint8[bitsRowBytes];
|
|
||||||
if (!bitsRowData)
|
|
||||||
return B_ERROR;
|
|
||||||
memset(bitsRowData, 0xff, bitsRowBytes);
|
|
||||||
uint32 tgapixcol = 0, tgapixrow = 0;
|
|
||||||
uint32 defaultcolor = 0;
|
|
||||||
memcpy(&defaultcolor, palette, 4);
|
|
||||||
// set bits output to last row in the image
|
|
||||||
off_t bitsoffset = ((msheader.height - (tgapixrow + 1)) * bitsRowBytes) +
|
|
||||||
(tgapixcol * 4);
|
|
||||||
outDestination->Seek(bitsoffset, SEEK_CUR);
|
|
||||||
ssize_t rd = inSource->Read(&count, 1);
|
|
||||||
while (rd > 0) {
|
|
||||||
// repeated color
|
|
||||||
if (count) {
|
|
||||||
// abort if all of the pixels in the row
|
|
||||||
// have already been drawn to
|
|
||||||
if (tgapixcol == msheader.width) {
|
|
||||||
rd = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// if count is greater than the number of
|
|
||||||
// pixels remaining in the current row,
|
|
||||||
// only process the correct number of pixels
|
|
||||||
// remaining in the row
|
|
||||||
if (count + tgapixcol > msheader.width)
|
|
||||||
count = msheader.width - tgapixcol;
|
|
||||||
|
|
||||||
rd = inSource->Read(&indices, 1);
|
|
||||||
if (rd != 1) {
|
|
||||||
rd = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (uint8 i = 0; i < count; i++) {
|
|
||||||
index = (indices >> (bitsPerPixel * ((pixelsPerByte - 1) -
|
|
||||||
(i % pixelsPerByte)))) & mask;
|
|
||||||
memcpy(bitsRowData + (tgapixcol*4), palette + (index*4), 3);
|
|
||||||
tgapixcol++;
|
|
||||||
}
|
|
||||||
// special code
|
|
||||||
} else {
|
|
||||||
uint8 code;
|
|
||||||
rd = inSource->Read(&code, 1);
|
|
||||||
if (rd != 1) {
|
|
||||||
rd = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (code) {
|
|
||||||
// end of line
|
|
||||||
case 0:
|
|
||||||
// if there are columns remaing on this
|
|
||||||
// line, set them to the color at index zero
|
|
||||||
if (tgapixcol < msheader.width)
|
|
||||||
pixelcpy(bitsRowData + (tgapixcol * 4),
|
|
||||||
defaultcolor, msheader.width - tgapixcol);
|
|
||||||
outDestination->Write(bitsRowData, bitsRowBytes);
|
|
||||||
tgapixcol = 0;
|
|
||||||
tgapixrow++;
|
|
||||||
if (tgapixrow < msheader.height)
|
|
||||||
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// end of bitmap
|
|
||||||
case 1:
|
|
||||||
// if at the end of a row
|
|
||||||
if (tgapixcol == msheader.width) {
|
|
||||||
outDestination->Write(bitsRowData, bitsRowBytes);
|
|
||||||
tgapixcol = 0;
|
|
||||||
tgapixrow++;
|
|
||||||
if (tgapixrow < msheader.height)
|
|
||||||
outDestination->Seek(-(bitsRowBytes * 2),
|
|
||||||
SEEK_CUR);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (tgapixrow < msheader.height) {
|
|
||||||
pixelcpy(bitsRowData + (tgapixcol * 4), defaultcolor,
|
|
||||||
msheader.width - tgapixcol);
|
|
||||||
outDestination->Write(bitsRowData, bitsRowBytes);
|
|
||||||
tgapixcol = 0;
|
|
||||||
tgapixrow++;
|
|
||||||
if (tgapixrow < msheader.height)
|
|
||||||
outDestination->Seek(-(bitsRowBytes * 2),
|
|
||||||
SEEK_CUR);
|
|
||||||
}
|
|
||||||
rd = 0;
|
|
||||||
// break out of while loop
|
|
||||||
break;
|
|
||||||
|
|
||||||
// delta, skip several rows and/or columns and
|
|
||||||
// fill the skipped pixels with the default color
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
uint8 da[2], lastcol, dx, dy;
|
|
||||||
rd = inSource->Read(da, 2);
|
|
||||||
if (rd != 2) {
|
|
||||||
rd = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dx = da[0];
|
|
||||||
dy = da[1];
|
|
||||||
|
|
||||||
// abort if dx or dy is too large
|
|
||||||
if ((dx + tgapixcol >= msheader.width) ||
|
|
||||||
(dy + tgapixrow >= msheader.height)) {
|
|
||||||
rd = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastcol = tgapixcol;
|
|
||||||
|
|
||||||
// set all pixels to the first entry in
|
|
||||||
// the palette, for the number of rows skipped
|
|
||||||
while (dy > 0) {
|
|
||||||
pixelcpy(bitsRowData + (tgapixcol * 4), defaultcolor,
|
|
||||||
msheader.width - tgapixcol);
|
|
||||||
outDestination->Write(bitsRowData, bitsRowBytes);
|
|
||||||
tgapixcol = 0;
|
|
||||||
tgapixrow++;
|
|
||||||
dy--;
|
|
||||||
outDestination->Seek(-(bitsRowBytes * 2), SEEK_CUR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tgapixcol < (uint32) lastcol + dx) {
|
|
||||||
pixelcpy(bitsRowData + (tgapixcol * 4), defaultcolor,
|
|
||||||
dx + lastcol - tgapixcol);
|
|
||||||
tgapixcol = dx + lastcol;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// code >= 3
|
|
||||||
// read code uncompressed indices
|
|
||||||
default:
|
|
||||||
// abort if all of the pixels in the row
|
|
||||||
// have already been drawn to
|
|
||||||
if (tgapixcol == msheader.width) {
|
|
||||||
rd = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// if code is greater than the number of
|
|
||||||
// pixels remaining in the current row,
|
|
||||||
// only process the correct number of pixels
|
|
||||||
// remaining in the row
|
|
||||||
if (code + tgapixcol > msheader.width)
|
|
||||||
code = msheader.width - tgapixcol;
|
|
||||||
|
|
||||||
uint8 uncomp[256];
|
|
||||||
int32 padding;
|
|
||||||
if (!(code % pixelsPerByte))
|
|
||||||
padding = (code / pixelsPerByte) % 2;
|
|
||||||
else
|
|
||||||
padding = ((code + pixelsPerByte -
|
|
||||||
(code % pixelsPerByte)) / pixelsPerByte) % 2;
|
|
||||||
int32 uncompBytes = (code / pixelsPerByte) +
|
|
||||||
((code % pixelsPerByte) ? 1 : 0) + padding;
|
|
||||||
rd = inSource->Read(uncomp, uncompBytes);
|
|
||||||
if (rd != uncompBytes) {
|
|
||||||
rd = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (uint8 i = 0; i < code; i++) {
|
|
||||||
indices = (uncomp + (i / pixelsPerByte))[0];
|
|
||||||
index = (indices >>
|
|
||||||
(bitsPerPixel * ((pixelsPerByte - 1) -
|
|
||||||
(i % pixelsPerByte)))) & mask;
|
|
||||||
memcpy(bitsRowData + (tgapixcol * 4),
|
|
||||||
palette + (index * 4), 3);
|
|
||||||
tgapixcol++;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rd > 0)
|
|
||||||
rd = inSource->Read(&count, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] bitsRowData;
|
|
||||||
|
|
||||||
if (!rd)
|
|
||||||
return B_OK;
|
|
||||||
else
|
|
||||||
return B_NO_TRANSLATOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// translate_from_tga
|
// translate_from_tga
|
||||||
//
|
//
|
||||||
@@ -1772,14 +1668,13 @@ translate_from_tga(BPositionIO *inSource, ssize_t amtread, uint8 *read,
|
|||||||
bool bheaderonly, bool bdataonly, uint32 outType,
|
bool bheaderonly, bool bdataonly, uint32 outType,
|
||||||
BPositionIO *outDestination)
|
BPositionIO *outDestination)
|
||||||
{
|
{
|
||||||
TGAFileHeader fileHeader;
|
TGAFileHeader fileheader;
|
||||||
MSInfoHeader msheader;
|
TGAColorMapSpec mapspec;
|
||||||
bool frommsformat;
|
TGAImageSpec imagespec;
|
||||||
off_t os2skip = 0;
|
|
||||||
|
|
||||||
status_t result;
|
status_t result;
|
||||||
result = identify_tga_header(inSource, NULL, amtread, read,
|
result = identify_tga_header(inSource, NULL, amtread, read,
|
||||||
&fileHeader, &msheader, &frommsformat, &os2skip);
|
&fileheader, &mapspec, &imagespec);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -1787,7 +1682,8 @@ translate_from_tga(BPositionIO *inSource, ssize_t amtread, uint8 *read,
|
|||||||
if (outType == B_TGA_FORMAT) {
|
if (outType == B_TGA_FORMAT) {
|
||||||
// write out the TGA headers
|
// write out the TGA headers
|
||||||
if (bheaderonly || (!bheaderonly && !bdataonly)) {
|
if (bheaderonly || (!bheaderonly && !bdataonly)) {
|
||||||
result = write_tga_headers(outDestination, fileHeader, msheader);
|
result = write_tga_headers(outDestination, fileheader,
|
||||||
|
mapspec, imagespec);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1797,33 +1693,9 @@ translate_from_tga(BPositionIO *inSource, ssize_t amtread, uint8 *read,
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
uint8 buf[1024];
|
uint8 buf[1024];
|
||||||
ssize_t rd;
|
ssize_t rd = inSource->Read(buf, rd);
|
||||||
uint32 rdtotal = 54;
|
|
||||||
if (!frommsformat && (msheader.bitsperpixel == 1 ||
|
|
||||||
msheader.bitsperpixel == 4 || msheader.bitsperpixel == 8)) {
|
|
||||||
// if OS/2 paletted format, convert palette to MS format
|
|
||||||
uint16 ncolors = 1 << msheader.bitsperpixel;
|
|
||||||
rd = inSource->Read(buf, ncolors * 3);
|
|
||||||
if (rd != ncolors * 3)
|
|
||||||
return B_NO_TRANSLATOR;
|
|
||||||
uint8 mspalent[4] = {0, 0, 0, 0};
|
|
||||||
for (uint16 i = 0; i < ncolors; i++) {
|
|
||||||
memcpy(mspalent, buf + (i * 3), 3);
|
|
||||||
outDestination->Write(mspalent, 4);
|
|
||||||
}
|
|
||||||
rdtotal = fileHeader.dataOffset;
|
|
||||||
}
|
|
||||||
// if there is junk between the OS/2 headers and
|
|
||||||
// the actual data, skip it
|
|
||||||
if (!frommsformat && os2skip)
|
|
||||||
inSource->Seek(os2skip, SEEK_CUR);
|
|
||||||
|
|
||||||
rd = min(1024, fileHeader.fileSize - rdtotal);
|
|
||||||
rd = inSource->Read(buf, rd);
|
|
||||||
while (rd > 0) {
|
while (rd > 0) {
|
||||||
outDestination->Write(buf, rd);
|
outDestination->Write(buf, rd);
|
||||||
rdtotal += rd;
|
|
||||||
rd = min(1024, fileHeader.fileSize - rdtotal);
|
|
||||||
rd = inSource->Read(buf, rd);
|
rd = inSource->Read(buf, rd);
|
||||||
}
|
}
|
||||||
if (rd == 0)
|
if (rd == 0)
|
||||||
@@ -1837,48 +1709,30 @@ translate_from_tga(BPositionIO *inSource, ssize_t amtread, uint8 *read,
|
|||||||
bitsHeader.magic = B_TRANSLATOR_BITMAP;
|
bitsHeader.magic = B_TRANSLATOR_BITMAP;
|
||||||
bitsHeader.bounds.left = 0;
|
bitsHeader.bounds.left = 0;
|
||||||
bitsHeader.bounds.top = 0;
|
bitsHeader.bounds.top = 0;
|
||||||
bitsHeader.bounds.right = msheader.width - 1;
|
bitsHeader.bounds.right = imagespec.width - 1;
|
||||||
bitsHeader.bounds.bottom = msheader.height - 1;
|
bitsHeader.bounds.bottom = imagespec.height - 1;
|
||||||
|
|
||||||
|
// skip over Image ID data (if present)
|
||||||
|
if (fileheader.idlength > 0)
|
||||||
|
inSource->Seek(fileheader.idlength, SEEK_CUR);
|
||||||
|
|
||||||
// read in palette and/or skip non-TGA data
|
// read in palette and/or skip non-TGA data
|
||||||
uint8 tgapalette[1024];
|
uint8 *ptgapalette = NULL;
|
||||||
off_t nskip = 0;
|
if (fileheader.colormaptype == TGA_COLORMAP) {
|
||||||
if (msheader.bitsperpixel == 1 ||
|
uint32 nentrybytes;
|
||||||
msheader.bitsperpixel == 4 ||
|
nentrybytes = mapspec.entrysize / 8;
|
||||||
msheader.bitsperpixel == 8) {
|
if (mapspec.entrysize % 8)
|
||||||
|
nentrybytes++;
|
||||||
uint8 palBytesPerPixel;
|
ptgapalette = new uint8[nentrybytes * mapspec.length];
|
||||||
if (frommsformat)
|
inSource->Read(ptgapalette, nentrybytes * mapspec.length);
|
||||||
palBytesPerPixel = 4;
|
}
|
||||||
else
|
|
||||||
palBytesPerPixel = 3;
|
|
||||||
|
|
||||||
if (!msheader.colorsused)
|
|
||||||
msheader.colorsused = 1 << msheader.bitsperpixel;
|
|
||||||
|
|
||||||
if (inSource->Read(tgapalette, msheader.colorsused *
|
|
||||||
palBytesPerPixel) !=
|
|
||||||
(off_t) msheader.colorsused * palBytesPerPixel)
|
|
||||||
return B_NO_TRANSLATOR;
|
|
||||||
|
|
||||||
// skip over non-TGA data
|
|
||||||
if (frommsformat) {
|
|
||||||
if (fileHeader.dataOffset > (msheader.colorsused *
|
|
||||||
palBytesPerPixel) + 54)
|
|
||||||
nskip = fileHeader.dataOffset -
|
|
||||||
((msheader.colorsused * palBytesPerPixel) + 54);
|
|
||||||
} else
|
|
||||||
nskip = os2skip;
|
|
||||||
} else if (fileHeader.dataOffset > 54)
|
|
||||||
// skip over non-TGA data
|
|
||||||
nskip = fileHeader.dataOffset - 54;
|
|
||||||
|
|
||||||
if (nskip > 0 && inSource->Seek(nskip, SEEK_CUR) < 0)
|
|
||||||
return B_NO_TRANSLATOR;
|
|
||||||
|
|
||||||
bitsHeader.rowBytes = msheader.width * 4;
|
bitsHeader.rowBytes = imagespec.width * 4;
|
||||||
bitsHeader.colors = B_RGB32;
|
if (imagespec.descriptor & TGA_DESC_ALPHABITS)
|
||||||
int32 datasize = bitsHeader.rowBytes * msheader.height;
|
bitsHeader.colors = B_RGBA32;
|
||||||
|
else
|
||||||
|
bitsHeader.colors = B_RGB32;
|
||||||
|
int32 datasize = bitsHeader.rowBytes * imagespec.height;
|
||||||
bitsHeader.dataSize = datasize;
|
bitsHeader.dataSize = datasize;
|
||||||
|
|
||||||
// write out Be's Bitmap header
|
// write out Be's Bitmap header
|
||||||
@@ -1894,46 +1748,29 @@ translate_from_tga(BPositionIO *inSource, ssize_t amtread, uint8 *read,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
// write out the actual image data
|
// write out the actual image data
|
||||||
switch (msheader.bitsperpixel) {
|
switch (fileheader.imagetype) {
|
||||||
case 32:
|
case TGA_NOCOMP_TRUECOLOR:
|
||||||
case 24:
|
result = translate_from_tgatc_to_bits(inSource,
|
||||||
return translate_from_tganpal_to_bits(inSource,
|
outDestination, imagespec);
|
||||||
outDestination, msheader);
|
break;
|
||||||
|
|
||||||
|
case TGA_NOCOMP_COLORMAP:
|
||||||
|
result = translate_from_tgacm_to_bits(inSource,
|
||||||
|
outDestination, mapspec, imagespec, ptgapalette);
|
||||||
|
break;
|
||||||
|
|
||||||
case 8:
|
|
||||||
// 8 bit TGA with NO compression
|
|
||||||
if (msheader.compression == TGA_NO_COMPRESS)
|
|
||||||
return translate_from_tgapal_to_bits(inSource,
|
|
||||||
outDestination, msheader, tgapalette, frommsformat);
|
|
||||||
|
|
||||||
// 8 bit RLE compressed TGA
|
|
||||||
else if (msheader.compression == TGA_RLE8_COMPRESS)
|
|
||||||
return translate_from_tgapalr_to_bits(inSource,
|
|
||||||
outDestination, datasize, msheader, tgapalette);
|
|
||||||
else
|
|
||||||
return B_NO_TRANSLATOR;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
// 4 bit TGA with NO compression
|
|
||||||
if (!msheader.compression)
|
|
||||||
return translate_from_tgapal_to_bits(inSource,
|
|
||||||
outDestination, msheader, tgapalette, frommsformat);
|
|
||||||
|
|
||||||
// 4 bit RLE compressed TGA
|
|
||||||
else if (msheader.compression == TGA_RLE4_COMPRESS)
|
|
||||||
return translate_from_tgapalr_to_bits(inSource,
|
|
||||||
outDestination, datasize, msheader, tgapalette);
|
|
||||||
else
|
|
||||||
return B_NO_TRANSLATOR;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
return translate_from_tgapal_to_bits(inSource,
|
|
||||||
outDestination, msheader, tgapalette, frommsformat);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return B_NO_TRANSLATOR;
|
result = B_NO_TRANSLATOR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ptgapalette) {
|
||||||
|
delete[] ptgapalette;
|
||||||
|
ptgapalette = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
return B_NO_TRANSLATOR;
|
return B_NO_TRANSLATOR;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user