opj_compress: improve help message regarding new IMF switch
[openjpeg.git] / src / bin / jp2 / convertbmp.c
1 /*
2  * The copyright in this software is being made available under the 2-clauses
3  * BSD License, included below. This software may be subject to other third
4  * party and contributor rights, including patent rights, and no such rights
5  * are granted under this license.
6  *
7  * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
8  * Copyright (c) 2002-2014, Professor Benoit Macq
9  * Copyright (c) 2001-2003, David Janssens
10  * Copyright (c) 2002-2003, Yannick Verschueren
11  * Copyright (c) 2003-2007, Francois-Olivier Devaux
12  * Copyright (c) 2003-2014, Antonin Descampe
13  * Copyright (c) 2005, Herve Drolon, FreeImage Team
14  * Copyright (c) 2006-2007, Parvatha Elangovan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 #include "opj_apps_config.h"
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44
45 #include "openjpeg.h"
46 #include "convert.h"
47
48 typedef struct {
49     OPJ_UINT16 bfType;      /* 'BM' for Bitmap (19776) */
50     OPJ_UINT32 bfSize;      /* Size of the file        */
51     OPJ_UINT16 bfReserved1; /* Reserved : 0            */
52     OPJ_UINT16 bfReserved2; /* Reserved : 0            */
53     OPJ_UINT32 bfOffBits;   /* Offset                  */
54 } OPJ_BITMAPFILEHEADER;
55
56 typedef struct {
57     OPJ_UINT32 biSize;             /* Size of the structure in bytes */
58     OPJ_UINT32 biWidth;            /* Width of the image in pixels */
59     OPJ_UINT32 biHeight;           /* Height of the image in pixels */
60     OPJ_UINT16 biPlanes;           /* 1 */
61     OPJ_UINT16 biBitCount;         /* Number of color bits by pixels */
62     OPJ_UINT32 biCompression;      /* Type of encoding 0: none 1: RLE8 2: RLE4 */
63     OPJ_UINT32 biSizeImage;        /* Size of the image in bytes */
64     OPJ_UINT32 biXpelsPerMeter;    /* Horizontal (X) resolution in pixels/meter */
65     OPJ_UINT32 biYpelsPerMeter;    /* Vertical (Y) resolution in pixels/meter */
66     OPJ_UINT32 biClrUsed;          /* Number of color used in the image (0: ALL) */
67     OPJ_UINT32 biClrImportant;     /* Number of important color (0: ALL) */
68     OPJ_UINT32 biRedMask;          /* Red channel bit mask */
69     OPJ_UINT32 biGreenMask;        /* Green channel bit mask */
70     OPJ_UINT32 biBlueMask;         /* Blue channel bit mask */
71     OPJ_UINT32 biAlphaMask;        /* Alpha channel bit mask */
72     OPJ_UINT32 biColorSpaceType;   /* Color space type */
73     OPJ_UINT8  biColorSpaceEP[36]; /* Color space end points */
74     OPJ_UINT32 biRedGamma;         /* Red channel gamma */
75     OPJ_UINT32 biGreenGamma;       /* Green channel gamma */
76     OPJ_UINT32 biBlueGamma;        /* Blue channel gamma */
77     OPJ_UINT32 biIntent;           /* Intent */
78     OPJ_UINT32 biIccProfileData;   /* ICC profile data */
79     OPJ_UINT32 biIccProfileSize;   /* ICC profile size */
80     OPJ_UINT32 biReserved;         /* Reserved */
81 } OPJ_BITMAPINFOHEADER;
82
83 static void opj_applyLUT8u_8u32s_C1R(
84     OPJ_UINT8 const* pSrc, OPJ_INT32 srcStride,
85     OPJ_INT32* pDst, OPJ_INT32 dstStride,
86     OPJ_UINT8 const* pLUT,
87     OPJ_UINT32 width, OPJ_UINT32 height)
88 {
89     OPJ_UINT32 y;
90
91     for (y = height; y != 0U; --y) {
92         OPJ_UINT32 x;
93
94         for (x = 0; x < width; x++) {
95             pDst[x] = (OPJ_INT32)pLUT[pSrc[x]];
96         }
97         pSrc += srcStride;
98         pDst += dstStride;
99     }
100 }
101
102 static void opj_applyLUT8u_8u32s_C1P3R(
103     OPJ_UINT8 const* pSrc, OPJ_INT32 srcStride,
104     OPJ_INT32* const* pDst, OPJ_INT32 const* pDstStride,
105     OPJ_UINT8 const* const* pLUT,
106     OPJ_UINT32 width, OPJ_UINT32 height)
107 {
108     OPJ_UINT32 y;
109     OPJ_INT32* pR = pDst[0];
110     OPJ_INT32* pG = pDst[1];
111     OPJ_INT32* pB = pDst[2];
112     OPJ_UINT8 const* pLUT_R = pLUT[0];
113     OPJ_UINT8 const* pLUT_G = pLUT[1];
114     OPJ_UINT8 const* pLUT_B = pLUT[2];
115
116     for (y = height; y != 0U; --y) {
117         OPJ_UINT32 x;
118
119         for (x = 0; x < width; x++) {
120             OPJ_UINT8 idx = pSrc[x];
121             pR[x] = (OPJ_INT32)pLUT_R[idx];
122             pG[x] = (OPJ_INT32)pLUT_G[idx];
123             pB[x] = (OPJ_INT32)pLUT_B[idx];
124         }
125         pSrc += srcStride;
126         pR += pDstStride[0];
127         pG += pDstStride[1];
128         pB += pDstStride[2];
129     }
130 }
131
132 static void bmp24toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride,
133                          opj_image_t* image)
134 {
135     int index;
136     OPJ_UINT32 width, height;
137     OPJ_UINT32 x, y;
138     const OPJ_UINT8 *pSrc = NULL;
139
140     width  = image->comps[0].w;
141     height = image->comps[0].h;
142
143     index = 0;
144     pSrc = pData + (height - 1U) * stride;
145     for (y = 0; y < height; y++) {
146         for (x = 0; x < width; x++) {
147             image->comps[0].data[index] = (OPJ_INT32)pSrc[3 * x + 2]; /* R */
148             image->comps[1].data[index] = (OPJ_INT32)pSrc[3 * x + 1]; /* G */
149             image->comps[2].data[index] = (OPJ_INT32)pSrc[3 * x + 0]; /* B */
150             index++;
151         }
152         pSrc -= stride;
153     }
154 }
155
156 static void bmp_mask_get_shift_and_prec(OPJ_UINT32 mask, OPJ_UINT32* shift,
157                                         OPJ_UINT32* prec)
158 {
159     OPJ_UINT32 l_shift, l_prec;
160
161     l_shift = l_prec = 0U;
162
163     if (mask != 0U) {
164         while ((mask & 1U) == 0U) {
165             mask >>= 1;
166             l_shift++;
167         }
168         while (mask & 1U) {
169             mask >>= 1;
170             l_prec++;
171         }
172     }
173     *shift = l_shift;
174     *prec = l_prec;
175 }
176
177 static void bmpmask32toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride,
178                              opj_image_t* image, OPJ_UINT32 redMask, OPJ_UINT32 greenMask,
179                              OPJ_UINT32 blueMask, OPJ_UINT32 alphaMask)
180 {
181     int index;
182     OPJ_UINT32 width, height;
183     OPJ_UINT32 x, y;
184     const OPJ_UINT8 *pSrc = NULL;
185     OPJ_BOOL hasAlpha;
186     OPJ_UINT32 redShift,   redPrec;
187     OPJ_UINT32 greenShift, greenPrec;
188     OPJ_UINT32 blueShift,  bluePrec;
189     OPJ_UINT32 alphaShift, alphaPrec;
190
191     width  = image->comps[0].w;
192     height = image->comps[0].h;
193
194     hasAlpha = image->numcomps > 3U;
195
196     bmp_mask_get_shift_and_prec(redMask,   &redShift,   &redPrec);
197     bmp_mask_get_shift_and_prec(greenMask, &greenShift, &greenPrec);
198     bmp_mask_get_shift_and_prec(blueMask,  &blueShift,  &bluePrec);
199     bmp_mask_get_shift_and_prec(alphaMask, &alphaShift, &alphaPrec);
200
201     image->comps[0].bpp = redPrec;
202     image->comps[0].prec = redPrec;
203     image->comps[1].bpp = greenPrec;
204     image->comps[1].prec = greenPrec;
205     image->comps[2].bpp = bluePrec;
206     image->comps[2].prec = bluePrec;
207     if (hasAlpha) {
208         image->comps[3].bpp = alphaPrec;
209         image->comps[3].prec = alphaPrec;
210     }
211
212     index = 0;
213     pSrc = pData + (height - 1U) * stride;
214     for (y = 0; y < height; y++) {
215         for (x = 0; x < width; x++) {
216             OPJ_UINT32 value = 0U;
217
218             value |= ((OPJ_UINT32)pSrc[4 * x + 0]) <<  0;
219             value |= ((OPJ_UINT32)pSrc[4 * x + 1]) <<  8;
220             value |= ((OPJ_UINT32)pSrc[4 * x + 2]) << 16;
221             value |= ((OPJ_UINT32)pSrc[4 * x + 3]) << 24;
222
223             image->comps[0].data[index] = (OPJ_INT32)((value & redMask)   >>
224                                           redShift);   /* R */
225             image->comps[1].data[index] = (OPJ_INT32)((value & greenMask) >>
226                                           greenShift); /* G */
227             image->comps[2].data[index] = (OPJ_INT32)((value & blueMask)  >>
228                                           blueShift);  /* B */
229             if (hasAlpha) {
230                 image->comps[3].data[index] = (OPJ_INT32)((value & alphaMask)  >>
231                                               alphaShift);  /* A */
232             }
233             index++;
234         }
235         pSrc -= stride;
236     }
237 }
238
239 static void bmpmask16toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride,
240                              opj_image_t* image, OPJ_UINT32 redMask, OPJ_UINT32 greenMask,
241                              OPJ_UINT32 blueMask, OPJ_UINT32 alphaMask)
242 {
243     int index;
244     OPJ_UINT32 width, height;
245     OPJ_UINT32 x, y;
246     const OPJ_UINT8 *pSrc = NULL;
247     OPJ_BOOL hasAlpha;
248     OPJ_UINT32 redShift,   redPrec;
249     OPJ_UINT32 greenShift, greenPrec;
250     OPJ_UINT32 blueShift,  bluePrec;
251     OPJ_UINT32 alphaShift, alphaPrec;
252
253     width  = image->comps[0].w;
254     height = image->comps[0].h;
255
256     hasAlpha = image->numcomps > 3U;
257
258     bmp_mask_get_shift_and_prec(redMask,   &redShift,   &redPrec);
259     bmp_mask_get_shift_and_prec(greenMask, &greenShift, &greenPrec);
260     bmp_mask_get_shift_and_prec(blueMask,  &blueShift,  &bluePrec);
261     bmp_mask_get_shift_and_prec(alphaMask, &alphaShift, &alphaPrec);
262
263     image->comps[0].bpp = redPrec;
264     image->comps[0].prec = redPrec;
265     image->comps[1].bpp = greenPrec;
266     image->comps[1].prec = greenPrec;
267     image->comps[2].bpp = bluePrec;
268     image->comps[2].prec = bluePrec;
269     if (hasAlpha) {
270         image->comps[3].bpp = alphaPrec;
271         image->comps[3].prec = alphaPrec;
272     }
273
274     index = 0;
275     pSrc = pData + (height - 1U) * stride;
276     for (y = 0; y < height; y++) {
277         for (x = 0; x < width; x++) {
278             OPJ_UINT32 value = 0U;
279
280             value |= ((OPJ_UINT32)pSrc[2 * x + 0]) <<  0;
281             value |= ((OPJ_UINT32)pSrc[2 * x + 1]) <<  8;
282
283             image->comps[0].data[index] = (OPJ_INT32)((value & redMask)   >>
284                                           redShift);   /* R */
285             image->comps[1].data[index] = (OPJ_INT32)((value & greenMask) >>
286                                           greenShift); /* G */
287             image->comps[2].data[index] = (OPJ_INT32)((value & blueMask)  >>
288                                           blueShift);  /* B */
289             if (hasAlpha) {
290                 image->comps[3].data[index] = (OPJ_INT32)((value & alphaMask)  >>
291                                               alphaShift);  /* A */
292             }
293             index++;
294         }
295         pSrc -= stride;
296     }
297 }
298
299 static opj_image_t* bmp8toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride,
300                                 opj_image_t* image, OPJ_UINT8 const* const* pLUT)
301 {
302     OPJ_UINT32 width, height;
303     const OPJ_UINT8 *pSrc = NULL;
304
305     width  = image->comps[0].w;
306     height = image->comps[0].h;
307
308     pSrc = pData + (height - 1U) * stride;
309     if (image->numcomps == 1U) {
310         opj_applyLUT8u_8u32s_C1R(pSrc, -(OPJ_INT32)stride, image->comps[0].data,
311                                  (OPJ_INT32)width, pLUT[0], width, height);
312     } else {
313         OPJ_INT32* pDst[3];
314         OPJ_INT32  pDstStride[3];
315
316         pDst[0] = image->comps[0].data;
317         pDst[1] = image->comps[1].data;
318         pDst[2] = image->comps[2].data;
319         pDstStride[0] = (OPJ_INT32)width;
320         pDstStride[1] = (OPJ_INT32)width;
321         pDstStride[2] = (OPJ_INT32)width;
322         opj_applyLUT8u_8u32s_C1P3R(pSrc, -(OPJ_INT32)stride, pDst, pDstStride, pLUT,
323                                    width, height);
324     }
325     return image;
326 }
327
328 static OPJ_BOOL bmp_read_file_header(FILE* IN, OPJ_BITMAPFILEHEADER* header)
329 {
330     header->bfType  = (OPJ_UINT16)getc(IN);
331     header->bfType |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8);
332
333     if (header->bfType != 19778) {
334         fprintf(stderr, "Error, not a BMP file!\n");
335         return OPJ_FALSE;
336     }
337
338     /* FILE HEADER */
339     /* ------------- */
340     header->bfSize  = (OPJ_UINT32)getc(IN);
341     header->bfSize |= (OPJ_UINT32)getc(IN) << 8;
342     header->bfSize |= (OPJ_UINT32)getc(IN) << 16;
343     header->bfSize |= (OPJ_UINT32)getc(IN) << 24;
344
345     header->bfReserved1  = (OPJ_UINT16)getc(IN);
346     header->bfReserved1 |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8);
347
348     header->bfReserved2  = (OPJ_UINT16)getc(IN);
349     header->bfReserved2 |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8);
350
351     header->bfOffBits  = (OPJ_UINT32)getc(IN);
352     header->bfOffBits |= (OPJ_UINT32)getc(IN) << 8;
353     header->bfOffBits |= (OPJ_UINT32)getc(IN) << 16;
354     header->bfOffBits |= (OPJ_UINT32)getc(IN) << 24;
355     return OPJ_TRUE;
356 }
357 static OPJ_BOOL bmp_read_info_header(FILE* IN, OPJ_BITMAPINFOHEADER* header)
358 {
359     memset(header, 0, sizeof(*header));
360     /* INFO HEADER */
361     /* ------------- */
362     header->biSize  = (OPJ_UINT32)getc(IN);
363     header->biSize |= (OPJ_UINT32)getc(IN) << 8;
364     header->biSize |= (OPJ_UINT32)getc(IN) << 16;
365     header->biSize |= (OPJ_UINT32)getc(IN) << 24;
366
367     switch (header->biSize) {
368     case 12U:  /* BITMAPCOREHEADER */
369     case 40U:  /* BITMAPINFOHEADER */
370     case 52U:  /* BITMAPV2INFOHEADER */
371     case 56U:  /* BITMAPV3INFOHEADER */
372     case 108U: /* BITMAPV4HEADER */
373     case 124U: /* BITMAPV5HEADER */
374         break;
375     default:
376         fprintf(stderr, "Error, unknown BMP header size %d\n", header->biSize);
377         return OPJ_FALSE;
378     }
379
380     header->biWidth  = (OPJ_UINT32)getc(IN);
381     header->biWidth |= (OPJ_UINT32)getc(IN) << 8;
382     header->biWidth |= (OPJ_UINT32)getc(IN) << 16;
383     header->biWidth |= (OPJ_UINT32)getc(IN) << 24;
384
385     header->biHeight  = (OPJ_UINT32)getc(IN);
386     header->biHeight |= (OPJ_UINT32)getc(IN) << 8;
387     header->biHeight |= (OPJ_UINT32)getc(IN) << 16;
388     header->biHeight |= (OPJ_UINT32)getc(IN) << 24;
389
390     header->biPlanes  = (OPJ_UINT16)getc(IN);
391     header->biPlanes |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8);
392
393     header->biBitCount  = (OPJ_UINT16)getc(IN);
394     header->biBitCount |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8);
395     if (header->biBitCount == 0) {
396         fprintf(stderr, "Error, invalid biBitCount %d\n", 0);
397         return OPJ_FALSE;
398     }
399
400     if (header->biSize >= 40U) {
401         header->biCompression  = (OPJ_UINT32)getc(IN);
402         header->biCompression |= (OPJ_UINT32)getc(IN) << 8;
403         header->biCompression |= (OPJ_UINT32)getc(IN) << 16;
404         header->biCompression |= (OPJ_UINT32)getc(IN) << 24;
405
406         header->biSizeImage  = (OPJ_UINT32)getc(IN);
407         header->biSizeImage |= (OPJ_UINT32)getc(IN) << 8;
408         header->biSizeImage |= (OPJ_UINT32)getc(IN) << 16;
409         header->biSizeImage |= (OPJ_UINT32)getc(IN) << 24;
410
411         header->biXpelsPerMeter  = (OPJ_UINT32)getc(IN);
412         header->biXpelsPerMeter |= (OPJ_UINT32)getc(IN) << 8;
413         header->biXpelsPerMeter |= (OPJ_UINT32)getc(IN) << 16;
414         header->biXpelsPerMeter |= (OPJ_UINT32)getc(IN) << 24;
415
416         header->biYpelsPerMeter  = (OPJ_UINT32)getc(IN);
417         header->biYpelsPerMeter |= (OPJ_UINT32)getc(IN) << 8;
418         header->biYpelsPerMeter |= (OPJ_UINT32)getc(IN) << 16;
419         header->biYpelsPerMeter |= (OPJ_UINT32)getc(IN) << 24;
420
421         header->biClrUsed  = (OPJ_UINT32)getc(IN);
422         header->biClrUsed |= (OPJ_UINT32)getc(IN) << 8;
423         header->biClrUsed |= (OPJ_UINT32)getc(IN) << 16;
424         header->biClrUsed |= (OPJ_UINT32)getc(IN) << 24;
425
426         header->biClrImportant  = (OPJ_UINT32)getc(IN);
427         header->biClrImportant |= (OPJ_UINT32)getc(IN) << 8;
428         header->biClrImportant |= (OPJ_UINT32)getc(IN) << 16;
429         header->biClrImportant |= (OPJ_UINT32)getc(IN) << 24;
430     }
431
432     if (header->biSize >= 56U) {
433         header->biRedMask  = (OPJ_UINT32)getc(IN);
434         header->biRedMask |= (OPJ_UINT32)getc(IN) << 8;
435         header->biRedMask |= (OPJ_UINT32)getc(IN) << 16;
436         header->biRedMask |= (OPJ_UINT32)getc(IN) << 24;
437
438         if (!header->biRedMask) {
439             fprintf(stderr, "Error, invalid red mask value %d\n", header->biRedMask);
440             return OPJ_FALSE;
441         }
442
443         header->biGreenMask  = (OPJ_UINT32)getc(IN);
444         header->biGreenMask |= (OPJ_UINT32)getc(IN) << 8;
445         header->biGreenMask |= (OPJ_UINT32)getc(IN) << 16;
446         header->biGreenMask |= (OPJ_UINT32)getc(IN) << 24;
447
448         if (!header->biGreenMask) {
449             fprintf(stderr, "Error, invalid green mask value %d\n", header->biGreenMask);
450             return OPJ_FALSE;
451         }
452
453         header->biBlueMask  = (OPJ_UINT32)getc(IN);
454         header->biBlueMask |= (OPJ_UINT32)getc(IN) << 8;
455         header->biBlueMask |= (OPJ_UINT32)getc(IN) << 16;
456         header->biBlueMask |= (OPJ_UINT32)getc(IN) << 24;
457
458         if (!header->biBlueMask) {
459             fprintf(stderr, "Error, invalid blue mask value %d\n", header->biBlueMask);
460             return OPJ_FALSE;
461         }
462
463         header->biAlphaMask  = (OPJ_UINT32)getc(IN);
464         header->biAlphaMask |= (OPJ_UINT32)getc(IN) << 8;
465         header->biAlphaMask |= (OPJ_UINT32)getc(IN) << 16;
466         header->biAlphaMask |= (OPJ_UINT32)getc(IN) << 24;
467     }
468
469     if (header->biSize >= 108U) {
470         header->biColorSpaceType  = (OPJ_UINT32)getc(IN);
471         header->biColorSpaceType |= (OPJ_UINT32)getc(IN) << 8;
472         header->biColorSpaceType |= (OPJ_UINT32)getc(IN) << 16;
473         header->biColorSpaceType |= (OPJ_UINT32)getc(IN) << 24;
474
475         if (fread(&(header->biColorSpaceEP), 1U, sizeof(header->biColorSpaceEP),
476                   IN) != sizeof(header->biColorSpaceEP)) {
477             fprintf(stderr, "Error, can't  read BMP header\n");
478             return OPJ_FALSE;
479         }
480
481         header->biRedGamma  = (OPJ_UINT32)getc(IN);
482         header->biRedGamma |= (OPJ_UINT32)getc(IN) << 8;
483         header->biRedGamma |= (OPJ_UINT32)getc(IN) << 16;
484         header->biRedGamma |= (OPJ_UINT32)getc(IN) << 24;
485
486         header->biGreenGamma  = (OPJ_UINT32)getc(IN);
487         header->biGreenGamma |= (OPJ_UINT32)getc(IN) << 8;
488         header->biGreenGamma |= (OPJ_UINT32)getc(IN) << 16;
489         header->biGreenGamma |= (OPJ_UINT32)getc(IN) << 24;
490
491         header->biBlueGamma  = (OPJ_UINT32)getc(IN);
492         header->biBlueGamma |= (OPJ_UINT32)getc(IN) << 8;
493         header->biBlueGamma |= (OPJ_UINT32)getc(IN) << 16;
494         header->biBlueGamma |= (OPJ_UINT32)getc(IN) << 24;
495     }
496
497     if (header->biSize >= 124U) {
498         header->biIntent  = (OPJ_UINT32)getc(IN);
499         header->biIntent |= (OPJ_UINT32)getc(IN) << 8;
500         header->biIntent |= (OPJ_UINT32)getc(IN) << 16;
501         header->biIntent |= (OPJ_UINT32)getc(IN) << 24;
502
503         header->biIccProfileData  = (OPJ_UINT32)getc(IN);
504         header->biIccProfileData |= (OPJ_UINT32)getc(IN) << 8;
505         header->biIccProfileData |= (OPJ_UINT32)getc(IN) << 16;
506         header->biIccProfileData |= (OPJ_UINT32)getc(IN) << 24;
507
508         header->biIccProfileSize  = (OPJ_UINT32)getc(IN);
509         header->biIccProfileSize |= (OPJ_UINT32)getc(IN) << 8;
510         header->biIccProfileSize |= (OPJ_UINT32)getc(IN) << 16;
511         header->biIccProfileSize |= (OPJ_UINT32)getc(IN) << 24;
512
513         header->biReserved  = (OPJ_UINT32)getc(IN);
514         header->biReserved |= (OPJ_UINT32)getc(IN) << 8;
515         header->biReserved |= (OPJ_UINT32)getc(IN) << 16;
516         header->biReserved |= (OPJ_UINT32)getc(IN) << 24;
517     }
518     return OPJ_TRUE;
519 }
520
521 static OPJ_BOOL bmp_read_raw_data(FILE* IN, OPJ_UINT8* pData, OPJ_UINT32 stride,
522                                   OPJ_UINT32 width, OPJ_UINT32 height)
523 {
524     OPJ_ARG_NOT_USED(width);
525
526     if (fread(pData, sizeof(OPJ_UINT8), stride * height, IN) != (stride * height)) {
527         fprintf(stderr,
528                 "\nError: fread return a number of element different from the expected.\n");
529         return OPJ_FALSE;
530     }
531     return OPJ_TRUE;
532 }
533
534 static OPJ_BOOL bmp_read_rle8_data(FILE* IN, OPJ_UINT8* pData,
535                                    OPJ_UINT32 stride, OPJ_UINT32 width, OPJ_UINT32 height)
536 {
537     OPJ_UINT32 x, y, written;
538     OPJ_UINT8 *pix;
539     const OPJ_UINT8 *beyond;
540
541     beyond = pData + stride * height;
542     pix = pData;
543
544     x = y = written = 0U;
545     while (y < height) {
546         int c = getc(IN);
547         if (c == EOF) {
548             return OPJ_FALSE;
549         }
550
551         if (c) {
552             int j, c1_int;
553             OPJ_UINT8 c1;
554
555             c1_int = getc(IN);
556             if (c1_int == EOF) {
557                 return OPJ_FALSE;
558             }
559             c1 = (OPJ_UINT8)c1_int;
560
561             for (j = 0; (j < c) && (x < width) &&
562                     ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
563                 *pix = c1;
564                 written++;
565             }
566         } else {
567             c = getc(IN);
568             if (c == EOF) {
569                 return OPJ_FALSE;
570             }
571
572             if (c == 0x00) { /* EOL */
573                 x = 0;
574                 ++y;
575                 pix = pData + y * stride + x;
576             } else if (c == 0x01) { /* EOP */
577                 break;
578             } else if (c == 0x02) { /* MOVE by dxdy */
579                 c = getc(IN);
580                 if (c == EOF) {
581                     return OPJ_FALSE;
582                 }
583                 x += (OPJ_UINT32)c;
584                 c = getc(IN);
585                 if (c == EOF) {
586                     return OPJ_FALSE;
587                 }
588                 y += (OPJ_UINT32)c;
589                 pix = pData + y * stride + x;
590             } else { /* 03 .. 255 */
591                 int j;
592                 for (j = 0; (j < c) && (x < width) &&
593                         ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
594                     int c1_int;
595                     OPJ_UINT8 c1;
596                     c1_int = getc(IN);
597                     if (c1_int == EOF) {
598                         return OPJ_FALSE;
599                     }
600                     c1 = (OPJ_UINT8)c1_int;
601                     *pix = c1;
602                     written++;
603                 }
604                 if ((OPJ_UINT32)c & 1U) { /* skip padding byte */
605                     c = getc(IN);
606                     if (c == EOF) {
607                         return OPJ_FALSE;
608                     }
609                 }
610             }
611         }
612     }/* while() */
613
614     if (written != width * height) {
615         fprintf(stderr, "warning, image's actual size does not match advertized one\n");
616         return OPJ_FALSE;
617     }
618
619     return OPJ_TRUE;
620 }
621
622 static OPJ_BOOL bmp_read_rle4_data(FILE* IN, OPJ_UINT8* pData,
623                                    OPJ_UINT32 stride, OPJ_UINT32 width, OPJ_UINT32 height)
624 {
625     OPJ_UINT32 x, y, written;
626     OPJ_UINT8 *pix;
627     const OPJ_UINT8 *beyond;
628
629     beyond = pData + stride * height;
630     pix = pData;
631     x = y = written = 0U;
632     while (y < height) {
633         int c = getc(IN);
634         if (c == EOF) {
635             return OPJ_FALSE;
636         }
637
638         if (c) { /* encoded mode */
639             int j, c1_int;
640             OPJ_UINT8 c1;
641
642             c1_int = getc(IN);
643             if (c1_int == EOF) {
644                 return OPJ_FALSE;
645             }
646             c1 = (OPJ_UINT8)c1_int;
647
648             for (j = 0; (j < c) && (x < width) &&
649                     ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
650                 *pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU));
651                 written++;
652             }
653         } else { /* absolute mode */
654             c = getc(IN);
655             if (c == EOF) {
656                 return OPJ_FALSE;
657             }
658
659             if (c == 0x00) { /* EOL */
660                 x = 0;
661                 y++;
662                 pix = pData + y * stride;
663             } else if (c == 0x01) { /* EOP */
664                 break;
665             } else if (c == 0x02) { /* MOVE by dxdy */
666                 c = getc(IN);
667                 if (c == EOF) {
668                     return OPJ_FALSE;
669                 }
670                 x += (OPJ_UINT32)c;
671                 c = getc(IN);
672                 if (c == EOF) {
673                     return OPJ_FALSE;
674                 }
675                 y += (OPJ_UINT32)c;
676                 pix = pData + y * stride + x;
677             } else { /* 03 .. 255 : absolute mode */
678                 int j;
679                 OPJ_UINT8 c1 = 0U;
680
681                 for (j = 0; (j < c) && (x < width) &&
682                         ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
683                     if ((j & 1) == 0) {
684                         int c1_int;
685                         c1_int = getc(IN);
686                         if (c1_int == EOF) {
687                             return OPJ_FALSE;
688                         }
689                         c1 = (OPJ_UINT8)c1_int;
690                     }
691                     *pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU));
692                     written++;
693                 }
694                 if (((c & 3) == 1) || ((c & 3) == 2)) { /* skip padding byte */
695                     c = getc(IN);
696                     if (c == EOF) {
697                         return OPJ_FALSE;
698                     }
699                 }
700             }
701         }
702     }  /* while(y < height) */
703     if (written != width * height) {
704         fprintf(stderr, "warning, image's actual size does not match advertized one\n");
705         return OPJ_FALSE;
706     }
707     return OPJ_TRUE;
708 }
709
710 opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters)
711 {
712     opj_image_cmptparm_t cmptparm[4];   /* maximum of 4 components */
713     OPJ_UINT8 lut_R[256], lut_G[256], lut_B[256];
714     OPJ_UINT8 const* pLUT[3];
715     opj_image_t * image = NULL;
716     FILE *IN;
717     OPJ_BITMAPFILEHEADER File_h;
718     OPJ_BITMAPINFOHEADER Info_h;
719     OPJ_UINT32 i, palette_len, numcmpts = 1U;
720     OPJ_BOOL l_result = OPJ_FALSE;
721     OPJ_UINT8* pData = NULL;
722     OPJ_UINT32 stride;
723
724     pLUT[0] = lut_R;
725     pLUT[1] = lut_G;
726     pLUT[2] = lut_B;
727
728     IN = fopen(filename, "rb");
729     if (!IN) {
730         fprintf(stderr, "Failed to open %s for reading !!\n", filename);
731         return NULL;
732     }
733
734     if (!bmp_read_file_header(IN, &File_h)) {
735         fclose(IN);
736         return NULL;
737     }
738     if (!bmp_read_info_header(IN, &Info_h)) {
739         fclose(IN);
740         return NULL;
741     }
742
743     /* Load palette */
744     if (Info_h.biBitCount <= 8U) {
745         memset(&lut_R[0], 0, sizeof(lut_R));
746         memset(&lut_G[0], 0, sizeof(lut_G));
747         memset(&lut_B[0], 0, sizeof(lut_B));
748
749         palette_len = Info_h.biClrUsed;
750         if ((palette_len == 0U) && (Info_h.biBitCount <= 8U)) {
751             palette_len = (1U << Info_h.biBitCount);
752         }
753         if (palette_len > 256U) {
754             palette_len = 256U;
755         }
756         if (palette_len > 0U) {
757             OPJ_UINT8 has_color = 0U;
758             for (i = 0U; i < palette_len; i++) {
759                 lut_B[i] = (OPJ_UINT8)getc(IN);
760                 lut_G[i] = (OPJ_UINT8)getc(IN);
761                 lut_R[i] = (OPJ_UINT8)getc(IN);
762                 (void)getc(IN); /* padding */
763                 has_color |= (lut_B[i] ^ lut_G[i]) | (lut_G[i] ^ lut_R[i]);
764             }
765             if (has_color) {
766                 numcmpts = 3U;
767             }
768         }
769     } else {
770         numcmpts = 3U;
771         if ((Info_h.biCompression == 3) && (Info_h.biAlphaMask != 0U)) {
772             numcmpts++;
773         }
774     }
775
776     if (Info_h.biWidth == 0 || Info_h.biHeight == 0) {
777         fclose(IN);
778         return NULL;
779     }
780
781     if (Info_h.biBitCount > (((OPJ_UINT32) - 1) - 31) / Info_h.biWidth) {
782         fclose(IN);
783         return NULL;
784     }
785     stride = ((Info_h.biWidth * Info_h.biBitCount + 31U) / 32U) *
786              4U; /* rows are aligned on 32bits */
787     if (Info_h.biBitCount == 4 &&
788             Info_h.biCompression == 2) { /* RLE 4 gets decoded as 8 bits data for now... */
789         if (8 > (((OPJ_UINT32) - 1) - 31) / Info_h.biWidth) {
790             fclose(IN);
791             return NULL;
792         }
793         stride = ((Info_h.biWidth * 8U + 31U) / 32U) * 4U;
794     }
795
796     if (stride > ((OPJ_UINT32) - 1) / sizeof(OPJ_UINT8) / Info_h.biHeight) {
797         fclose(IN);
798         return NULL;
799     }
800     pData = (OPJ_UINT8 *) calloc(1, sizeof(OPJ_UINT8) * stride * Info_h.biHeight);
801     if (pData == NULL) {
802         fclose(IN);
803         return NULL;
804     }
805     /* Place the cursor at the beginning of the image information */
806     fseek(IN, 0, SEEK_SET);
807     fseek(IN, (long)File_h.bfOffBits, SEEK_SET);
808
809     switch (Info_h.biCompression) {
810     case 0:
811     case 3:
812         /* read raw data */
813         l_result = bmp_read_raw_data(IN, pData, stride, Info_h.biWidth,
814                                      Info_h.biHeight);
815         break;
816     case 1:
817         /* read rle8 data */
818         l_result = bmp_read_rle8_data(IN, pData, stride, Info_h.biWidth,
819                                       Info_h.biHeight);
820         break;
821     case 2:
822         /* read rle4 data */
823         l_result = bmp_read_rle4_data(IN, pData, stride, Info_h.biWidth,
824                                       Info_h.biHeight);
825         break;
826     default:
827         fprintf(stderr, "Unsupported BMP compression\n");
828         l_result = OPJ_FALSE;
829         break;
830     }
831     if (!l_result) {
832         free(pData);
833         fclose(IN);
834         return NULL;
835     }
836
837     /* create the image */
838     memset(&cmptparm[0], 0, sizeof(cmptparm));
839     for (i = 0; i < 4U; i++) {
840         cmptparm[i].prec = 8;
841         cmptparm[i].bpp  = 8;
842         cmptparm[i].sgnd = 0;
843         cmptparm[i].dx   = (OPJ_UINT32)parameters->subsampling_dx;
844         cmptparm[i].dy   = (OPJ_UINT32)parameters->subsampling_dy;
845         cmptparm[i].w    = Info_h.biWidth;
846         cmptparm[i].h    = Info_h.biHeight;
847     }
848
849     image = opj_image_create(numcmpts, &cmptparm[0],
850                              (numcmpts == 1U) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB);
851     if (!image) {
852         fclose(IN);
853         free(pData);
854         return NULL;
855     }
856     if (numcmpts == 4U) {
857         image->comps[3].alpha = 1;
858     }
859
860     /* set image offset and reference grid */
861     image->x0 = (OPJ_UINT32)parameters->image_offset_x0;
862     image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
863     image->x1 = image->x0 + (Info_h.biWidth  - 1U) * (OPJ_UINT32)
864                 parameters->subsampling_dx + 1U;
865     image->y1 = image->y0 + (Info_h.biHeight - 1U) * (OPJ_UINT32)
866                 parameters->subsampling_dy + 1U;
867
868     /* Read the data */
869     if (Info_h.biBitCount == 24 && Info_h.biCompression == 0) { /*RGB */
870         bmp24toimage(pData, stride, image);
871     } else if (Info_h.biBitCount == 8 &&
872                Info_h.biCompression == 0) { /* RGB 8bpp Indexed */
873         bmp8toimage(pData, stride, image, pLUT);
874     } else if (Info_h.biBitCount == 8 && Info_h.biCompression == 1) { /*RLE8*/
875         bmp8toimage(pData, stride, image, pLUT);
876     } else if (Info_h.biBitCount == 4 && Info_h.biCompression == 2) { /*RLE4*/
877         bmp8toimage(pData, stride, image,
878                     pLUT); /* RLE 4 gets decoded as 8 bits data for now */
879     } else if (Info_h.biBitCount == 32 && Info_h.biCompression == 0) { /* RGBX */
880         bmpmask32toimage(pData, stride, image, 0x00FF0000U, 0x0000FF00U, 0x000000FFU,
881                          0x00000000U);
882     } else if (Info_h.biBitCount == 32 && Info_h.biCompression == 3) { /* bitmask */
883         if ((Info_h.biRedMask == 0U) && (Info_h.biGreenMask == 0U) &&
884                 (Info_h.biBlueMask == 0U)) {
885             Info_h.biRedMask   = 0x00FF0000U;
886             Info_h.biGreenMask = 0x0000FF00U;
887             Info_h.biBlueMask  = 0x000000FFU;
888         }
889         bmpmask32toimage(pData, stride, image, Info_h.biRedMask, Info_h.biGreenMask,
890                          Info_h.biBlueMask, Info_h.biAlphaMask);
891     } else if (Info_h.biBitCount == 16 && Info_h.biCompression == 0) { /* RGBX */
892         bmpmask16toimage(pData, stride, image, 0x7C00U, 0x03E0U, 0x001FU, 0x0000U);
893     } else if (Info_h.biBitCount == 16 && Info_h.biCompression == 3) { /* bitmask */
894         if ((Info_h.biRedMask == 0U) && (Info_h.biGreenMask == 0U) &&
895                 (Info_h.biBlueMask == 0U)) {
896             Info_h.biRedMask   = 0xF800U;
897             Info_h.biGreenMask = 0x07E0U;
898             Info_h.biBlueMask  = 0x001FU;
899         }
900         bmpmask16toimage(pData, stride, image, Info_h.biRedMask, Info_h.biGreenMask,
901                          Info_h.biBlueMask, Info_h.biAlphaMask);
902     } else {
903         opj_image_destroy(image);
904         image = NULL;
905         fprintf(stderr,
906                 "Other system than 24 bits/pixels or 8 bits (no RLE coding) is not yet implemented [%d]\n",
907                 Info_h.biBitCount);
908     }
909     free(pData);
910     fclose(IN);
911     return image;
912 }
913
914 int imagetobmp(opj_image_t * image, const char *outfile)
915 {
916     int w, h;
917     int i, pad;
918     FILE *fdest = NULL;
919     int adjustR, adjustG, adjustB;
920
921     if (image->comps[0].prec < 8) {
922         fprintf(stderr, "imagetobmp: Unsupported precision: %d\n",
923                 image->comps[0].prec);
924         return 1;
925     }
926     if (image->numcomps >= 3 && image->comps[0].dx == image->comps[1].dx
927             && image->comps[1].dx == image->comps[2].dx
928             && image->comps[0].dy == image->comps[1].dy
929             && image->comps[1].dy == image->comps[2].dy
930             && image->comps[0].prec == image->comps[1].prec
931             && image->comps[1].prec == image->comps[2].prec
932             && image->comps[0].sgnd == image->comps[1].sgnd
933             && image->comps[1].sgnd == image->comps[2].sgnd) {
934
935         /* -->> -->> -->> -->>
936         24 bits color
937         <<-- <<-- <<-- <<-- */
938
939         fdest = fopen(outfile, "wb");
940         if (!fdest) {
941             fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
942             return 1;
943         }
944
945         w = (int)image->comps[0].w;
946         h = (int)image->comps[0].h;
947
948         fprintf(fdest, "BM");
949
950         /* FILE HEADER */
951         /* ------------- */
952         fprintf(fdest, "%c%c%c%c",
953                 (OPJ_UINT8)(h * w * 3 + 3 * h * (w % 2) + 54) & 0xff,
954                 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2) + 54) >> 8) & 0xff,
955                 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2) + 54) >> 16) & 0xff,
956                 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2) + 54) >> 24) & 0xff);
957         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
958                 ((0) >> 24) & 0xff);
959         fprintf(fdest, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff, ((54) >> 16) & 0xff,
960                 ((54) >> 24) & 0xff);
961
962         /* INFO HEADER   */
963         /* ------------- */
964         fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff,
965                 ((40) >> 24) & 0xff);
966         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((w) & 0xff),
967                 (OPJ_UINT8)((w) >> 8) & 0xff,
968                 (OPJ_UINT8)((w) >> 16) & 0xff,
969                 (OPJ_UINT8)((w) >> 24) & 0xff);
970         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((h) & 0xff),
971                 (OPJ_UINT8)((h) >> 8) & 0xff,
972                 (OPJ_UINT8)((h) >> 16) & 0xff,
973                 (OPJ_UINT8)((h) >> 24) & 0xff);
974         fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
975         fprintf(fdest, "%c%c", (24) & 0xff, ((24) >> 8) & 0xff);
976         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
977                 ((0) >> 24) & 0xff);
978         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)(3 * h * w + 3 * h * (w % 2)) & 0xff,
979                 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2)) >> 8) & 0xff,
980                 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2)) >> 16) & 0xff,
981                 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2)) >> 24) & 0xff);
982         fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
983                 ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
984         fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
985                 ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
986         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
987                 ((0) >> 24) & 0xff);
988         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
989                 ((0) >> 24) & 0xff);
990
991         if (image->comps[0].prec > 8) {
992             adjustR = (int)image->comps[0].prec - 8;
993             printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n",
994                    image->comps[0].prec);
995         } else {
996             adjustR = 0;
997         }
998         if (image->comps[1].prec > 8) {
999             adjustG = (int)image->comps[1].prec - 8;
1000             printf("BMP CONVERSION: Truncating component 1 from %d bits to 8 bits\n",
1001                    image->comps[1].prec);
1002         } else {
1003             adjustG = 0;
1004         }
1005         if (image->comps[2].prec > 8) {
1006             adjustB = (int)image->comps[2].prec - 8;
1007             printf("BMP CONVERSION: Truncating component 2 from %d bits to 8 bits\n",
1008                    image->comps[2].prec);
1009         } else {
1010             adjustB = 0;
1011         }
1012
1013         for (i = 0; i < w * h; i++) {
1014             OPJ_UINT8 rc, gc, bc;
1015             int r, g, b;
1016
1017             r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
1018             r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
1019             if (adjustR > 0) {
1020                 r = ((r >> adjustR) + ((r >> (adjustR - 1)) % 2));
1021             }
1022             if (r > 255) {
1023                 r = 255;
1024             } else if (r < 0) {
1025                 r = 0;
1026             }
1027             rc = (OPJ_UINT8)r;
1028
1029             g = image->comps[1].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
1030             g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
1031             if (adjustG > 0) {
1032                 g = ((g >> adjustG) + ((g >> (adjustG - 1)) % 2));
1033             }
1034             if (g > 255) {
1035                 g = 255;
1036             } else if (g < 0) {
1037                 g = 0;
1038             }
1039             gc = (OPJ_UINT8)g;
1040
1041             b = image->comps[2].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
1042             b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
1043             if (adjustB > 0) {
1044                 b = ((b >> adjustB) + ((b >> (adjustB - 1)) % 2));
1045             }
1046             if (b > 255) {
1047                 b = 255;
1048             } else if (b < 0) {
1049                 b = 0;
1050             }
1051             bc = (OPJ_UINT8)b;
1052
1053             fprintf(fdest, "%c%c%c", bc, gc, rc);
1054
1055             if ((i + 1) % w == 0) {
1056                 for (pad = ((3 * w) % 4) ? (4 - (3 * w) % 4) : 0; pad > 0; pad--) { /* ADD */
1057                     fprintf(fdest, "%c", 0);
1058                 }
1059             }
1060         }
1061         fclose(fdest);
1062     } else {            /* Gray-scale */
1063
1064         /* -->> -->> -->> -->>
1065         8 bits non code (Gray scale)
1066         <<-- <<-- <<-- <<-- */
1067
1068         fdest = fopen(outfile, "wb");
1069         if (!fdest) {
1070             fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
1071             return 1;
1072         }
1073         if (image->numcomps > 1) {
1074             fprintf(stderr, "imagetobmp: only first component of %d is used.\n",
1075                     image->numcomps);
1076         }
1077         w = (int)image->comps[0].w;
1078         h = (int)image->comps[0].h;
1079
1080         fprintf(fdest, "BM");
1081
1082         /* FILE HEADER */
1083         /* ------------- */
1084         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)(h * w + 54 + 1024 + h * (w % 2)) & 0xff,
1085                 (OPJ_UINT8)((h * w + 54 + 1024 + h * (w % 2)) >> 8) & 0xff,
1086                 (OPJ_UINT8)((h * w + 54 + 1024 + h * (w % 2)) >> 16) & 0xff,
1087                 (OPJ_UINT8)((h * w + 54 + 1024 + w * (w % 2)) >> 24) & 0xff);
1088         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
1089                 ((0) >> 24) & 0xff);
1090         fprintf(fdest, "%c%c%c%c", (54 + 1024) & 0xff, ((54 + 1024) >> 8) & 0xff,
1091                 ((54 + 1024) >> 16) & 0xff,
1092                 ((54 + 1024) >> 24) & 0xff);
1093
1094         /* INFO HEADER */
1095         /* ------------- */
1096         fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff,
1097                 ((40) >> 24) & 0xff);
1098         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((w) & 0xff),
1099                 (OPJ_UINT8)((w) >> 8) & 0xff,
1100                 (OPJ_UINT8)((w) >> 16) & 0xff,
1101                 (OPJ_UINT8)((w) >> 24) & 0xff);
1102         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((h) & 0xff),
1103                 (OPJ_UINT8)((h) >> 8) & 0xff,
1104                 (OPJ_UINT8)((h) >> 16) & 0xff,
1105                 (OPJ_UINT8)((h) >> 24) & 0xff);
1106         fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
1107         fprintf(fdest, "%c%c", (8) & 0xff, ((8) >> 8) & 0xff);
1108         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
1109                 ((0) >> 24) & 0xff);
1110         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)(h * w + h * (w % 2)) & 0xff,
1111                 (OPJ_UINT8)((h * w + h * (w % 2)) >> 8) &  0xff,
1112                 (OPJ_UINT8)((h * w + h * (w % 2)) >> 16) & 0xff,
1113                 (OPJ_UINT8)((h * w + h * (w % 2)) >> 24) & 0xff);
1114         fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
1115                 ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
1116         fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
1117                 ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
1118         fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff,
1119                 ((256) >> 16) & 0xff, ((256) >> 24) & 0xff);
1120         fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff,
1121                 ((256) >> 16) & 0xff, ((256) >> 24) & 0xff);
1122
1123         if (image->comps[0].prec > 8) {
1124             adjustR = (int)image->comps[0].prec - 8;
1125             printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n",
1126                    image->comps[0].prec);
1127         } else {
1128             adjustR = 0;
1129         }
1130
1131         for (i = 0; i < 256; i++) {
1132             fprintf(fdest, "%c%c%c%c", i, i, i, 0);
1133         }
1134
1135         for (i = 0; i < w * h; i++) {
1136             int r;
1137
1138             r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
1139             r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
1140             if (adjustR > 0) {
1141                 r = ((r >> adjustR) + ((r >> (adjustR - 1)) % 2));
1142             }
1143             if (r > 255) {
1144                 r = 255;
1145             } else if (r < 0) {
1146                 r = 0;
1147             }
1148
1149             fprintf(fdest, "%c", (OPJ_UINT8)r);
1150
1151             if ((i + 1) % w == 0) {
1152                 for (pad = (w % 4) ? (4 - w % 4) : 0; pad > 0; pad--) { /* ADD */
1153                     fprintf(fdest, "%c", 0);
1154                 }
1155             }
1156         }
1157         fclose(fdest);
1158     }
1159
1160     return 0;
1161 }