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:
@@ -132,7 +132,7 @@ const translation_format *BMPTranslator::OutputFormats(int32 *out_count) const
|
||||
}
|
||||
|
||||
status_t identify_bits_header(BPositionIO *inSource, translator_info *outInfo,
|
||||
ssize_t amtread, char *read)
|
||||
ssize_t amtread, uint8 *read)
|
||||
{
|
||||
TranslatorBitmap header;
|
||||
|
||||
@@ -140,7 +140,7 @@ status_t identify_bits_header(BPositionIO *inSource, translator_info *outInfo,
|
||||
// copy portion of header already read in
|
||||
// read in the rest of the header
|
||||
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;
|
||||
|
||||
// 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
|
||||
if (header.colors != B_RGB32 &&
|
||||
header.colors != B_RGB32_BIG &&
|
||||
header.colors != B_RGBA32 &&
|
||||
header.colors != B_RGBA32_BIG &&
|
||||
header.colors != B_RGB24 &&
|
||||
header.colors != B_RGB24_BIG &&
|
||||
header.colors != B_RGB16 &&
|
||||
header.colors != B_RGB16_BIG &&
|
||||
header.colors != B_RGB15 &&
|
||||
header.colors != B_RGB15_BIG &&
|
||||
header.colors != B_RGBA15 &&
|
||||
header.colors != B_RGBA15_BIG &&
|
||||
header.colors != B_CMAP8 &&
|
||||
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;
|
||||
if (header.rowBytes * (header.bounds.Height() + 1) > header.dataSize)
|
||||
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,
|
||||
ssize_t amtread, char *read)
|
||||
ssize_t amtread, uint8 *read)
|
||||
{
|
||||
char buf[40];
|
||||
uint8 buf[40];
|
||||
BMPFileHeader fileHeader;
|
||||
|
||||
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),
|
||||
B_SWAP_LENDIAN_TO_HOST) != B_OK)
|
||||
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)
|
||||
return B_ERROR;
|
||||
|
||||
@@ -242,7 +252,7 @@ status_t BMPTranslator::Identify(BPositionIO *inSource,
|
||||
if (outType != B_TRANSLATOR_BITMAP && outType != B_BMP_FORMAT)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
char ch[4];
|
||||
uint8 ch[4];
|
||||
uint32 nbits = B_TRANSLATOR_BITMAP;
|
||||
uint16 nbm = 'MB';
|
||||
|
||||
@@ -273,8 +283,169 @@ status_t BMPTranslator::Identify(BPositionIO *inSource,
|
||||
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,
|
||||
char *read, uint32 outType, BPositionIO *outDestination)
|
||||
uint8 *read, uint32 outType, BPositionIO *outDestination)
|
||||
{
|
||||
TranslatorBitmap bitsHeader;
|
||||
|
||||
@@ -282,7 +453,7 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
|
||||
// copy portion of bitsHeader already read in
|
||||
// read in the rest of the bitsHeader
|
||||
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;
|
||||
|
||||
// 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
|
||||
if (bitsHeader.colors != B_RGB32 &&
|
||||
bitsHeader.colors != B_RGB32_BIG &&
|
||||
bitsHeader.colors != B_RGBA32 &&
|
||||
bitsHeader.colors != B_RGBA32_BIG &&
|
||||
bitsHeader.colors != B_RGB24 &&
|
||||
bitsHeader.colors != B_RGB24_BIG &&
|
||||
bitsHeader.colors != B_RGB16 &&
|
||||
bitsHeader.colors != B_RGB16_BIG &&
|
||||
bitsHeader.colors != B_RGB15 &&
|
||||
bitsHeader.colors != B_RGB15_BIG &&
|
||||
bitsHeader.colors != B_RGBA15 &&
|
||||
bitsHeader.colors != B_RGBA15_BIG &&
|
||||
bitsHeader.colors != B_CMAP8 &&
|
||||
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;
|
||||
if (bitsHeader.rowBytes * (bitsHeader.bounds.Height() + 1) >
|
||||
bitsHeader.dataSize)
|
||||
@@ -315,7 +496,7 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
|
||||
sizeof(TranslatorBitmap)) != sizeof(TranslatorBitmap))
|
||||
return B_ERROR;
|
||||
|
||||
char buf[1024];
|
||||
uint8 buf[1024];
|
||||
ssize_t rd = inSource->Read(buf, 1024);
|
||||
while (rd > 0) {
|
||||
outDestination->Write(buf, rd);
|
||||
@@ -349,8 +530,21 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
|
||||
// determine fileSize / imagesize
|
||||
switch (bitsHeader.colors) {
|
||||
case B_RGB32:
|
||||
case B_RGB32_BIG:
|
||||
case B_RGBA32:
|
||||
case B_RGBA32_BIG:
|
||||
case B_RGB24:
|
||||
case B_RGB24_BIG:
|
||||
case B_RGB16:
|
||||
case B_RGB16_BIG:
|
||||
case B_RGB15:
|
||||
case B_RGB15_BIG:
|
||||
case B_RGBA15:
|
||||
case B_RGBA15_BIG:
|
||||
case B_CMYK32:
|
||||
case B_CMY32:
|
||||
case B_CMYA32:
|
||||
case B_CMY24:
|
||||
|
||||
infoHeader.bitsperpixel = 24;
|
||||
infoHeader.compression = BMP_NO_COMPRESS;
|
||||
@@ -369,7 +563,7 @@ status_t translate_from_bits(BPositionIO *inSource, ssize_t amtread,
|
||||
}
|
||||
|
||||
// write out the BMP headers
|
||||
char bmpheaders[54];
|
||||
uint8 bmpheaders[54];
|
||||
memcpy(bmpheaders, &fileHeader.magic, sizeof(uint16));
|
||||
memcpy(bmpheaders + 2, &fileHeader.fileSize, 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;
|
||||
|
||||
// write out the BMP pixel data
|
||||
char *bmppixels = new char[infoHeader.imagesize];
|
||||
if (!bmppixels)
|
||||
return B_ERROR;
|
||||
|
||||
switch (bitsHeader.colors) {
|
||||
case B_RGB32:
|
||||
char bitspixel[4];
|
||||
int32 bytesperline = (infoHeader.width * 3) + padding;
|
||||
int32 bitspixoffset = 0;
|
||||
ssize_t bitsoffset = 0;
|
||||
ssize_t rd = inSource->Read(bitspixel, 4);
|
||||
while (rd > 0) {
|
||||
int32 bmpoffset = ((infoHeader.height -
|
||||
((bitsoffset / bitsHeader.rowBytes) + 1)) *
|
||||
bytesperline) + (bitspixoffset * 3);
|
||||
memcpy(bmppixels + bmpoffset, bitspixel, 3);
|
||||
case B_RGB32_BIG:
|
||||
case B_RGBA32:
|
||||
case B_RGBA32_BIG:
|
||||
case B_RGB24:
|
||||
case B_RGB24_BIG:
|
||||
case B_RGB16:
|
||||
case B_RGB16_BIG:
|
||||
case B_RGB15:
|
||||
case B_RGB15_BIG:
|
||||
case B_RGBA15:
|
||||
case B_RGBA15_BIG:
|
||||
case B_CMYK32:
|
||||
case B_CMY32:
|
||||
case B_CMYA32:
|
||||
case B_CMY24:
|
||||
translate_from_bits32_to_bmp(inSource, outDestination,
|
||||
bitsHeader.colors, infoHeader);
|
||||
break;
|
||||
|
||||
bitspixoffset++;
|
||||
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;
|
||||
}
|
||||
rd = inSource->Read(bitspixel, 4);
|
||||
}
|
||||
outDestination->Write(bmppixels, infoHeader.imagesize);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
delete[] bmppixels;
|
||||
|
||||
return B_OK;
|
||||
} else
|
||||
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,
|
||||
int32 datasize, BMPInfoHeader &infoHeader)
|
||||
{
|
||||
@@ -446,10 +625,10 @@ status_t translate_from_bmpnpal_to_bits(BPositionIO *inSource, BPositionIO *outD
|
||||
uint32 bmppixrow = 0;
|
||||
off_t bmpoffset = ((infoHeader.height - 1) * bmpRowBytes);
|
||||
inSource->Seek(bmpoffset, SEEK_CUR);
|
||||
char *bmpRowData = new char[bmpRowBytes];
|
||||
uint8 *bmpRowData = new uint8[bmpRowBytes];
|
||||
if (!bmpRowData)
|
||||
return B_ERROR;
|
||||
char *bitsRowData = new char[bitsRowBytes];
|
||||
uint8 *bitsRowData = new uint8[bitsRowBytes];
|
||||
if (!bitsRowData) {
|
||||
delete[] bmpRowData;
|
||||
return B_ERROR;
|
||||
@@ -479,334 +658,15 @@ status_t translate_from_bmpnpal_to_bits(BPositionIO *inSource, BPositionIO *outD
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t translate_from_bmp8r_to_bits(BPositionIO *inSource, BPositionIO *outDestination,
|
||||
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;
|
||||
}
|
||||
|
||||
// for converting palette-based uncompressed BMP images to the Be Bitmap format
|
||||
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 bitsPerPixel = infoHeader.bitsperpixel;
|
||||
|
||||
uint8 mask = 1;
|
||||
for (uint16 i = 0; i < bitsPerPixel; i++)
|
||||
mask *= 2;
|
||||
mask -= 1;
|
||||
mask = (mask << bitsPerPixel) - 1;
|
||||
|
||||
int32 padding;
|
||||
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);
|
||||
inSource->Seek(bmpoffset, SEEK_CUR);
|
||||
char *bmpRowData = new char[bmpRowBytes];
|
||||
uint8 *bmpRowData = new uint8[bmpRowBytes];
|
||||
if (!bmpRowData)
|
||||
return B_ERROR;
|
||||
int32 bitsRowBytes = infoHeader.width * 4;
|
||||
char *bitsRowData = new char[bitsRowBytes];
|
||||
uint8 *bitsRowData = new uint8[bitsRowBytes];
|
||||
if (!bitsRowData) {
|
||||
delete[] bmpRowData;
|
||||
return B_ERROR;
|
||||
@@ -862,10 +722,182 @@ status_t translate_from_bmppal_to_bits(BPositionIO *inSource, BPositionIO *outDe
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
|
||||
char *read, uint32 outType, BPositionIO *outDestination)
|
||||
// for converting palette-based RLE BMP images to the Be Bitmap format
|
||||
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;
|
||||
|
||||
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,
|
||||
B_SWAP_LENDIAN_TO_HOST) != B_OK)
|
||||
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)
|
||||
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),
|
||||
B_SWAP_HOST_TO_LENDIAN) != B_OK)
|
||||
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)
|
||||
return B_ERROR;
|
||||
if (outDestination->Write(&fileHeader.magic, 2) != 2)
|
||||
return B_ERROR;
|
||||
if (outDestination->Write(((char *) &fileHeader) + 2, 12) != 12)
|
||||
if (outDestination->Write(((uint8 *) &fileHeader) + 2, 12) != 12)
|
||||
return B_ERROR;
|
||||
|
||||
// write out infoHeader
|
||||
@@ -935,7 +967,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
|
||||
sizeof(BMPInfoHeader))
|
||||
return B_ERROR;
|
||||
|
||||
char buf[1024];
|
||||
uint8 buf[1024];
|
||||
ssize_t rd = inSource->Read(buf, 1024);
|
||||
while (rd > 0) {
|
||||
outDestination->Write(buf, rd);
|
||||
@@ -957,7 +989,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
|
||||
bitsHeader.bounds.bottom = infoHeader.height - 1;
|
||||
|
||||
// read in palette and/or skip non-BMP data
|
||||
char bmppalette[1024];
|
||||
uint8 bmppalette[1024];
|
||||
off_t nskip = 0;
|
||||
if (infoHeader.bitsperpixel == 1 ||
|
||||
infoHeader.bitsperpixel == 4 ||
|
||||
@@ -965,8 +997,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
|
||||
|
||||
if (!infoHeader.colorsused) {
|
||||
infoHeader.colorsused = 1;
|
||||
for (int npow = 0; npow < infoHeader.bitsperpixel; npow++)
|
||||
infoHeader.colorsused *= 2;
|
||||
infoHeader.colorsused <<= infoHeader.bitsperpixel;
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
else
|
||||
return B_NO_TRANSLATOR;
|
||||
@@ -1021,7 +1052,7 @@ status_t translate_from_bmp(BPositionIO *inSource, ssize_t amtread,
|
||||
|
||||
// 4 bit RLE compressed BMP
|
||||
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);
|
||||
else
|
||||
return B_NO_TRANSLATOR;
|
||||
@@ -1049,7 +1080,7 @@ status_t BMPTranslator::Translate(BPositionIO *inSource,
|
||||
|
||||
inSource->Seek(0, SEEK_SET);
|
||||
|
||||
char ch[4];
|
||||
uint8 ch[4];
|
||||
uint32 nbits = B_TRANSLATOR_BITMAP;
|
||||
uint16 nbm = 'MB';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user