diff --git a/src/add-ons/translators/bmptranslator/BMPTranslator.cpp b/src/add-ons/translators/bmptranslator/BMPTranslator.cpp index d7ea8e6042..7d71288e65 100644 --- a/src/add-ons/translators/bmptranslator/BMPTranslator.cpp +++ b/src/add-ons/translators/bmptranslator/BMPTranslator.cpp @@ -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); - - 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); + 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; - } - - delete[] bmppixels; + + default: + break; + } 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';