X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fbin%2Fjp2%2Fconvertbmp.c;h=0bc9c9f352f2bf906c955a9986cff57c865117e9;hb=563bd8499e63db976ca8358216138647593354bc;hp=7f570203a80e36eb44e78d813dc7c8e059a52ead;hpb=f1bae45c769e4360d9ed2e78fff5cb52fa6e4a8c;p=openjpeg.git diff --git a/src/bin/jp2/convertbmp.c b/src/bin/jp2/convertbmp.c index 7f570203..0bc9c9f3 100644 --- a/src/bin/jp2/convertbmp.c +++ b/src/bin/jp2/convertbmp.c @@ -1,6 +1,6 @@ /* - * The copyright in this software is being made available under the 2-clauses - * BSD License, included below. This software may be subject to other third + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third * party and contributor rights, including patent rights, and no such rights * are granted under this license. * @@ -8,7 +8,7 @@ * Copyright (c) 2002-2014, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2007, Francois-Olivier Devaux * Copyright (c) 2003-2014, Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2006-2007, Parvatha Elangovan @@ -46,514 +46,786 @@ #include "convert.h" typedef struct { - OPJ_UINT16 bfType; /* 'BM' for Bitmap (19776) */ - OPJ_UINT32 bfSize; /* Size of the file */ - OPJ_UINT16 bfReserved1; /* Reserved : 0 */ - OPJ_UINT16 bfReserved2; /* Reserved : 0 */ - OPJ_UINT32 bfOffBits; /* Offset */ + OPJ_UINT16 bfType; /* 'BM' for Bitmap (19776) */ + OPJ_UINT32 bfSize; /* Size of the file */ + OPJ_UINT16 bfReserved1; /* Reserved : 0 */ + OPJ_UINT16 bfReserved2; /* Reserved : 0 */ + OPJ_UINT32 bfOffBits; /* Offset */ } OPJ_BITMAPFILEHEADER; typedef struct { - OPJ_UINT32 biSize; /* Size of the structure in bytes */ - OPJ_UINT32 biWidth; /* Width of the image in pixels */ - OPJ_UINT32 biHeight; /* Heigth of the image in pixels */ - OPJ_UINT16 biPlanes; /* 1 */ - OPJ_UINT16 biBitCount; /* Number of color bits by pixels */ - OPJ_UINT32 biCompression; /* Type of encoding 0: none 1: RLE8 2: RLE4 */ - OPJ_UINT32 biSizeImage; /* Size of the image in bytes */ - OPJ_UINT32 biXpelsPerMeter; /* Horizontal (X) resolution in pixels/meter */ - OPJ_UINT32 biYpelsPerMeter; /* Vertical (Y) resolution in pixels/meter */ - OPJ_UINT32 biClrUsed; /* Number of color used in the image (0: ALL) */ - OPJ_UINT32 biClrImportant; /* Number of important color (0: ALL) */ + OPJ_UINT32 biSize; /* Size of the structure in bytes */ + OPJ_UINT32 biWidth; /* Width of the image in pixels */ + OPJ_UINT32 biHeight; /* Heigth of the image in pixels */ + OPJ_UINT16 biPlanes; /* 1 */ + OPJ_UINT16 biBitCount; /* Number of color bits by pixels */ + OPJ_UINT32 biCompression; /* Type of encoding 0: none 1: RLE8 2: RLE4 */ + OPJ_UINT32 biSizeImage; /* Size of the image in bytes */ + OPJ_UINT32 biXpelsPerMeter; /* Horizontal (X) resolution in pixels/meter */ + OPJ_UINT32 biYpelsPerMeter; /* Vertical (Y) resolution in pixels/meter */ + OPJ_UINT32 biClrUsed; /* Number of color used in the image (0: ALL) */ + OPJ_UINT32 biClrImportant; /* Number of important color (0: ALL) */ + OPJ_UINT32 biRedMask; /* Red channel bit mask */ + OPJ_UINT32 biGreenMask; /* Green channel bit mask */ + OPJ_UINT32 biBlueMask; /* Blue channel bit mask */ + OPJ_UINT32 biAlphaMask; /* Alpha channel bit mask */ + OPJ_UINT32 biColorSpaceType; /* Color space type */ + OPJ_UINT8 biColorSpaceEP[36]; /* Color space end points */ + OPJ_UINT32 biRedGamma; /* Red channel gamma */ + OPJ_UINT32 biGreenGamma; /* Green channel gamma */ + OPJ_UINT32 biBlueGamma; /* Blue channel gamma */ + OPJ_UINT32 biIntent; /* Intent */ + OPJ_UINT32 biIccProfileData; /* ICC profile data */ + OPJ_UINT32 biIccProfileSize; /* ICC profile size */ + OPJ_UINT32 biReserved; /* Reserved */ } OPJ_BITMAPINFOHEADER; static void opj_applyLUT8u_8u32s_C1R( - OPJ_UINT8 const* pSrc, OPJ_INT32 srcStride, - OPJ_INT32* pDst, OPJ_INT32 dstStride, - OPJ_UINT8 const* pLUT, - OPJ_UINT32 width, OPJ_UINT32 height) + OPJ_UINT8 const* pSrc, OPJ_INT32 srcStride, + OPJ_INT32* pDst, OPJ_INT32 dstStride, + OPJ_UINT8 const* pLUT, + OPJ_UINT32 width, OPJ_UINT32 height) { - OPJ_UINT32 y; - - for (y = height; y != 0U; --y) { - OPJ_UINT32 x; - - for(x = 0; x < width; x++) - { - pDst[x] = pLUT[pSrc[x]]; - } - pSrc += srcStride; - pDst += dstStride; - } + OPJ_UINT32 y; + + for (y = height; y != 0U; --y) { + OPJ_UINT32 x; + + for (x = 0; x < width; x++) { + pDst[x] = (OPJ_INT32)pLUT[pSrc[x]]; + } + pSrc += srcStride; + pDst += dstStride; + } } static void opj_applyLUT8u_8u32s_C1P3R( - OPJ_UINT8 const* pSrc, OPJ_INT32 srcStride, - OPJ_INT32* const* pDst, OPJ_INT32 const* pDstStride, - OPJ_UINT8 const* const* pLUT, - OPJ_UINT32 width, OPJ_UINT32 height) + OPJ_UINT8 const* pSrc, OPJ_INT32 srcStride, + OPJ_INT32* const* pDst, OPJ_INT32 const* pDstStride, + OPJ_UINT8 const* const* pLUT, + OPJ_UINT32 width, OPJ_UINT32 height) +{ + OPJ_UINT32 y; + OPJ_INT32* pR = pDst[0]; + OPJ_INT32* pG = pDst[1]; + OPJ_INT32* pB = pDst[2]; + OPJ_UINT8 const* pLUT_R = pLUT[0]; + OPJ_UINT8 const* pLUT_G = pLUT[1]; + OPJ_UINT8 const* pLUT_B = pLUT[2]; + + for (y = height; y != 0U; --y) { + OPJ_UINT32 x; + + for (x = 0; x < width; x++) { + OPJ_UINT8 idx = pSrc[x]; + pR[x] = (OPJ_INT32)pLUT_R[idx]; + pG[x] = (OPJ_INT32)pLUT_G[idx]; + pB[x] = (OPJ_INT32)pLUT_B[idx]; + } + pSrc += srcStride; + pR += pDstStride[0]; + pG += pDstStride[1]; + pB += pDstStride[2]; + } +} + +static void bmp24toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride, + opj_image_t* image) { - OPJ_UINT32 y; - OPJ_INT32* pR = pDst[0]; - OPJ_INT32* pG = pDst[1]; - OPJ_INT32* pB = pDst[2]; - OPJ_UINT8 const* pLUT_R = pLUT[0]; - OPJ_UINT8 const* pLUT_G = pLUT[1]; - OPJ_UINT8 const* pLUT_B = pLUT[2]; - - for (y = height; y != 0U; --y) { - OPJ_UINT32 x; - - for(x = 0; x < width; x++) - { - OPJ_UINT8 idx = pSrc[x]; - pR[x] = pLUT_R[idx]; - pG[x] = pLUT_G[idx]; - pB[x] = pLUT_B[idx]; - } - pSrc += srcStride; - pR += pDstStride[0]; - pG += pDstStride[1]; - pB += pDstStride[2]; - } + int index; + OPJ_UINT32 width, height; + OPJ_UINT32 x, y; + const OPJ_UINT8 *pSrc = NULL; + + width = image->comps[0].w; + height = image->comps[0].h; + + index = 0; + pSrc = pData + (height - 1U) * stride; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + image->comps[0].data[index] = (OPJ_INT32)pSrc[3 * x + 2]; /* R */ + image->comps[1].data[index] = (OPJ_INT32)pSrc[3 * x + 1]; /* G */ + image->comps[2].data[index] = (OPJ_INT32)pSrc[3 * x + 0]; /* B */ + index++; + } + pSrc -= stride; + } +} + +static void bmp_mask_get_shift_and_prec(OPJ_UINT32 mask, OPJ_UINT32* shift, + OPJ_UINT32* prec) +{ + OPJ_UINT32 l_shift, l_prec; + + l_shift = l_prec = 0U; + + if (mask != 0U) { + while ((mask & 1U) == 0U) { + mask >>= 1; + l_shift++; + } + while (mask & 1U) { + mask >>= 1; + l_prec++; + } + } + *shift = l_shift; + *prec = l_prec; +} + +static void bmpmask32toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride, + opj_image_t* image, OPJ_UINT32 redMask, OPJ_UINT32 greenMask, + OPJ_UINT32 blueMask, OPJ_UINT32 alphaMask) +{ + int index; + OPJ_UINT32 width, height; + OPJ_UINT32 x, y; + const OPJ_UINT8 *pSrc = NULL; + OPJ_BOOL hasAlpha; + OPJ_UINT32 redShift, redPrec; + OPJ_UINT32 greenShift, greenPrec; + OPJ_UINT32 blueShift, bluePrec; + OPJ_UINT32 alphaShift, alphaPrec; + + width = image->comps[0].w; + height = image->comps[0].h; + + hasAlpha = image->numcomps > 3U; + + bmp_mask_get_shift_and_prec(redMask, &redShift, &redPrec); + bmp_mask_get_shift_and_prec(greenMask, &greenShift, &greenPrec); + bmp_mask_get_shift_and_prec(blueMask, &blueShift, &bluePrec); + bmp_mask_get_shift_and_prec(alphaMask, &alphaShift, &alphaPrec); + + image->comps[0].bpp = redPrec; + image->comps[0].prec = redPrec; + image->comps[1].bpp = greenPrec; + image->comps[1].prec = greenPrec; + image->comps[2].bpp = bluePrec; + image->comps[2].prec = bluePrec; + if (hasAlpha) { + image->comps[3].bpp = alphaPrec; + image->comps[3].prec = alphaPrec; + } + + index = 0; + pSrc = pData + (height - 1U) * stride; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + OPJ_UINT32 value = 0U; + + value |= ((OPJ_UINT32)pSrc[4 * x + 0]) << 0; + value |= ((OPJ_UINT32)pSrc[4 * x + 1]) << 8; + value |= ((OPJ_UINT32)pSrc[4 * x + 2]) << 16; + value |= ((OPJ_UINT32)pSrc[4 * x + 3]) << 24; + + image->comps[0].data[index] = (OPJ_INT32)((value & redMask) >> + redShift); /* R */ + image->comps[1].data[index] = (OPJ_INT32)((value & greenMask) >> + greenShift); /* G */ + image->comps[2].data[index] = (OPJ_INT32)((value & blueMask) >> + blueShift); /* B */ + if (hasAlpha) { + image->comps[3].data[index] = (OPJ_INT32)((value & alphaMask) >> + alphaShift); /* A */ + } + index++; + } + pSrc -= stride; + } +} + +static void bmpmask16toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride, + opj_image_t* image, OPJ_UINT32 redMask, OPJ_UINT32 greenMask, + OPJ_UINT32 blueMask, OPJ_UINT32 alphaMask) +{ + int index; + OPJ_UINT32 width, height; + OPJ_UINT32 x, y; + const OPJ_UINT8 *pSrc = NULL; + OPJ_BOOL hasAlpha; + OPJ_UINT32 redShift, redPrec; + OPJ_UINT32 greenShift, greenPrec; + OPJ_UINT32 blueShift, bluePrec; + OPJ_UINT32 alphaShift, alphaPrec; + + width = image->comps[0].w; + height = image->comps[0].h; + + hasAlpha = image->numcomps > 3U; + + bmp_mask_get_shift_and_prec(redMask, &redShift, &redPrec); + bmp_mask_get_shift_and_prec(greenMask, &greenShift, &greenPrec); + bmp_mask_get_shift_and_prec(blueMask, &blueShift, &bluePrec); + bmp_mask_get_shift_and_prec(alphaMask, &alphaShift, &alphaPrec); + + image->comps[0].bpp = redPrec; + image->comps[0].prec = redPrec; + image->comps[1].bpp = greenPrec; + image->comps[1].prec = greenPrec; + image->comps[2].bpp = bluePrec; + image->comps[2].prec = bluePrec; + if (hasAlpha) { + image->comps[3].bpp = alphaPrec; + image->comps[3].prec = alphaPrec; + } + + index = 0; + pSrc = pData + (height - 1U) * stride; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + OPJ_UINT32 value = 0U; + + value |= ((OPJ_UINT32)pSrc[2 * x + 0]) << 0; + value |= ((OPJ_UINT32)pSrc[2 * x + 1]) << 8; + + image->comps[0].data[index] = (OPJ_INT32)((value & redMask) >> + redShift); /* R */ + image->comps[1].data[index] = (OPJ_INT32)((value & greenMask) >> + greenShift); /* G */ + image->comps[2].data[index] = (OPJ_INT32)((value & blueMask) >> + blueShift); /* B */ + if (hasAlpha) { + image->comps[3].data[index] = (OPJ_INT32)((value & alphaMask) >> + alphaShift); /* A */ + } + index++; + } + pSrc -= stride; + } +} + +static opj_image_t* bmp8toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride, + opj_image_t* image, OPJ_UINT8 const* const* pLUT) +{ + OPJ_UINT32 width, height; + const OPJ_UINT8 *pSrc = NULL; + + width = image->comps[0].w; + height = image->comps[0].h; + + pSrc = pData + (height - 1U) * stride; + if (image->numcomps == 1U) { + opj_applyLUT8u_8u32s_C1R(pSrc, -(OPJ_INT32)stride, image->comps[0].data, + (OPJ_INT32)width, pLUT[0], width, height); + } else { + OPJ_INT32* pDst[3]; + OPJ_INT32 pDstStride[3]; + + pDst[0] = image->comps[0].data; + pDst[1] = image->comps[1].data; + pDst[2] = image->comps[2].data; + pDstStride[0] = (OPJ_INT32)width; + pDstStride[1] = (OPJ_INT32)width; + pDstStride[2] = (OPJ_INT32)width; + opj_applyLUT8u_8u32s_C1P3R(pSrc, -(OPJ_INT32)stride, pDst, pDstStride, pLUT, + width, height); + } + return image; +} + +static OPJ_BOOL bmp_read_file_header(FILE* IN, OPJ_BITMAPFILEHEADER* header) +{ + header->bfType = (OPJ_UINT16)getc(IN); + header->bfType |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8); + + if (header->bfType != 19778) { + fprintf(stderr, "Error, not a BMP file!\n"); + return OPJ_FALSE; + } + + /* FILE HEADER */ + /* ------------- */ + header->bfSize = (OPJ_UINT32)getc(IN); + header->bfSize |= (OPJ_UINT32)getc(IN) << 8; + header->bfSize |= (OPJ_UINT32)getc(IN) << 16; + header->bfSize |= (OPJ_UINT32)getc(IN) << 24; + + header->bfReserved1 = (OPJ_UINT16)getc(IN); + header->bfReserved1 |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8); + + header->bfReserved2 = (OPJ_UINT16)getc(IN); + header->bfReserved2 |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8); + + header->bfOffBits = (OPJ_UINT32)getc(IN); + header->bfOffBits |= (OPJ_UINT32)getc(IN) << 8; + header->bfOffBits |= (OPJ_UINT32)getc(IN) << 16; + header->bfOffBits |= (OPJ_UINT32)getc(IN) << 24; + return OPJ_TRUE; +} +static OPJ_BOOL bmp_read_info_header(FILE* IN, OPJ_BITMAPINFOHEADER* header) +{ + memset(header, 0, sizeof(*header)); + /* INFO HEADER */ + /* ------------- */ + header->biSize = (OPJ_UINT32)getc(IN); + header->biSize |= (OPJ_UINT32)getc(IN) << 8; + header->biSize |= (OPJ_UINT32)getc(IN) << 16; + header->biSize |= (OPJ_UINT32)getc(IN) << 24; + + switch (header->biSize) { + case 12U: /* BITMAPCOREHEADER */ + case 40U: /* BITMAPINFOHEADER */ + case 52U: /* BITMAPV2INFOHEADER */ + case 56U: /* BITMAPV3INFOHEADER */ + case 108U: /* BITMAPV4HEADER */ + case 124U: /* BITMAPV5HEADER */ + break; + default: + fprintf(stderr, "Error, unknown BMP header size %d\n", header->biSize); + return OPJ_FALSE; + } + + header->biWidth = (OPJ_UINT32)getc(IN); + header->biWidth |= (OPJ_UINT32)getc(IN) << 8; + header->biWidth |= (OPJ_UINT32)getc(IN) << 16; + header->biWidth |= (OPJ_UINT32)getc(IN) << 24; + + header->biHeight = (OPJ_UINT32)getc(IN); + header->biHeight |= (OPJ_UINT32)getc(IN) << 8; + header->biHeight |= (OPJ_UINT32)getc(IN) << 16; + header->biHeight |= (OPJ_UINT32)getc(IN) << 24; + + header->biPlanes = (OPJ_UINT16)getc(IN); + header->biPlanes |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8); + + header->biBitCount = (OPJ_UINT16)getc(IN); + header->biBitCount |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8); + + if (header->biSize >= 40U) { + header->biCompression = (OPJ_UINT32)getc(IN); + header->biCompression |= (OPJ_UINT32)getc(IN) << 8; + header->biCompression |= (OPJ_UINT32)getc(IN) << 16; + header->biCompression |= (OPJ_UINT32)getc(IN) << 24; + + header->biSizeImage = (OPJ_UINT32)getc(IN); + header->biSizeImage |= (OPJ_UINT32)getc(IN) << 8; + header->biSizeImage |= (OPJ_UINT32)getc(IN) << 16; + header->biSizeImage |= (OPJ_UINT32)getc(IN) << 24; + + header->biXpelsPerMeter = (OPJ_UINT32)getc(IN); + header->biXpelsPerMeter |= (OPJ_UINT32)getc(IN) << 8; + header->biXpelsPerMeter |= (OPJ_UINT32)getc(IN) << 16; + header->biXpelsPerMeter |= (OPJ_UINT32)getc(IN) << 24; + + header->biYpelsPerMeter = (OPJ_UINT32)getc(IN); + header->biYpelsPerMeter |= (OPJ_UINT32)getc(IN) << 8; + header->biYpelsPerMeter |= (OPJ_UINT32)getc(IN) << 16; + header->biYpelsPerMeter |= (OPJ_UINT32)getc(IN) << 24; + + header->biClrUsed = (OPJ_UINT32)getc(IN); + header->biClrUsed |= (OPJ_UINT32)getc(IN) << 8; + header->biClrUsed |= (OPJ_UINT32)getc(IN) << 16; + header->biClrUsed |= (OPJ_UINT32)getc(IN) << 24; + + header->biClrImportant = (OPJ_UINT32)getc(IN); + header->biClrImportant |= (OPJ_UINT32)getc(IN) << 8; + header->biClrImportant |= (OPJ_UINT32)getc(IN) << 16; + header->biClrImportant |= (OPJ_UINT32)getc(IN) << 24; + } + + if (header->biSize >= 56U) { + header->biRedMask = (OPJ_UINT32)getc(IN); + header->biRedMask |= (OPJ_UINT32)getc(IN) << 8; + header->biRedMask |= (OPJ_UINT32)getc(IN) << 16; + header->biRedMask |= (OPJ_UINT32)getc(IN) << 24; + + header->biGreenMask = (OPJ_UINT32)getc(IN); + header->biGreenMask |= (OPJ_UINT32)getc(IN) << 8; + header->biGreenMask |= (OPJ_UINT32)getc(IN) << 16; + header->biGreenMask |= (OPJ_UINT32)getc(IN) << 24; + + header->biBlueMask = (OPJ_UINT32)getc(IN); + header->biBlueMask |= (OPJ_UINT32)getc(IN) << 8; + header->biBlueMask |= (OPJ_UINT32)getc(IN) << 16; + header->biBlueMask |= (OPJ_UINT32)getc(IN) << 24; + + header->biAlphaMask = (OPJ_UINT32)getc(IN); + header->biAlphaMask |= (OPJ_UINT32)getc(IN) << 8; + header->biAlphaMask |= (OPJ_UINT32)getc(IN) << 16; + header->biAlphaMask |= (OPJ_UINT32)getc(IN) << 24; + } + + if (header->biSize >= 108U) { + header->biColorSpaceType = (OPJ_UINT32)getc(IN); + header->biColorSpaceType |= (OPJ_UINT32)getc(IN) << 8; + header->biColorSpaceType |= (OPJ_UINT32)getc(IN) << 16; + header->biColorSpaceType |= (OPJ_UINT32)getc(IN) << 24; + + if (fread(&(header->biColorSpaceEP), 1U, sizeof(header->biColorSpaceEP), + IN) != sizeof(header->biColorSpaceEP)) { + fprintf(stderr, "Error, can't read BMP header\n"); + return OPJ_FALSE; + } + + header->biRedGamma = (OPJ_UINT32)getc(IN); + header->biRedGamma |= (OPJ_UINT32)getc(IN) << 8; + header->biRedGamma |= (OPJ_UINT32)getc(IN) << 16; + header->biRedGamma |= (OPJ_UINT32)getc(IN) << 24; + + header->biGreenGamma = (OPJ_UINT32)getc(IN); + header->biGreenGamma |= (OPJ_UINT32)getc(IN) << 8; + header->biGreenGamma |= (OPJ_UINT32)getc(IN) << 16; + header->biGreenGamma |= (OPJ_UINT32)getc(IN) << 24; + + header->biBlueGamma = (OPJ_UINT32)getc(IN); + header->biBlueGamma |= (OPJ_UINT32)getc(IN) << 8; + header->biBlueGamma |= (OPJ_UINT32)getc(IN) << 16; + header->biBlueGamma |= (OPJ_UINT32)getc(IN) << 24; + } + + if (header->biSize >= 124U) { + header->biIntent = (OPJ_UINT32)getc(IN); + header->biIntent |= (OPJ_UINT32)getc(IN) << 8; + header->biIntent |= (OPJ_UINT32)getc(IN) << 16; + header->biIntent |= (OPJ_UINT32)getc(IN) << 24; + + header->biIccProfileData = (OPJ_UINT32)getc(IN); + header->biIccProfileData |= (OPJ_UINT32)getc(IN) << 8; + header->biIccProfileData |= (OPJ_UINT32)getc(IN) << 16; + header->biIccProfileData |= (OPJ_UINT32)getc(IN) << 24; + + header->biIccProfileSize = (OPJ_UINT32)getc(IN); + header->biIccProfileSize |= (OPJ_UINT32)getc(IN) << 8; + header->biIccProfileSize |= (OPJ_UINT32)getc(IN) << 16; + header->biIccProfileSize |= (OPJ_UINT32)getc(IN) << 24; + + header->biReserved = (OPJ_UINT32)getc(IN); + header->biReserved |= (OPJ_UINT32)getc(IN) << 8; + header->biReserved |= (OPJ_UINT32)getc(IN) << 16; + header->biReserved |= (OPJ_UINT32)getc(IN) << 24; + } + return OPJ_TRUE; } -static opj_image_t* bmp24toimage(FILE *IN, const OPJ_BITMAPFILEHEADER* File_h, const OPJ_BITMAPINFOHEADER* Info_h, const opj_cparameters_t *parameters) +static OPJ_BOOL bmp_read_raw_data(FILE* IN, OPJ_UINT8* pData, OPJ_UINT32 stride, + OPJ_UINT32 width, OPJ_UINT32 height) { - opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */ - opj_image_t * image = NULL; - int i, index; - OPJ_UINT32 width, height, stride; - OPJ_UINT32 x, y; - OPJ_UINT8 *pData = NULL; - const OPJ_UINT8 *pSrc = NULL; - - width = Info_h->biWidth; - height = Info_h->biHeight; - - /* initialize image components */ - memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t)); - for(i = 0; i < 3; i++) - { - cmptparm[i].prec = 8; - cmptparm[i].bpp = 8; - cmptparm[i].sgnd = 0; - cmptparm[i].dx = (OPJ_UINT32)parameters->subsampling_dx; - cmptparm[i].dy = (OPJ_UINT32)parameters->subsampling_dy; - cmptparm[i].w = (OPJ_UINT32)width; - cmptparm[i].h = (OPJ_UINT32)height; - } - /* create the image */ - image = opj_image_create(3U, &cmptparm[0], OPJ_CLRSPC_SRGB); - if(!image) - { - return NULL; - } - - /* set image offset and reference grid */ - image->x0 = (OPJ_UINT32)parameters->image_offset_x0; - image->y0 = (OPJ_UINT32)parameters->image_offset_y0; - image->x1 = image->x0 + (OPJ_UINT32)(width - 1U) * (OPJ_UINT32)parameters->subsampling_dx + 1U; - image->y1 = image->y0 + (OPJ_UINT32)(height - 1U) * (OPJ_UINT32)parameters->subsampling_dy + 1U; - - /* set image data */ - - /* Place the cursor at the beginning of the image information */ - fseek(IN, 0, SEEK_SET); - fseek(IN, (long)File_h->bfOffBits, SEEK_SET); - - stride = width * 3U; - /* line is 32 bits aligned */ - if (stride & 3U) { - stride += 4U - (stride & 3U); - } - - pData = (OPJ_UINT8 *)malloc(stride * height * sizeof(OPJ_UINT8)); - - if ( fread(pData, sizeof(OPJ_UINT8), stride * height, IN) != (stride * height) ) - { - free(pData); - opj_image_destroy(image); - fprintf(stderr, "\nError: fread return a number of element different from the expected.\n"); - return NULL; - } - - index = 0; - pSrc = pData + (height - 1U) * stride; - for(y = 0; y < height; y++) - { - for(x = 0; x < width; x++) - { - image->comps[0].data[index] = pSrc[3*x+2]; /* R */ - image->comps[1].data[index] = pSrc[3*x+1]; /* G */ - image->comps[2].data[index] = pSrc[3*x+0]; /* B */ - index++; - } - pSrc -= stride; - } - free(pData); - return image; + OPJ_ARG_NOT_USED(width); + + if (fread(pData, sizeof(OPJ_UINT8), stride * height, IN) != (stride * height)) { + fprintf(stderr, + "\nError: fread return a number of element different from the expected.\n"); + return OPJ_FALSE; + } + return OPJ_TRUE; } -static opj_image_t* bmp8toimage(FILE *IN, const OPJ_BITMAPFILEHEADER* File_h, const OPJ_BITMAPINFOHEADER* Info_h, const opj_cparameters_t *parameters) +static OPJ_BOOL bmp_read_rle8_data(FILE* IN, OPJ_UINT8* pData, + OPJ_UINT32 stride, OPJ_UINT32 width, OPJ_UINT32 height) { - OPJ_UINT8 lut_R[256], lut_G[256], lut_B[256]; - opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */ - opj_image_t * image = NULL; - OPJ_SIZE_T index; - OPJ_UINT32 i, palette_len; - OPJ_UINT32 width, height, stride; - OPJ_UINT8 *pData = NULL; - const OPJ_UINT8 *pSrc = NULL; - OPJ_UINT32 numcmpts = 1U; /* grayscale by default */ - - width = Info_h->biWidth; - height = Info_h->biHeight; - - /* initialize */ - memset(&cmptparm[0], 0, sizeof(cmptparm)); - memset(&lut_R[0], 0, sizeof(lut_R)); - memset(&lut_G[0], 0, sizeof(lut_G)); - memset(&lut_B[0], 0, sizeof(lut_B)); - - palette_len = Info_h->biClrUsed; - if ((palette_len == 0U) || (palette_len > 256U)) { - palette_len = 256U; - } - - /* Load palette */ - { - OPJ_UINT8 has_color = 0U; - for (i = 0; i < palette_len; i++) { - lut_B[i] = (OPJ_UINT8)getc(IN); - lut_G[i] = (OPJ_UINT8)getc(IN); - lut_R[i] = (OPJ_UINT8)getc(IN); - getc(IN); /* padding */ - has_color |= lut_B[i] ^ (lut_G[i] | lut_R[i]); - } - if(has_color) { - numcmpts = 3; - } - } - - - for(i = 0; i < numcmpts; i++) - { - cmptparm[i].prec = 8; - cmptparm[i].bpp = 8; - cmptparm[i].sgnd = 0; - cmptparm[i].dx = (OPJ_UINT32)parameters->subsampling_dx; - cmptparm[i].dy = (OPJ_UINT32)parameters->subsampling_dy; - cmptparm[i].w = width; - cmptparm[i].h = height; - } - /* create the image */ - image = opj_image_create(numcmpts, &cmptparm[0], (numcmpts == 1U) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB); - if(!image) - { - return NULL; - } - - /* set image offset and reference grid */ - image->x0 = (OPJ_UINT32)parameters->image_offset_x0; - image->y0 = (OPJ_UINT32)parameters->image_offset_y0; - image->x1 = image->x0 + (width - 1U) * (OPJ_UINT32)parameters->subsampling_dx + 1U; - image->y1 = image->y0 + (height - 1U) * (OPJ_UINT32)parameters->subsampling_dy + 1U; - - /* set image data */ - - /* Place the cursor at the beginning of the image information */ - fseek(IN, 0, SEEK_SET); - fseek(IN, (long)File_h->bfOffBits, SEEK_SET); - - stride = width; - /* line is 32 bits aligned */ - if (stride & 3U) { - stride += 4U - (stride & 3U); - } - - pData = (OPJ_UINT8 *)malloc(stride * height * sizeof(OPJ_UINT8)); - - if ( fread(pData, sizeof(OPJ_UINT8), stride * height, IN) != (stride * height) ) - { - free(pData); - opj_image_destroy(image); - fprintf(stderr, "\nError: fread return a number of element different from the expected.\n"); - return NULL; - } - - index = 0; - pSrc = pData + (height - 1U) * stride; - if (numcmpts == 1U) { - opj_applyLUT8u_8u32s_C1R(pSrc, -(OPJ_INT32)stride, image->comps[0].data, (OPJ_INT32)width, lut_R, width, height); - } - else { - OPJ_INT32* pDst[] = { image->comps[0].data, image->comps[1].data, image->comps[2].data }; - OPJ_INT32 pDstStride[] = { (OPJ_INT32)width, (OPJ_INT32)width, (OPJ_INT32)width }; - OPJ_UINT8 const* pLUT[] = { lut_R, lut_G, lut_B }; - - opj_applyLUT8u_8u32s_C1P3R(pSrc, -(OPJ_INT32)stride, pDst, pDstStride, pLUT, width, height); - } - - free(pData); - return image; + OPJ_UINT32 x, y; + OPJ_UINT8 *pix; + const OPJ_UINT8 *beyond; + + beyond = pData + stride * height; + pix = pData; + + x = y = 0U; + while (y < height) { + int c = getc(IN); + + if (c) { + int j; + OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN); + + for (j = 0; (j < c) && (x < width) && + ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) { + *pix = c1; + } + } else { + c = getc(IN); + if (c == 0x00) { /* EOL */ + x = 0; + ++y; + pix = pData + y * stride + x; + } else if (c == 0x01) { /* EOP */ + break; + } else if (c == 0x02) { /* MOVE by dxdy */ + c = getc(IN); + x += (OPJ_UINT32)c; + c = getc(IN); + y += (OPJ_UINT32)c; + pix = pData + y * stride + x; + } else { /* 03 .. 255 */ + int j; + for (j = 0; (j < c) && (x < width) && + ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) { + OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN); + *pix = c1; + } + if ((OPJ_UINT32)c & 1U) { /* skip padding byte */ + getc(IN); + } + } + } + }/* while() */ + return OPJ_TRUE; } -static opj_image_t* bmprle8toimage(FILE *IN, const OPJ_BITMAPFILEHEADER* File_h, const OPJ_BITMAPINFOHEADER* Info_h, const opj_cparameters_t *parameters) +static OPJ_BOOL bmp_read_rle4_data(FILE* IN, OPJ_UINT8* pData, + OPJ_UINT32 stride, OPJ_UINT32 width, OPJ_UINT32 height) { - OPJ_UINT8 lut_R[256], lut_G[256], lut_B[256]; - opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */ - opj_image_t * image = NULL; - OPJ_SIZE_T index; - OPJ_UINT32 i, palette_len; - OPJ_UINT32 x, y, width, height; - OPJ_UINT8 *pData = NULL, *pix; - const OPJ_UINT8 *beyond; - OPJ_UINT32 numcmpts = 1U; /* grayscale by default */ - - width = Info_h->biWidth; - height = Info_h->biHeight; - - /* initialize */ - memset(&cmptparm[0], 0, sizeof(cmptparm)); - memset(&lut_R[0], 0, sizeof(lut_R)); - memset(&lut_G[0], 0, sizeof(lut_G)); - memset(&lut_B[0], 0, sizeof(lut_B)); - - palette_len = Info_h->biClrUsed; - if ((palette_len == 0U) || (palette_len > 256U)) { - palette_len = 256U; - } - - /* Load palette */ - { - OPJ_UINT8 has_color = 0U; - for (i = 0; i < palette_len; i++) { - lut_B[i] = (OPJ_UINT8)getc(IN); - lut_G[i] = (OPJ_UINT8)getc(IN); - lut_R[i] = (OPJ_UINT8)getc(IN); - getc(IN); /* padding */ - has_color |= lut_B[i] ^ (lut_G[i] | lut_R[i]); - } - if(has_color) { - numcmpts = 3; - } - } - - - for(i = 0; i < numcmpts; i++) - { - cmptparm[i].prec = 8; - cmptparm[i].bpp = 8; - cmptparm[i].sgnd = 0; - cmptparm[i].dx = (OPJ_UINT32)parameters->subsampling_dx; - cmptparm[i].dy = (OPJ_UINT32)parameters->subsampling_dy; - cmptparm[i].w = width; - cmptparm[i].h = height; - } - /* create the image */ - image = opj_image_create(numcmpts, &cmptparm[0], (numcmpts == 1U) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB); - if(!image) - { - return NULL; - } - - /* set image offset and reference grid */ - image->x0 = (OPJ_UINT32)parameters->image_offset_x0; - image->y0 = (OPJ_UINT32)parameters->image_offset_y0; - image->x1 = image->x0 + (width - 1U) * (OPJ_UINT32)parameters->subsampling_dx + 1U; - image->y1 = image->y0 + (height - 1U) * (OPJ_UINT32)parameters->subsampling_dy + 1U; - - /* set image data */ - - /* Place the cursor at the beginning of the image information */ - fseek(IN, 0, SEEK_SET); - fseek(IN, (long)File_h->bfOffBits, SEEK_SET); - - pData = (OPJ_UINT8 *) calloc(1, width * height * sizeof(OPJ_UINT8)); - beyond = pData + width * height; - pix = (OPJ_UINT8 *)(beyond - width); - x = y = 0U; - while (y < height) - { - int c = getc(IN); - - if (c) { - int j; - OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN); - - for (j = 0; (j < c) && (x < width) && ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) { - *pix = c1; - } - } - else { - c = getc(IN); - if (c == 0x00) { /* EOL */ - x = 0; - ++y; - pix = pData + (height - y - 1U) * width + x; - } - else if (c == 0x01) { /* EOP */ - break; - } - else if (c == 0x02) { /* MOVE by dxdy */ - c = getc(IN); - x += (OPJ_UINT32)c; - c = getc(IN); - y += (OPJ_UINT32)c; - pix = pData + (height - y - 1U) * width + x; - } - else /* 03 .. 255 */ - { - int j; - for (j = 0; (j < c) && (x < width) && ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) - { - OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN); - *pix = c1; - } - if ((OPJ_UINT32)c & 1U) { /* skip padding byte */ - getc(IN); - } - } - } - }/* while() */ - - index = 0; - if (numcmpts == 1) { - opj_applyLUT8u_8u32s_C1R(pData, (OPJ_INT32)width, image->comps[0].data, (OPJ_INT32)width, lut_R, width, height); - } - else { - OPJ_INT32* pDst[] = { image->comps[0].data, image->comps[1].data, image->comps[2].data }; - OPJ_INT32 pDstStride[] = { (OPJ_INT32)width, (OPJ_INT32)width, (OPJ_INT32)width }; - OPJ_UINT8 const* pLUT[] = { lut_R, lut_G, lut_B }; - - opj_applyLUT8u_8u32s_C1P3R(pData, (OPJ_INT32)width, pDst, pDstStride, pLUT, width, height); - } - - free(pData); - return image; + OPJ_UINT32 x, y; + OPJ_UINT8 *pix; + const OPJ_UINT8 *beyond; + + beyond = pData + stride * height; + pix = pData; + x = y = 0U; + while (y < height) { + int c = getc(IN); + if (c == EOF) { + break; + } + + if (c) { /* encoded mode */ + int j; + OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN); + + for (j = 0; (j < c) && (x < width) && + ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) { + *pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU)); + } + } else { /* absolute mode */ + c = getc(IN); + if (c == EOF) { + break; + } + + if (c == 0x00) { /* EOL */ + x = 0; + y++; + pix = pData + y * stride; + } else if (c == 0x01) { /* EOP */ + break; + } else if (c == 0x02) { /* MOVE by dxdy */ + c = getc(IN); + x += (OPJ_UINT32)c; + c = getc(IN); + y += (OPJ_UINT32)c; + pix = pData + y * stride + x; + } else { /* 03 .. 255 : absolute mode */ + int j; + OPJ_UINT8 c1 = 0U; + + for (j = 0; (j < c) && (x < width) && + ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) { + if ((j & 1) == 0) { + c1 = (OPJ_UINT8)getc(IN); + } + *pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU)); + } + if (((c & 3) == 1) || ((c & 3) == 2)) { /* skip padding byte */ + getc(IN); + } + } + } + } /* while(y < height) */ + return OPJ_TRUE; } opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters) { - opj_image_t * image = NULL; - - FILE *IN; - OPJ_BITMAPFILEHEADER File_h; - OPJ_BITMAPINFOHEADER Info_h; - - IN = fopen(filename, "rb"); - if (!IN) - { - fprintf(stderr, "Failed to open %s for reading !!\n", filename); - return NULL; - } - - File_h.bfType = (OPJ_UINT16)getc(IN); - File_h.bfType = (OPJ_UINT16)((getc(IN) << 8) + File_h.bfType); - - if (File_h.bfType != 19778) { - fprintf(stderr,"Error, not a BMP file!\n"); - fclose(IN); - return NULL; - } - - /* FILE HEADER */ - /* ------------- */ - File_h.bfSize = (OPJ_UINT32)getc(IN); - File_h.bfSize = (OPJ_UINT32)(getc(IN) << 8) + File_h.bfSize; - File_h.bfSize = (OPJ_UINT32)(getc(IN) << 16) + File_h.bfSize; - File_h.bfSize = (OPJ_UINT32)(getc(IN) << 24) + File_h.bfSize; - - File_h.bfReserved1 = (OPJ_UINT16)getc(IN); - File_h.bfReserved1 = (OPJ_UINT16)((getc(IN) << 8) + File_h.bfReserved1); - - File_h.bfReserved2 = (OPJ_UINT16)getc(IN); - File_h.bfReserved2 = (OPJ_UINT16)((getc(IN) << 8) + File_h.bfReserved2); - - File_h.bfOffBits = (OPJ_UINT32)getc(IN); - File_h.bfOffBits = (OPJ_UINT32)(getc(IN) << 8) + File_h.bfOffBits; - File_h.bfOffBits = (OPJ_UINT32)(getc(IN) << 16) + File_h.bfOffBits; - File_h.bfOffBits = (OPJ_UINT32)(getc(IN) << 24) + File_h.bfOffBits; - - /* INFO HEADER */ - /* ------------- */ - - Info_h.biSize = (OPJ_UINT32)getc(IN); - Info_h.biSize = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biSize; - Info_h.biSize = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biSize; - Info_h.biSize = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biSize; - - if(Info_h.biSize != 40) { - fprintf(stderr,"Error, unknown BMP header size %d\n", Info_h.biSize); - fclose(IN); - return NULL; - } - - Info_h.biWidth = (OPJ_UINT32)getc(IN); - Info_h.biWidth = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biWidth; - Info_h.biWidth = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biWidth; - Info_h.biWidth = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biWidth; - - Info_h.biHeight = (OPJ_UINT32)getc(IN); - Info_h.biHeight = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biHeight; - Info_h.biHeight = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biHeight; - Info_h.biHeight = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biHeight; - - Info_h.biPlanes = (OPJ_UINT16)getc(IN); - Info_h.biPlanes = (OPJ_UINT16)((getc(IN) << 8) + Info_h.biPlanes); - - Info_h.biBitCount = (OPJ_UINT16)getc(IN); - Info_h.biBitCount = (OPJ_UINT16)((getc(IN) << 8) + Info_h.biBitCount); - - Info_h.biCompression = (OPJ_UINT32)getc(IN); - Info_h.biCompression = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biCompression; - Info_h.biCompression = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biCompression; - Info_h.biCompression = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biCompression; - - Info_h.biSizeImage = (OPJ_UINT32)getc(IN); - Info_h.biSizeImage = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biSizeImage; - Info_h.biSizeImage = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biSizeImage; - Info_h.biSizeImage = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biSizeImage; - - Info_h.biXpelsPerMeter = (OPJ_UINT32)getc(IN); - Info_h.biXpelsPerMeter = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biXpelsPerMeter; - Info_h.biXpelsPerMeter = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biXpelsPerMeter; - Info_h.biXpelsPerMeter = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biXpelsPerMeter; - - Info_h.biYpelsPerMeter = (OPJ_UINT32)getc(IN); - Info_h.biYpelsPerMeter = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biYpelsPerMeter; - Info_h.biYpelsPerMeter = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biYpelsPerMeter; - Info_h.biYpelsPerMeter = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biYpelsPerMeter; - - Info_h.biClrUsed = (OPJ_UINT32)getc(IN); - Info_h.biClrUsed = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biClrUsed; - Info_h.biClrUsed = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biClrUsed; - Info_h.biClrUsed = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biClrUsed; - - Info_h.biClrImportant = (OPJ_UINT32)getc(IN); - Info_h.biClrImportant = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biClrImportant; - Info_h.biClrImportant = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biClrImportant; - Info_h.biClrImportant = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biClrImportant; - - /* Read the data */ - if (Info_h.biBitCount == 24) { /*RGB */ - image = bmp24toimage(IN, &File_h, &Info_h, parameters); - } - else if (Info_h.biBitCount == 8 && Info_h.biCompression == 0) { /* RGB 8bpp Indexed */ - image = bmp8toimage(IN, &File_h, &Info_h, parameters); - } - else if (Info_h.biBitCount == 8 && Info_h.biCompression == 1) { /*RLE8*/ - image = bmprle8toimage(IN, &File_h, &Info_h, parameters); - } - else { - fprintf(stderr, "Other system than 24 bits/pixels or 8 bits (no RLE coding) is not yet implemented [%d]\n", Info_h.biBitCount); - } - fclose(IN); - return image; + opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */ + OPJ_UINT8 lut_R[256], lut_G[256], lut_B[256]; + OPJ_UINT8 const* pLUT[3]; + opj_image_t * image = NULL; + FILE *IN; + OPJ_BITMAPFILEHEADER File_h; + OPJ_BITMAPINFOHEADER Info_h; + OPJ_UINT32 i, palette_len, numcmpts = 1U; + OPJ_BOOL l_result = OPJ_FALSE; + OPJ_UINT8* pData = NULL; + OPJ_UINT32 stride; + + pLUT[0] = lut_R; + pLUT[1] = lut_G; + pLUT[2] = lut_B; + + IN = fopen(filename, "rb"); + if (!IN) { + fprintf(stderr, "Failed to open %s for reading !!\n", filename); + return NULL; + } + + if (!bmp_read_file_header(IN, &File_h)) { + fclose(IN); + return NULL; + } + if (!bmp_read_info_header(IN, &Info_h)) { + fclose(IN); + return NULL; + } + + /* Load palette */ + if (Info_h.biBitCount <= 8U) { + memset(&lut_R[0], 0, sizeof(lut_R)); + memset(&lut_G[0], 0, sizeof(lut_G)); + memset(&lut_B[0], 0, sizeof(lut_B)); + + palette_len = Info_h.biClrUsed; + if ((palette_len == 0U) && (Info_h.biBitCount <= 8U)) { + palette_len = (1U << Info_h.biBitCount); + } + if (palette_len > 256U) { + palette_len = 256U; + } + if (palette_len > 0U) { + OPJ_UINT8 has_color = 0U; + for (i = 0U; i < palette_len; i++) { + lut_B[i] = (OPJ_UINT8)getc(IN); + lut_G[i] = (OPJ_UINT8)getc(IN); + lut_R[i] = (OPJ_UINT8)getc(IN); + (void)getc(IN); /* padding */ + has_color |= (lut_B[i] ^ lut_G[i]) | (lut_G[i] ^ lut_R[i]); + } + if (has_color) { + numcmpts = 3U; + } + } + } else { + numcmpts = 3U; + if ((Info_h.biCompression == 3) && (Info_h.biAlphaMask != 0U)) { + numcmpts++; + } + } + + if (Info_h.biWidth == 0 || Info_h.biHeight == 0) { + fclose(IN); + return NULL; + } + + if (Info_h.biBitCount > (((OPJ_UINT32) - 1) - 31) / Info_h.biWidth) { + fclose(IN); + return NULL; + } + stride = ((Info_h.biWidth * Info_h.biBitCount + 31U) / 32U) * + 4U; /* rows are aligned on 32bits */ + if (Info_h.biBitCount == 4 && + Info_h.biCompression == 2) { /* RLE 4 gets decoded as 8 bits data for now... */ + if (8 > (((OPJ_UINT32) - 1) - 31) / Info_h.biWidth) { + fclose(IN); + return NULL; + } + stride = ((Info_h.biWidth * 8U + 31U) / 32U) * 4U; + } + + if (stride > ((OPJ_UINT32) - 1) / sizeof(OPJ_UINT8) / Info_h.biHeight) { + fclose(IN); + return NULL; + } + pData = (OPJ_UINT8 *) calloc(1, stride * Info_h.biHeight * sizeof(OPJ_UINT8)); + if (pData == NULL) { + fclose(IN); + return NULL; + } + /* Place the cursor at the beginning of the image information */ + fseek(IN, 0, SEEK_SET); + fseek(IN, (long)File_h.bfOffBits, SEEK_SET); + + switch (Info_h.biCompression) { + case 0: + case 3: + /* read raw data */ + l_result = bmp_read_raw_data(IN, pData, stride, Info_h.biWidth, + Info_h.biHeight); + break; + case 1: + /* read rle8 data */ + l_result = bmp_read_rle8_data(IN, pData, stride, Info_h.biWidth, + Info_h.biHeight); + break; + case 2: + /* read rle4 data */ + l_result = bmp_read_rle4_data(IN, pData, stride, Info_h.biWidth, + Info_h.biHeight); + break; + default: + fprintf(stderr, "Unsupported BMP compression\n"); + l_result = OPJ_FALSE; + break; + } + if (!l_result) { + free(pData); + fclose(IN); + return NULL; + } + + /* create the image */ + memset(&cmptparm[0], 0, sizeof(cmptparm)); + for (i = 0; i < 4U; i++) { + cmptparm[i].prec = 8; + cmptparm[i].bpp = 8; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = (OPJ_UINT32)parameters->subsampling_dx; + cmptparm[i].dy = (OPJ_UINT32)parameters->subsampling_dy; + cmptparm[i].w = Info_h.biWidth; + cmptparm[i].h = Info_h.biHeight; + } + + image = opj_image_create(numcmpts, &cmptparm[0], + (numcmpts == 1U) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB); + if (!image) { + fclose(IN); + free(pData); + return NULL; + } + if (numcmpts == 4U) { + image->comps[3].alpha = 1; + } + + /* set image offset and reference grid */ + image->x0 = (OPJ_UINT32)parameters->image_offset_x0; + image->y0 = (OPJ_UINT32)parameters->image_offset_y0; + image->x1 = image->x0 + (Info_h.biWidth - 1U) * (OPJ_UINT32) + parameters->subsampling_dx + 1U; + image->y1 = image->y0 + (Info_h.biHeight - 1U) * (OPJ_UINT32) + parameters->subsampling_dy + 1U; + + /* Read the data */ + if (Info_h.biBitCount == 24 && Info_h.biCompression == 0) { /*RGB */ + bmp24toimage(pData, stride, image); + } else if (Info_h.biBitCount == 8 && + Info_h.biCompression == 0) { /* RGB 8bpp Indexed */ + bmp8toimage(pData, stride, image, pLUT); + } else if (Info_h.biBitCount == 8 && Info_h.biCompression == 1) { /*RLE8*/ + bmp8toimage(pData, stride, image, pLUT); + } else if (Info_h.biBitCount == 4 && Info_h.biCompression == 2) { /*RLE4*/ + bmp8toimage(pData, stride, image, + pLUT); /* RLE 4 gets decoded as 8 bits data for now */ + } else if (Info_h.biBitCount == 32 && Info_h.biCompression == 0) { /* RGBX */ + bmpmask32toimage(pData, stride, image, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, + 0x00000000U); + } else if (Info_h.biBitCount == 32 && Info_h.biCompression == 3) { /* bitmask */ + bmpmask32toimage(pData, stride, image, Info_h.biRedMask, Info_h.biGreenMask, + Info_h.biBlueMask, Info_h.biAlphaMask); + } else if (Info_h.biBitCount == 16 && Info_h.biCompression == 0) { /* RGBX */ + bmpmask16toimage(pData, stride, image, 0x7C00U, 0x03E0U, 0x001FU, 0x0000U); + } else if (Info_h.biBitCount == 16 && Info_h.biCompression == 3) { /* bitmask */ + if ((Info_h.biRedMask == 0U) && (Info_h.biGreenMask == 0U) && + (Info_h.biBlueMask == 0U)) { + Info_h.biRedMask = 0xF800U; + Info_h.biGreenMask = 0x07E0U; + Info_h.biBlueMask = 0x001FU; + } + bmpmask16toimage(pData, stride, image, Info_h.biRedMask, Info_h.biGreenMask, + Info_h.biBlueMask, Info_h.biAlphaMask); + } else { + opj_image_destroy(image); + image = NULL; + fprintf(stderr, + "Other system than 24 bits/pixels or 8 bits (no RLE coding) is not yet implemented [%d]\n", + Info_h.biBitCount); + } + free(pData); + fclose(IN); + return image; } -int imagetobmp(opj_image_t * image, const char *outfile) { +int imagetobmp(opj_image_t * image, const char *outfile) +{ int w, h; int i, pad; FILE *fdest = NULL; @@ -588,54 +860,65 @@ int imagetobmp(opj_image_t * image, const char *outfile) { /* FILE HEADER */ /* ------------- */ fprintf(fdest, "%c%c%c%c", - (OPJ_UINT8) (h * w * 3 + 3 * h * (w % 2) + 54) & 0xff, - (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 8) & 0xff, - (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 16) & 0xff, - (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff,((54) >> 16) & 0xff, ((54) >> 24) & 0xff); + (OPJ_UINT8)(h * w * 3 + 3 * h * (w % 2) + 54) & 0xff, + (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2) + 54) >> 8) & 0xff, + (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2) + 54) >> 16) & 0xff, + (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2) + 54) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, + ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff, ((54) >> 16) & 0xff, + ((54) >> 24) & 0xff); /* INFO HEADER */ /* ------------- */ - fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff, ((40) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) ((w) & 0xff), - (OPJ_UINT8) ((w) >> 8) & 0xff, - (OPJ_UINT8) ((w) >> 16) & 0xff, - (OPJ_UINT8) ((w) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) ((h) & 0xff), - (OPJ_UINT8) ((h) >> 8) & 0xff, - (OPJ_UINT8) ((h) >> 16) & 0xff, - (OPJ_UINT8) ((h) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff, + ((40) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((w) & 0xff), + (OPJ_UINT8)((w) >> 8) & 0xff, + (OPJ_UINT8)((w) >> 16) & 0xff, + (OPJ_UINT8)((w) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((h) & 0xff), + (OPJ_UINT8)((h) >> 8) & 0xff, + (OPJ_UINT8)((h) >> 16) & 0xff, + (OPJ_UINT8)((h) >> 24) & 0xff); fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff); fprintf(fdest, "%c%c", (24) & 0xff, ((24) >> 8) & 0xff); - fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) (3 * h * w + 3 * h * (w % 2)) & 0xff, - (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2)) >> 8) & 0xff, - (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2)) >> 16) & 0xff, - (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2)) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, + ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)(3 * h * w + 3 * h * (w % 2)) & 0xff, + (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2)) >> 8) & 0xff, + (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2)) >> 16) & 0xff, + (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2)) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, + ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, + ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, + ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, + ((0) >> 24) & 0xff); if (image->comps[0].prec > 8) { adjustR = (int)image->comps[0].prec - 8; - printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec); - } - else + printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", + image->comps[0].prec); + } else { adjustR = 0; + } if (image->comps[1].prec > 8) { adjustG = (int)image->comps[1].prec - 8; - printf("BMP CONVERSION: Truncating component 1 from %d bits to 8 bits\n", image->comps[1].prec); - } - else + printf("BMP CONVERSION: Truncating component 1 from %d bits to 8 bits\n", + image->comps[1].prec); + } else { adjustG = 0; + } if (image->comps[2].prec > 8) { adjustB = (int)image->comps[2].prec - 8; - printf("BMP CONVERSION: Truncating component 2 from %d bits to 8 bits\n", image->comps[2].prec); - } - else + printf("BMP CONVERSION: Truncating component 2 from %d bits to 8 bits\n", + image->comps[2].prec); + } else { adjustB = 0; + } for (i = 0; i < w * h; i++) { OPJ_UINT8 rc, gc, bc; @@ -643,37 +926,54 @@ int imagetobmp(opj_image_t * image, const char *outfile) { r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)]; r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); - r = ((r >> adjustR)+((r >> (adjustR-1))%2)); - if(r > 255) r = 255; else if(r < 0) r = 0; + r = ((r >> adjustR) + ((r >> (adjustR - 1)) % 2)); + if (r > 255) { + r = 255; + } else if (r < 0) { + r = 0; + } rc = (OPJ_UINT8)r; g = image->comps[1].data[w * h - ((i) / (w) + 1) * w + (i) % (w)]; g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); - g = ((g >> adjustG)+((g >> (adjustG-1))%2)); - if(g > 255) g = 255; else if(g < 0) g = 0; + g = ((g >> adjustG) + ((g >> (adjustG - 1)) % 2)); + if (g > 255) { + g = 255; + } else if (g < 0) { + g = 0; + } gc = (OPJ_UINT8)g; b = image->comps[2].data[w * h - ((i) / (w) + 1) * w + (i) % (w)]; b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); - b = ((b >> adjustB)+((b >> (adjustB-1))%2)); - if(b > 255) b = 255; else if(b < 0) b = 0; + b = ((b >> adjustB) + ((b >> (adjustB - 1)) % 2)); + if (b > 255) { + b = 255; + } else if (b < 0) { + b = 0; + } bc = (OPJ_UINT8)b; fprintf(fdest, "%c%c%c", bc, gc, rc); if ((i + 1) % w == 0) { - for (pad = (3 * w) % 4 ? 4 - (3 * w) % 4 : 0; pad > 0; pad--) /* ADD */ + for (pad = ((3 * w) % 4) ? (4 - (3 * w) % 4) : 0; pad > 0; pad--) { /* ADD */ fprintf(fdest, "%c", 0); + } } } fclose(fdest); - } else { /* Gray-scale */ + } else { /* Gray-scale */ /* -->> -->> -->> -->> 8 bits non code (Gray scale) <<-- <<-- <<-- <<-- */ fdest = fopen(outfile, "wb"); + if (!fdest) { + fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile); + return 1; + } w = (int)image->comps[0].w; h = (int)image->comps[0].h; @@ -681,43 +981,52 @@ int imagetobmp(opj_image_t * image, const char *outfile) { /* FILE HEADER */ /* ------------- */ - fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) (h * w + 54 + 1024 + h * (w % 2)) & 0xff, - (OPJ_UINT8) ((h * w + 54 + 1024 + h * (w % 2)) >> 8) & 0xff, - (OPJ_UINT8) ((h * w + 54 + 1024 + h * (w % 2)) >> 16) & 0xff, - (OPJ_UINT8) ((h * w + 54 + 1024 + w * (w % 2)) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)(h * w + 54 + 1024 + h * (w % 2)) & 0xff, + (OPJ_UINT8)((h * w + 54 + 1024 + h * (w % 2)) >> 8) & 0xff, + (OPJ_UINT8)((h * w + 54 + 1024 + h * (w % 2)) >> 16) & 0xff, + (OPJ_UINT8)((h * w + 54 + 1024 + w * (w % 2)) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, + ((0) >> 24) & 0xff); fprintf(fdest, "%c%c%c%c", (54 + 1024) & 0xff, ((54 + 1024) >> 8) & 0xff, ((54 + 1024) >> 16) & 0xff, ((54 + 1024) >> 24) & 0xff); /* INFO HEADER */ /* ------------- */ - fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff, ((40) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) ((w) & 0xff), - (OPJ_UINT8) ((w) >> 8) & 0xff, - (OPJ_UINT8) ((w) >> 16) & 0xff, - (OPJ_UINT8) ((w) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) ((h) & 0xff), - (OPJ_UINT8) ((h) >> 8) & 0xff, - (OPJ_UINT8) ((h) >> 16) & 0xff, - (OPJ_UINT8) ((h) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff, + ((40) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((w) & 0xff), + (OPJ_UINT8)((w) >> 8) & 0xff, + (OPJ_UINT8)((w) >> 16) & 0xff, + (OPJ_UINT8)((w) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((h) & 0xff), + (OPJ_UINT8)((h) >> 8) & 0xff, + (OPJ_UINT8)((h) >> 16) & 0xff, + (OPJ_UINT8)((h) >> 24) & 0xff); fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff); fprintf(fdest, "%c%c", (8) & 0xff, ((8) >> 8) & 0xff); - fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) (h * w + h * (w % 2)) & 0xff, - (OPJ_UINT8) ((h * w + h * (w % 2)) >> 8) & 0xff, - (OPJ_UINT8) ((h * w + h * (w % 2)) >> 16) & 0xff, - (OPJ_UINT8) ((h * w + h * (w % 2)) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, ((256) >> 16) & 0xff, ((256) >> 24) & 0xff); - fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, ((256) >> 16) & 0xff, ((256) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, + ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)(h * w + h * (w % 2)) & 0xff, + (OPJ_UINT8)((h * w + h * (w % 2)) >> 8) & 0xff, + (OPJ_UINT8)((h * w + h * (w % 2)) >> 16) & 0xff, + (OPJ_UINT8)((h * w + h * (w % 2)) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, + ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, + ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, + ((256) >> 16) & 0xff, ((256) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, + ((256) >> 16) & 0xff, ((256) >> 24) & 0xff); if (image->comps[0].prec > 8) { adjustR = (int)image->comps[0].prec - 8; - printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec); - }else + printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", + image->comps[0].prec); + } else { adjustR = 0; + } for (i = 0; i < 256; i++) { fprintf(fdest, "%c%c%c%c", i, i, i, 0); @@ -728,14 +1037,19 @@ int imagetobmp(opj_image_t * image, const char *outfile) { r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)]; r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); - r = ((r >> adjustR)+((r >> (adjustR-1))%2)); - if(r > 255) r = 255; else if(r < 0) r = 0; + r = ((r >> adjustR) + ((r >> (adjustR - 1)) % 2)); + if (r > 255) { + r = 255; + } else if (r < 0) { + r = 0; + } fprintf(fdest, "%c", (OPJ_UINT8)r); if ((i + 1) % w == 0) { - for (pad = w % 4 ? 4 - w % 4 : 0; pad > 0; pad--) /* ADD */ + for (pad = (w % 4) ? (4 - w % 4) : 0; pad > 0; pad--) { /* ADD */ fprintf(fdest, "%c", 0); + } } } fclose(fdest);