Added support for more Be Bitmap types and cleaned up code in general

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@415 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Matthew Wilber
2002-07-24 03:09:13 +00:00
parent 3f6453cd59
commit 817a47b050
@@ -132,7 +132,7 @@ const translation_format *BMPTranslator::OutputFormats(int32 *out_count) const
} }
status_t identify_bits_header(BPositionIO *inSource, translator_info *outInfo, status_t identify_bits_header(BPositionIO *inSource, translator_info *outInfo,
ssize_t amtread, char *read) ssize_t amtread, uint8 *read)
{ {
TranslatorBitmap header; TranslatorBitmap header;
@@ -140,7 +140,7 @@ status_t identify_bits_header(BPositionIO *inSource, translator_info *outInfo,
// copy portion of header already read in // copy portion of header already read in
// read in the rest of the header // read in the rest of the header
ssize_t size = sizeof(TranslatorBitmap) - amtread; ssize_t size = sizeof(TranslatorBitmap) - amtread;
if (inSource->Read(((char *) &header) + amtread, size) != size) if (inSource->Read(((uint8 *) &header) + amtread, size) != size)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
// convert to host byte order // convert to host byte order
@@ -150,14 +150,24 @@ status_t identify_bits_header(BPositionIO *inSource, translator_info *outInfo,
// check if header values are reasonable // check if header values are reasonable
if (header.colors != B_RGB32 && if (header.colors != B_RGB32 &&
header.colors != B_RGB32_BIG &&
header.colors != B_RGBA32 && header.colors != B_RGBA32 &&
header.colors != B_RGBA32_BIG &&
header.colors != B_RGB24 && header.colors != B_RGB24 &&
header.colors != B_RGB24_BIG &&
header.colors != B_RGB16 && header.colors != B_RGB16 &&
header.colors != B_RGB16_BIG &&
header.colors != B_RGB15 && header.colors != B_RGB15 &&
header.colors != B_RGB15_BIG &&
header.colors != B_RGBA15 && header.colors != B_RGBA15 &&
header.colors != B_RGBA15_BIG &&
header.colors != B_CMAP8 && header.colors != B_CMAP8 &&
header.colors != B_GRAY8 && header.colors != B_GRAY8 &&
header.colors != B_GRAY1) header.colors != B_GRAY1 &&
header.colors != B_CMYK32 &&
header.colors != B_CMY32 &&
header.colors != B_CMYA32 &&
header.colors != B_CMY24)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
if (header.rowBytes * (header.bounds.Height() + 1) > header.dataSize) if (header.rowBytes * (header.bounds.Height() + 1) > header.dataSize)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
@@ -173,9 +183,9 @@ status_t identify_bits_header(BPositionIO *inSource, translator_info *outInfo,
} }
status_t identify_bmp_header(BPositionIO *inSource, translator_info *outInfo, status_t identify_bmp_header(BPositionIO *inSource, translator_info *outInfo,
ssize_t amtread, char *read) ssize_t amtread, uint8 *read)
{ {
char buf[40]; uint8 buf[40];
BMPFileHeader fileHeader; BMPFileHeader fileHeader;
memcpy(buf, read, amtread); memcpy(buf, read, amtread);
@@ -193,7 +203,7 @@ status_t identify_bmp_header(BPositionIO *inSource, translator_info *outInfo,
if (swap_data(B_UINT16_TYPE, &fileHeader.magic, sizeof(uint16), if (swap_data(B_UINT16_TYPE, &fileHeader.magic, sizeof(uint16),
B_SWAP_LENDIAN_TO_HOST) != B_OK) B_SWAP_LENDIAN_TO_HOST) != B_OK)
return B_ERROR; return B_ERROR;
if (swap_data(B_UINT32_TYPE, ((char *) &fileHeader) + 2, 12, if (swap_data(B_UINT32_TYPE, ((uint8 *) &fileHeader) + 2, 12,
B_SWAP_LENDIAN_TO_HOST) != B_OK) B_SWAP_LENDIAN_TO_HOST) != B_OK)
return B_ERROR; return B_ERROR;
@@ -242,7 +252,7 @@ status_t BMPTranslator::Identify(BPositionIO *inSource,
if (outType != B_TRANSLATOR_BITMAP && outType != B_BMP_FORMAT) if (outType != B_TRANSLATOR_BITMAP && outType != B_BMP_FORMAT)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
char ch[4]; uint8 ch[4];
uint32 nbits = B_TRANSLATOR_BITMAP; uint32 nbits = B_TRANSLATOR_BITMAP;
uint16 nbm = 'MB'; uint16 nbm = 'MB';
@@ -273,8 +283,169 @@ status_t BMPTranslator::Identify(BPositionIO *inSource,
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
} }
// for converting uncompressed BMP images with no palette to the Be Bitmap format
status_t translate_from_bits32_to_bmp(BPositionIO *inSource, BPositionIO *outDestination,
color_space fromspace, BMPInfoHeader &infoHeader)
{
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;
default:
return B_ERROR;
}
int32 bitsRowBytes = infoHeader.width * bitsBytesPerPixel;
int32 bmpBytesPerPixel = infoHeader.bitsperpixel / 8;
int32 padding = (infoHeader.width * bmpBytesPerPixel) % 4;
if (padding)
padding = 4 - padding;
int32 bmpRowBytes = (infoHeader.width * bmpBytesPerPixel) + padding;
uint32 bmppixrow = 0;
off_t bitsoffset = ((infoHeader.height - 1) * bitsRowBytes);
inSource->Seek(bitsoffset, SEEK_CUR);
uint8 *bmpRowData = new uint8[bmpRowBytes];
if (!bmpRowData)
return B_ERROR;
uint8 *bitsRowData = new uint8[bitsRowBytes];
if (!bitsRowData) {
delete[] bmpRowData;
return B_ERROR;
}
memset(bmpRowData, 0, bmpRowBytes);
ssize_t rd = inSource->Read(bitsRowData, bitsRowBytes);
while (rd == bitsRowBytes) {
for (uint32 i = 0; i < infoHeader.width; i++) {
uint8 *bitspixel, *bmppixel;
uint16 val;
switch (fromspace) {
case B_RGB32:
case B_RGBA32:
case B_RGB24:
memcpy(bmpRowData + (i * 3),
bitsRowData + (i * bitsBytesPerPixel), 3);
break;
case B_RGB16:
case B_RGB16_BIG:
bitspixel = bitsRowData + (i * bitsBytesPerPixel);
bmppixel = bmpRowData + (i * 3);
if (fromspace == B_RGB16)
val = bitspixel[0] + (bitspixel[1] << 8);
else
val = bitspixel[1] + (bitspixel[1] << 8);
bmppixel[0] = ((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
bmppixel[1] = ((val & 0x7e0) >> 3) | ((val & 0x7e0) >> 9);
bmppixel[2] = ((val & 0xf800) >> 8) | ((val & 0xf800) >> 13);
break;
case B_RGB15:
case B_RGB15_BIG:
case B_RGBA15:
case B_RGBA15_BIG:
// NOTE: the alpha data for B_RGBA15 is ignored and discarded
bitspixel = bitsRowData + (i * bitsBytesPerPixel);
bmppixel = bmpRowData + (i * 3);
if (fromspace == B_RGB15 || fromspace == B_RGBA15)
val = bitspixel[0] + (bitspixel[1] << 8);
else
val = bitspixel[1] + (bitspixel[0] << 8);
bmppixel[0] = ((val & 0x1f) << 3) | ((val & 0x1f) >> 2);
bmppixel[1] = ((val & 0x3e0) >> 2) | ((val & 0x3e0) >> 7);
bmppixel[2] = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
break;
case B_RGB32_BIG:
case B_RGBA32_BIG:
bitspixel = bitsRowData + (i * bitsBytesPerPixel);
bmppixel = bmpRowData + (i * 3);
bmppixel[0] = bitspixel[3];
bmppixel[1] = bitspixel[2];
bmppixel[2] = bitspixel[1];
break;
case B_RGB24_BIG:
bitspixel = bitsRowData + (i * bitsBytesPerPixel);
bmppixel = bmpRowData + (i * 3);
bmppixel[0] = bitspixel[2];
bmppixel[1] = bitspixel[1];
bmppixel[2] = bitspixel[0];
break;
case B_CMYK32:
{
bitspixel = bitsRowData + (i * bitsBytesPerPixel);
bmppixel = bmpRowData + (i * 3);
int32 comp = 255 - bitspixel[2] - bitspixel[3];
bmppixel[0] = (comp < 0) ? 0 : comp;
comp = 255 - bitspixel[1] - bitspixel[3];
bmppixel[1] = (comp < 0) ? 0 : comp;
comp = 255 - bitspixel[0] - bitspixel[3];
bmppixel[2] = (comp < 0) ? 0 : comp;
break;
}
case B_CMY32:
case B_CMYA32:
case B_CMY24:
bitspixel = bitsRowData + (i * bitsBytesPerPixel);
bmppixel = bmpRowData + (i * 3);
bmppixel[0] = 255 - bitspixel[2];
bmppixel[1] = 255 - bitspixel[1];
bmppixel[2] = 255 - bitspixel[0];
break;
default:
break;
} // switch (fromspace)
} // for for (uint32 i = 0; i < infoHeader.width; i++)
outDestination->Write(bmpRowData, bmpRowBytes);
bmppixrow++;
// if I've read all of the pixel data, break
// out of the loop so I don't try to read
// non-pixel data
if (bmppixrow == infoHeader.height)
break;
inSource->Seek(-(bitsRowBytes * 2), SEEK_CUR);
rd = inSource->Read(bitsRowData, bitsRowBytes);
} // while (rd == bitsRowBytes)
delete[] bmpRowData;
delete[] bitsRowData;
return B_OK;
}
status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread, status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
char *read, uint32 outType, BPositionIO *outDestination) uint8 *read, uint32 outType, BPositionIO *outDestination)
{ {
TranslatorBitmap bitsHeader; TranslatorBitmap bitsHeader;
@@ -282,7 +453,7 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
// copy portion of bitsHeader already read in // copy portion of bitsHeader already read in
// read in the rest of the bitsHeader // read in the rest of the bitsHeader
ssize_t size = sizeof(TranslatorBitmap) - amtread; ssize_t size = sizeof(TranslatorBitmap) - amtread;
if (inSource->Read(((char *) &bitsHeader) + amtread, size) != size) if (inSource->Read(((uint8 *) &bitsHeader) + amtread, size) != size)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
// convert to host byte order // convert to host byte order
@@ -292,14 +463,24 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
// check if bitsHeader values are reasonable // check if bitsHeader values are reasonable
if (bitsHeader.colors != B_RGB32 && if (bitsHeader.colors != B_RGB32 &&
bitsHeader.colors != B_RGB32_BIG &&
bitsHeader.colors != B_RGBA32 && bitsHeader.colors != B_RGBA32 &&
bitsHeader.colors != B_RGBA32_BIG &&
bitsHeader.colors != B_RGB24 && bitsHeader.colors != B_RGB24 &&
bitsHeader.colors != B_RGB24_BIG &&
bitsHeader.colors != B_RGB16 && bitsHeader.colors != B_RGB16 &&
bitsHeader.colors != B_RGB16_BIG &&
bitsHeader.colors != B_RGB15 && bitsHeader.colors != B_RGB15 &&
bitsHeader.colors != B_RGB15_BIG &&
bitsHeader.colors != B_RGBA15 && bitsHeader.colors != B_RGBA15 &&
bitsHeader.colors != B_RGBA15_BIG &&
bitsHeader.colors != B_CMAP8 && bitsHeader.colors != B_CMAP8 &&
bitsHeader.colors != B_GRAY8 && bitsHeader.colors != B_GRAY8 &&
bitsHeader.colors != B_GRAY1) bitsHeader.colors != B_GRAY1 &&
bitsHeader.colors != B_CMYK32 &&
bitsHeader.colors != B_CMY32 &&
bitsHeader.colors != B_CMYA32 &&
bitsHeader.colors != B_CMY24)
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
if (bitsHeader.rowBytes * (bitsHeader.bounds.Height() + 1) > if (bitsHeader.rowBytes * (bitsHeader.bounds.Height() + 1) >
bitsHeader.dataSize) bitsHeader.dataSize)
@@ -315,7 +496,7 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
sizeof(TranslatorBitmap)) != sizeof(TranslatorBitmap)) sizeof(TranslatorBitmap)) != sizeof(TranslatorBitmap))
return B_ERROR; return B_ERROR;
char buf[1024]; uint8 buf[1024];
ssize_t rd = inSource->Read(buf, 1024); ssize_t rd = inSource->Read(buf, 1024);
while (rd > 0) { while (rd > 0) {
outDestination->Write(buf, rd); outDestination->Write(buf, rd);
@@ -349,8 +530,21 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
// determine fileSize / imagesize // determine fileSize / imagesize
switch (bitsHeader.colors) { switch (bitsHeader.colors) {
case B_RGB32: case B_RGB32:
case B_RGB32_BIG:
case B_RGBA32: case B_RGBA32:
case B_RGBA32_BIG:
case B_RGB24: 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:
infoHeader.bitsperpixel = 24; infoHeader.bitsperpixel = 24;
infoHeader.compression = BMP_NO_COMPRESS; infoHeader.compression = BMP_NO_COMPRESS;
@@ -369,7 +563,7 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
} }
// write out the BMP headers // write out the BMP headers
char bmpheaders[54]; uint8 bmpheaders[54];
memcpy(bmpheaders, &fileHeader.magic, sizeof(uint16)); memcpy(bmpheaders, &fileHeader.magic, sizeof(uint16));
memcpy(bmpheaders + 2, &fileHeader.fileSize, sizeof(uint32)); memcpy(bmpheaders + 2, &fileHeader.fileSize, sizeof(uint32));
memcpy(bmpheaders + 6, &fileHeader.reserved, sizeof(uint32)); memcpy(bmpheaders + 6, &fileHeader.reserved, sizeof(uint32));
@@ -388,52 +582,37 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
return B_ERROR; return B_ERROR;
// write out the BMP pixel data // write out the BMP pixel data
char *bmppixels = new char[infoHeader.imagesize];
if (!bmppixels)
return B_ERROR;
switch (bitsHeader.colors) { switch (bitsHeader.colors) {
case B_RGB32: case B_RGB32:
char bitspixel[4]; case B_RGB32_BIG:
int32 bytesperline = (infoHeader.width * 3) + padding; case B_RGBA32:
int32 bitspixoffset = 0; case B_RGBA32_BIG:
ssize_t bitsoffset = 0; case B_RGB24:
ssize_t rd = inSource->Read(bitspixel, 4); case B_RGB24_BIG:
while (rd > 0) { case B_RGB16:
int32 bmpoffset = ((infoHeader.height - case B_RGB16_BIG:
((bitsoffset / bitsHeader.rowBytes) + 1)) * case B_RGB15:
bytesperline) + (bitspixoffset * 3); case B_RGB15_BIG:
memcpy(bmppixels + bmpoffset, bitspixel, 3); case B_RGBA15:
case B_RGBA15_BIG:
case B_CMYK32:
case B_CMY32:
case B_CMYA32:
case B_CMY24:
translate_from_bits32_to_bmp(inSource, outDestination,
bitsHeader.colors, infoHeader);
break;
bitspixoffset++; default:
bitsoffset += rd;
if (!(bitsoffset % bitsHeader.rowBytes)) {
bitspixoffset = 0;
// put padding at the end of the line
if (padding) {
char chpadding[4] = { 0, 0, 0, 0 };
memcpy(bmppixels + bmpoffset + 3, chpadding,
padding);
}
// after I've read the entire bitmap, make sure to bail
if (bitsoffset / bitsHeader.rowBytes ==
infoHeader.height)
break; break;
} }
rd = inSource->Read(bitspixel, 4);
}
outDestination->Write(bmppixels, infoHeader.imagesize);
break;
}
delete[] bmppixels;
return B_OK; return B_OK;
} else } else
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
} }
// for converting uncompressed BMP images with no palette to the Be Bitmap format
status_t translate_from_bmpnpal_to_bits(BPositionIO *inSource, BPositionIO *outDestination, status_t translate_from_bmpnpal_to_bits(BPositionIO *inSource, BPositionIO *outDestination,
int32 datasize, BMPInfoHeader &infoHeader) int32 datasize, BMPInfoHeader &infoHeader)
{ {
@@ -446,10 +625,10 @@ status_t translate_from_bmpnpal_to_bits(BPositionIO *inSource, BPositionIO *outD
uint32 bmppixrow = 0; uint32 bmppixrow = 0;
off_t bmpoffset = ((infoHeader.height - 1) * bmpRowBytes); off_t bmpoffset = ((infoHeader.height - 1) * bmpRowBytes);
inSource->Seek(bmpoffset, SEEK_CUR); inSource->Seek(bmpoffset, SEEK_CUR);
char *bmpRowData = new char[bmpRowBytes]; uint8 *bmpRowData = new uint8[bmpRowBytes];
if (!bmpRowData) if (!bmpRowData)
return B_ERROR; return B_ERROR;
char *bitsRowData = new char[bitsRowBytes]; uint8 *bitsRowData = new uint8[bitsRowBytes];
if (!bitsRowData) { if (!bitsRowData) {
delete[] bmpRowData; delete[] bmpRowData;
return B_ERROR; return B_ERROR;
@@ -479,334 +658,15 @@ status_t translate_from_bmpnpal_to_bits(BPositionIO *inSource, BPositionIO *outD
return B_OK; return B_OK;
} }
status_t translate_from_bmp8r_to_bits(BPositionIO *inSource, BPositionIO *outDestination, // for converting palette-based uncompressed BMP images to the Be Bitmap format
int32 datasize, BMPInfoHeader &infoHeader, const char *palette)
{
uint8 count, index;
char *bitspixels = new char[datasize];
if (!bitspixels)
return B_ERROR;
memset(bitspixels, 0xffffffff, datasize);
int32 bitsRowBytes = infoHeader.width * 4;
uint32 bmppixcol = 0, bmppixrow = 0;
int32 bitsoffset = 0;
ssize_t rd = inSource->Read(&count, 1);
while (rd > 0) {
// repeated color
if (count) {
rd = inSource->Read(&index, 1);
if (rd != 1)
break;
for (uint8 i = 0; i < count; i++) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) * bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette + (index * 4), 3);
bmppixcol++;
}
// special code
} else {
uint8 code;
rd = inSource->Read(&code, 1);
if (rd != 1)
break;
switch (code) {
case 0:
// end of line
// if there are columns remaing on this
// line, set them to the color at index zero
while (bmppixcol != infoHeader.width) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
}
bmppixcol = 0;
bmppixrow++;
break;
case 1:
// end of bitmap
if (bmppixcol == infoHeader.width) {
bmppixcol = 0;
bmppixrow++;
}
while (bmppixrow < infoHeader.height) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
if (bmppixcol == infoHeader.width) {
bmppixcol = 0;
bmppixrow++;
}
}
rd = 0;
// break out of while loop
break;
case 2:
{
// delta, wierd feature
uint8 x, dx, dy;
inSource->Read(&dx, 1);
inSource->Read(&dy, 1);
x = bmppixcol;
// set all pixels to the first entry in
// the palette, for the number of rows skipped
while (dy > 0) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
if (bmppixcol == infoHeader.width) {
bmppixcol = 0;
bmppixrow++;
dy--;
}
}
// get to the same column as where we started
while (x != bmppixcol) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
}
// move over dx pixels
for (uint8 i = 0; i < dx; i++) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
}
break;
}
// code >= 3
default:
// read code uncompressed pixels
for (uint8 i = 0; i < code; i++) {
rd = inSource->Read(&index, 1);
if (rd != 1)
break;
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset,
palette + (index * 4), 3);
bmppixcol++;
}
// if odd number, there is junk padding
if (code % 2)
rd = inSource->Seek(1, SEEK_CUR);
break;
}
}
if (rd > 0)
rd = inSource->Read(&count, 1);
}
outDestination->Write(bitspixels, datasize);
delete[] bitspixels;
return B_OK;
}
status_t translate_from_bmp4r_to_bits(BPositionIO *inSource, BPositionIO *outDestination,
int32 datasize, BMPInfoHeader &infoHeader, const char *palette)
{
uint8 count, indices, index;
char *bitspixels = new char[datasize];
if (!bitspixels)
return B_ERROR;
memset(bitspixels, 0xffffffff, datasize);
int32 bitsRowBytes = infoHeader.width * 4;
uint32 bmppixcol = 0, bmppixrow = 0;
int32 bitsoffset = 0;
ssize_t rd = inSource->Read(&count, 1);
while (rd > 0) {
// repeated color
if (count) {
rd = inSource->Read(&indices, 1);
if (rd != 1)
break;
for (uint8 i = 0; i < count; i++) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) * bitsRowBytes) +
(bmppixcol * 4);
if (!(i % 2))
index = (indices>>4) & 0xf;
else
index = indices & 0xf;
memcpy(bitspixels + bitsoffset, palette + (index * 4), 3);
bmppixcol++;
}
// special code
} else {
uint8 code;
rd = inSource->Read(&code, 1);
if (rd != 1)
break;
switch (code) {
case 0:
// end of line
// if there are columns remaing on this
// line, set them to the color at index zero
while (bmppixcol != infoHeader.width) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
}
bmppixcol = 0;
bmppixrow++;
break;
case 1:
// end of bitmap
if (bmppixcol == infoHeader.width) {
bmppixcol = 0;
bmppixrow++;
}
while (bmppixrow < infoHeader.height) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
if (bmppixcol == infoHeader.width) {
bmppixcol = 0;
bmppixrow++;
}
}
rd = 0;
// break out of while loop
break;
case 2:
{
// delta, wierd feature
uint8 x, dx, dy;
inSource->Read(&dx, 1);
inSource->Read(&dy, 1);
x = bmppixcol;
// set all pixels to the first entry in
// the palette, for the number of rows skipped
while (dy > 0) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
if (bmppixcol == infoHeader.width) {
bmppixcol = 0;
bmppixrow++;
dy--;
}
}
// get to the same column as where we started
while (x != bmppixcol) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
}
// move over dx pixels
for (uint8 i = 0; i < dx; i++) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
}
break;
}
// code >= 3
default:
// read code uncompressed pixels
for (uint8 i = 0; i < code; i++) {
if (!(i % 2)) {
rd = inSource->Read(&indices, 1);
if (rd != 1)
break;
}
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
if (!(i % 2))
index = (indices>>4) & 0xf;
else
index = indices & 0xf;
memcpy(bitspixels + bitsoffset,
palette + (index * 4), 3);
bmppixcol++;
}
int32 padding;
padding = (((code + (code % 2)) / 2) % 2);
// if odd number, there is junk padding
if (padding)
inSource->Seek(padding, SEEK_CUR);
break;
}
}
if (rd > 0)
rd = inSource->Read(&count, 1);
}
outDestination->Write(bitspixels, datasize);
delete[] bitspixels;
return B_OK;
}
status_t translate_from_bmppal_to_bits(BPositionIO *inSource, BPositionIO *outDestination, status_t translate_from_bmppal_to_bits(BPositionIO *inSource, BPositionIO *outDestination,
int32 datasize, BMPInfoHeader &infoHeader, const char *palette) int32 datasize, BMPInfoHeader &infoHeader, const uint8 *palette)
{ {
uint16 pixelsPerByte = 8 / infoHeader.bitsperpixel; uint16 pixelsPerByte = 8 / infoHeader.bitsperpixel;
uint16 bitsPerPixel = infoHeader.bitsperpixel; uint16 bitsPerPixel = infoHeader.bitsperpixel;
uint8 mask = 1; uint8 mask = 1;
for (uint16 i = 0; i < bitsPerPixel; i++) mask = (mask << bitsPerPixel) - 1;
mask *= 2;
mask -= 1;
int32 padding; int32 padding;
if (!(infoHeader.width % pixelsPerByte)) if (!(infoHeader.width % pixelsPerByte))
@@ -823,11 +683,11 @@ status_t translate_from_bmppal_to_bits(BPositionIO *inSource, BPositionIO *outDe
off_t bmpoffset = ((infoHeader.height - 1) * bmpRowBytes); off_t bmpoffset = ((infoHeader.height - 1) * bmpRowBytes);
inSource->Seek(bmpoffset, SEEK_CUR); inSource->Seek(bmpoffset, SEEK_CUR);
char *bmpRowData = new char[bmpRowBytes]; uint8 *bmpRowData = new uint8[bmpRowBytes];
if (!bmpRowData) if (!bmpRowData)
return B_ERROR; return B_ERROR;
int32 bitsRowBytes = infoHeader.width * 4; int32 bitsRowBytes = infoHeader.width * 4;
char *bitsRowData = new char[bitsRowBytes]; uint8 *bitsRowData = new uint8[bitsRowBytes];
if (!bitsRowData) { if (!bitsRowData) {
delete[] bmpRowData; delete[] bmpRowData;
return B_ERROR; return B_ERROR;
@@ -862,10 +722,182 @@ status_t translate_from_bmppal_to_bits(BPositionIO *inSource, BPositionIO *outDe
return B_OK; return B_OK;
} }
status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread, // for converting palette-based RLE BMP images to the Be Bitmap format
char *read, uint32 outType, BPositionIO *outDestination) status_t translate_from_bmppalr_to_bits(BPositionIO *inSource, BPositionIO *outDestination,
int32 datasize, BMPInfoHeader &infoHeader, const uint8 *palette)
{ {
char buf[40]; uint16 pixelsPerByte = 8 / infoHeader.bitsperpixel;
uint16 bitsPerPixel = infoHeader.bitsperpixel;
uint8 mask = 1;
mask = (mask << bitsPerPixel) - 1;
uint8 count, indices, index;
uint8 *bitspixels = new uint8[datasize];
if (!bitspixels)
return B_ERROR;
memset(bitspixels, 0xffffffff, datasize);
int32 bitsRowBytes = infoHeader.width * 4;
uint32 bmppixcol = 0, bmppixrow = 0;
int32 bitsoffset = 0;
ssize_t rd = inSource->Read(&count, 1);
while (rd > 0) {
// repeated color
if (count) {
rd = inSource->Read(&indices, 1);
if (rd != 1)
break;
for (uint8 i = 0; i < count; i++) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) * bitsRowBytes) +
(bmppixcol * 4);
index = (indices >> (bitsPerPixel * ((pixelsPerByte - 1) - (i % pixelsPerByte)))) & mask;
memcpy(bitspixels + bitsoffset, palette + (index * 4), 3);
bmppixcol++;
}
// special code
} else {
uint8 code;
rd = inSource->Read(&code, 1);
if (rd != 1)
break;
switch (code) {
case 0:
// end of line
// if there are columns remaing on this
// line, set them to the color at index zero
while (bmppixcol != infoHeader.width) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
}
bmppixcol = 0;
bmppixrow++;
break;
case 1:
// end of bitmap
if (bmppixcol == infoHeader.width) {
bmppixcol = 0;
bmppixrow++;
}
while (bmppixrow < infoHeader.height) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
if (bmppixcol == infoHeader.width) {
bmppixcol = 0;
bmppixrow++;
}
}
rd = 0;
// break out of while loop
break;
case 2:
{
// delta, wierd feature
uint8 x, dx, dy;
inSource->Read(&dx, 1);
inSource->Read(&dy, 1);
x = bmppixcol;
// set all pixels to the first entry in
// the palette, for the number of rows skipped
while (dy > 0) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
if (bmppixcol == infoHeader.width) {
bmppixcol = 0;
bmppixrow++;
dy--;
}
}
// get to the same column as where we started
while (x != bmppixcol) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
}
// move over dx pixels
for (uint8 i = 0; i < dx; i++) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
memcpy(bitspixels + bitsoffset, palette, 3);
bmppixcol++;
}
break;
}
// code >= 3
default:
// read code uncompressed indices
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 = 0;
break;
}
for (uint8 i = 0; i < code; i++) {
bitsoffset = ((infoHeader.height -
(bmppixrow + 1)) *
bitsRowBytes) +
(bmppixcol * 4);
indices = (uncomp + (i / pixelsPerByte))[0];
index = (indices >>
(bitsPerPixel * ((pixelsPerByte - 1) - (i % pixelsPerByte)))) & mask;
memcpy(bitspixels + bitsoffset,
palette + (index * 4), 3);
bmppixcol++;
}
break;
}
}
if (rd > 0)
rd = inSource->Read(&count, 1);
}
outDestination->Write(bitspixels, datasize);
delete[] bitspixels;
return B_OK;
}
status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
uint8 *read, uint32 outType, BPositionIO *outDestination)
{
uint8 buf[40];
BMPFileHeader fileHeader; BMPFileHeader fileHeader;
memcpy(buf, read, amtread); memcpy(buf, read, amtread);
@@ -883,7 +915,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
if (swap_data(B_UINT16_TYPE, &fileHeader.magic, 2, if (swap_data(B_UINT16_TYPE, &fileHeader.magic, 2,
B_SWAP_LENDIAN_TO_HOST) != B_OK) B_SWAP_LENDIAN_TO_HOST) != B_OK)
return B_ERROR; return B_ERROR;
if (swap_data(B_UINT32_TYPE, ((char *) &fileHeader) + 2, 12, if (swap_data(B_UINT32_TYPE, ((uint8 *) &fileHeader) + 2, 12,
B_SWAP_LENDIAN_TO_HOST) != B_OK) B_SWAP_LENDIAN_TO_HOST) != B_OK)
return B_ERROR; return B_ERROR;
@@ -919,12 +951,12 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
if (swap_data(B_UINT16_TYPE, &fileHeader.magic, sizeof(uint16), if (swap_data(B_UINT16_TYPE, &fileHeader.magic, sizeof(uint16),
B_SWAP_HOST_TO_LENDIAN) != B_OK) B_SWAP_HOST_TO_LENDIAN) != B_OK)
return B_ERROR; return B_ERROR;
if (swap_data(B_UINT32_TYPE, ((char *) &fileHeader) + 2, 12, if (swap_data(B_UINT32_TYPE, ((uint8 *) &fileHeader) + 2, 12,
B_SWAP_HOST_TO_LENDIAN) != B_OK) B_SWAP_HOST_TO_LENDIAN) != B_OK)
return B_ERROR; return B_ERROR;
if (outDestination->Write(&fileHeader.magic, 2) != 2) if (outDestination->Write(&fileHeader.magic, 2) != 2)
return B_ERROR; return B_ERROR;
if (outDestination->Write(((char *) &fileHeader) + 2, 12) != 12) if (outDestination->Write(((uint8 *) &fileHeader) + 2, 12) != 12)
return B_ERROR; return B_ERROR;
// write out infoHeader // write out infoHeader
@@ -935,7 +967,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
sizeof(BMPInfoHeader)) sizeof(BMPInfoHeader))
return B_ERROR; return B_ERROR;
char buf[1024]; uint8 buf[1024];
ssize_t rd = inSource->Read(buf, 1024); ssize_t rd = inSource->Read(buf, 1024);
while (rd > 0) { while (rd > 0) {
outDestination->Write(buf, rd); outDestination->Write(buf, rd);
@@ -957,7 +989,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
bitsHeader.bounds.bottom = infoHeader.height - 1; bitsHeader.bounds.bottom = infoHeader.height - 1;
// read in palette and/or skip non-BMP data // read in palette and/or skip non-BMP data
char bmppalette[1024]; uint8 bmppalette[1024];
off_t nskip = 0; off_t nskip = 0;
if (infoHeader.bitsperpixel == 1 || if (infoHeader.bitsperpixel == 1 ||
infoHeader.bitsperpixel == 4 || infoHeader.bitsperpixel == 4 ||
@@ -965,8 +997,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
if (!infoHeader.colorsused) { if (!infoHeader.colorsused) {
infoHeader.colorsused = 1; infoHeader.colorsused = 1;
for (int npow = 0; npow < infoHeader.bitsperpixel; npow++) infoHeader.colorsused <<= infoHeader.bitsperpixel;
infoHeader.colorsused *= 2;
} }
if (inSource->Read(bmppalette, infoHeader.colorsused * 4) != if (inSource->Read(bmppalette, infoHeader.colorsused * 4) !=
@@ -1008,7 +1039,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
// 8 bit RLE compressed BMP // 8 bit RLE compressed BMP
else if (infoHeader.compression == BMP_RLE8_COMPRESS) else if (infoHeader.compression == BMP_RLE8_COMPRESS)
return translate_from_bmp8r_to_bits(inSource, return translate_from_bmppalr_to_bits(inSource,
outDestination, datasize, infoHeader, bmppalette); outDestination, datasize, infoHeader, bmppalette);
else else
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
@@ -1021,7 +1052,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
// 4 bit RLE compressed BMP // 4 bit RLE compressed BMP
else if (infoHeader.compression == BMP_RLE4_COMPRESS) else if (infoHeader.compression == BMP_RLE4_COMPRESS)
return translate_from_bmp4r_to_bits(inSource, return translate_from_bmppalr_to_bits(inSource,
outDestination, datasize, infoHeader, bmppalette); outDestination, datasize, infoHeader, bmppalette);
else else
return B_NO_TRANSLATOR; return B_NO_TRANSLATOR;
@@ -1049,7 +1080,7 @@ status_t BMPTranslator::Translate(BPositionIO *inSource,
inSource->Seek(0, SEEK_SET); inSource->Seek(0, SEEK_SET);
char ch[4]; uint8 ch[4];
uint32 nbits = B_TRANSLATOR_BITMAP; uint32 nbits = B_TRANSLATOR_BITMAP;
uint16 nbm = 'MB'; uint16 nbm = 'MB';