Fix some typos (found by `codespell` and `typos`)
[openjpeg.git] / src / bin / jp2 / convertbmp.c
index 7f570203a80e36eb44e78d813dc7c8e059a52ead..3ef9915fe1a33b0c7a5962c4e31655be8d68d24f 100644 (file)
@@ -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
 #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;           /* Height 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] = pLUT_R[idx];
-                       pG[x] = pLUT_G[idx];
-                       pB[x] = pLUT_B[idx];
-               }
-               pSrc += srcStride;
-               pR += pDstStride[0];
-               pG += pDstStride[1];
-               pB += pDstStride[2];
-       }
+    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)
+{
+    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].prec = redPrec;
+    image->comps[1].prec = greenPrec;
+    image->comps[2].prec = bluePrec;
+    if (hasAlpha) {
+        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].prec = redPrec;
+    image->comps[1].prec = greenPrec;
+    image->comps[2].prec = bluePrec;
+    if (hasAlpha) {
+        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->biBitCount == 0) {
+        fprintf(stderr, "Error, invalid biBitCount %d\n", 0);
+        return OPJ_FALSE;
+    }
+
+    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;
+
+        if (!header->biRedMask) {
+            fprintf(stderr, "Error, invalid red mask value %d\n", header->biRedMask);
+            return OPJ_FALSE;
+        }
+
+        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;
+
+        if (!header->biGreenMask) {
+            fprintf(stderr, "Error, invalid green mask value %d\n", header->biGreenMask);
+            return OPJ_FALSE;
+        }
+
+        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;
+
+        if (!header->biBlueMask) {
+            fprintf(stderr, "Error, invalid blue mask value %d\n", header->biBlueMask);
+            return OPJ_FALSE;
+        }
+
+        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, written;
+    OPJ_UINT8 *pix;
+    const OPJ_UINT8 *beyond;
+
+    beyond = pData + stride * height;
+    pix = pData;
+
+    x = y = written = 0U;
+    while (y < height) {
+        int c = getc(IN);
+        if (c == EOF) {
+            return OPJ_FALSE;
+        }
+
+        if (c) {
+            int j, c1_int;
+            OPJ_UINT8 c1;
+
+            c1_int = getc(IN);
+            if (c1_int == EOF) {
+                return OPJ_FALSE;
+            }
+            c1 = (OPJ_UINT8)c1_int;
+
+            for (j = 0; (j < c) && (x < width) &&
+                    ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
+                *pix = c1;
+                written++;
+            }
+        } else {
+            c = getc(IN);
+            if (c == EOF) {
+                return OPJ_FALSE;
+            }
+
+            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);
+                if (c == EOF) {
+                    return OPJ_FALSE;
+                }
+                x += (OPJ_UINT32)c;
+                c = getc(IN);
+                if (c == EOF) {
+                    return OPJ_FALSE;
+                }
+                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++) {
+                    int c1_int;
+                    OPJ_UINT8 c1;
+                    c1_int = getc(IN);
+                    if (c1_int == EOF) {
+                        return OPJ_FALSE;
+                    }
+                    c1 = (OPJ_UINT8)c1_int;
+                    *pix = c1;
+                    written++;
+                }
+                if ((OPJ_UINT32)c & 1U) { /* skip padding byte */
+                    c = getc(IN);
+                    if (c == EOF) {
+                        return OPJ_FALSE;
+                    }
+                }
+            }
+        }
+    }/* while() */
+
+    if (written != width * height) {
+        fprintf(stderr, "warning, image's actual size does not match advertised one\n");
+        return OPJ_FALSE;
+    }
+
+    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, written;
+    OPJ_UINT8 *pix;
+    const OPJ_UINT8 *beyond;
+
+    beyond = pData + stride * height;
+    pix = pData;
+    x = y = written = 0U;
+    while (y < height) {
+        int c = getc(IN);
+        if (c == EOF) {
+            return OPJ_FALSE;
+        }
+
+        if (c) { /* encoded mode */
+            int j, c1_int;
+            OPJ_UINT8 c1;
+
+            c1_int = getc(IN);
+            if (c1_int == EOF) {
+                return OPJ_FALSE;
+            }
+            c1 = (OPJ_UINT8)c1_int;
+
+            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));
+                written++;
+            }
+        } else { /* absolute mode */
+            c = getc(IN);
+            if (c == EOF) {
+                return OPJ_FALSE;
+            }
+
+            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);
+                if (c == EOF) {
+                    return OPJ_FALSE;
+                }
+                x += (OPJ_UINT32)c;
+                c = getc(IN);
+                if (c == EOF) {
+                    return OPJ_FALSE;
+                }
+                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) {
+                        int c1_int;
+                        c1_int = getc(IN);
+                        if (c1_int == EOF) {
+                            return OPJ_FALSE;
+                        }
+                        c1 = (OPJ_UINT8)c1_int;
+                    }
+                    *pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU));
+                    written++;
+                }
+                if (((c & 3) == 1) || ((c & 3) == 2)) { /* skip padding byte */
+                    c = getc(IN);
+                    if (c == EOF) {
+                        return OPJ_FALSE;
+                    }
+                }
+            }
+        }
+    }  /* while(y < height) */
+    if (written != width * height) {
+        fprintf(stderr, "warning, image's actual size does not match advertised one\n");
+        return OPJ_FALSE;
+    }
+    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, sizeof(OPJ_UINT8) * stride * Info_h.biHeight);
+    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].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 */
+        if ((Info_h.biRedMask == 0U) && (Info_h.biGreenMask == 0U) &&
+                (Info_h.biBlueMask == 0U)) {
+            Info_h.biRedMask   = 0x00FF0000U;
+            Info_h.biGreenMask = 0x0000FF00U;
+            Info_h.biBlueMask  = 0x000000FFU;
+        }
+        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;
     int adjustR, adjustG, adjustB;
 
     if (image->comps[0].prec < 8) {
-        fprintf(stderr, "Unsupported number of components: %d\n", image->comps[0].prec);
+        fprintf(stderr, "imagetobmp: Unsupported precision: %d\n",
+                image->comps[0].prec);
         return 1;
     }
     if (image->numcomps >= 3 && image->comps[0].dx == image->comps[1].dx
@@ -568,7 +919,9 @@ int imagetobmp(opj_image_t * image, const char *outfile) {
             && image->comps[0].dy == image->comps[1].dy
             && image->comps[1].dy == image->comps[2].dy
             && image->comps[0].prec == image->comps[1].prec
-            && image->comps[1].prec == image->comps[2].prec) {
+            && image->comps[1].prec == image->comps[2].prec
+            && image->comps[0].sgnd == image->comps[1].sgnd
+            && image->comps[1].sgnd == image->comps[2].sgnd) {
 
         /* -->> -->> -->> -->>
         24 bits color
@@ -588,54 +941,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 +1007,64 @@ 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;
+            if (adjustR > 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;
+            if (adjustG > 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;
+            if (adjustB > 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;
+        }
+        if (image->numcomps > 1) {
+            fprintf(stderr, "imagetobmp: only first component of %d is used.\n",
+                    image->numcomps);
+        }
         w = (int)image->comps[0].w;
         h = (int)image->comps[0].h;
 
@@ -681,43 +1072,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 +1128,21 @@ 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;
+            if (adjustR > 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);