7f570203a80e36eb44e78d813dc7c8e059a52ead
[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;        /* Heigth 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_BITMAPINFOHEADER;
69
70 static void opj_applyLUT8u_8u32s_C1R(
71         OPJ_UINT8 const* pSrc, OPJ_INT32 srcStride,
72         OPJ_INT32* pDst, OPJ_INT32 dstStride,
73         OPJ_UINT8 const* pLUT,
74         OPJ_UINT32 width, OPJ_UINT32 height)
75 {
76         OPJ_UINT32 y;
77         
78         for (y = height; y != 0U; --y) {
79                 OPJ_UINT32 x;
80                 
81                 for(x = 0; x < width; x++)
82                 {
83                         pDst[x] = pLUT[pSrc[x]];
84                 }
85                 pSrc += srcStride;
86                 pDst += dstStride;
87         }
88 }
89
90 static void opj_applyLUT8u_8u32s_C1P3R(
91         OPJ_UINT8 const* pSrc, OPJ_INT32 srcStride,
92         OPJ_INT32* const* pDst, OPJ_INT32 const* pDstStride,
93         OPJ_UINT8 const* const* pLUT,
94         OPJ_UINT32 width, OPJ_UINT32 height)
95 {
96         OPJ_UINT32 y;
97         OPJ_INT32* pR = pDst[0];
98         OPJ_INT32* pG = pDst[1];
99         OPJ_INT32* pB = pDst[2];
100         OPJ_UINT8 const* pLUT_R = pLUT[0];
101         OPJ_UINT8 const* pLUT_G = pLUT[1];
102         OPJ_UINT8 const* pLUT_B = pLUT[2];
103         
104         for (y = height; y != 0U; --y) {
105                 OPJ_UINT32 x;
106                 
107                 for(x = 0; x < width; x++)
108                 {
109                         OPJ_UINT8 idx = pSrc[x];
110                         pR[x] = pLUT_R[idx];
111                         pG[x] = pLUT_G[idx];
112                         pB[x] = pLUT_B[idx];
113                 }
114                 pSrc += srcStride;
115                 pR += pDstStride[0];
116                 pG += pDstStride[1];
117                 pB += pDstStride[2];
118         }
119 }
120
121 static opj_image_t* bmp24toimage(FILE *IN, const OPJ_BITMAPFILEHEADER* File_h, const OPJ_BITMAPINFOHEADER* Info_h, const opj_cparameters_t *parameters)
122 {
123         opj_image_cmptparm_t cmptparm[3];       /* maximum of 3 components */
124         opj_image_t * image = NULL;
125         int i, index;
126         OPJ_UINT32 width, height, stride;
127         OPJ_UINT32 x, y;
128         OPJ_UINT8 *pData = NULL;
129         const OPJ_UINT8 *pSrc = NULL;
130
131         width  = Info_h->biWidth;
132         height = Info_h->biHeight;
133         
134         /* initialize image components */
135         memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));
136         for(i = 0; i < 3; i++)
137         {
138                 cmptparm[i].prec = 8;
139                 cmptparm[i].bpp  = 8;
140                 cmptparm[i].sgnd = 0;
141                 cmptparm[i].dx   = (OPJ_UINT32)parameters->subsampling_dx;
142                 cmptparm[i].dy   = (OPJ_UINT32)parameters->subsampling_dy;
143                 cmptparm[i].w    = (OPJ_UINT32)width;
144                 cmptparm[i].h    = (OPJ_UINT32)height;
145         }
146         /* create the image */
147         image = opj_image_create(3U, &cmptparm[0], OPJ_CLRSPC_SRGB);
148         if(!image)
149         {
150                 return NULL;
151         }
152         
153         /* set image offset and reference grid */
154         image->x0 = (OPJ_UINT32)parameters->image_offset_x0;
155         image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
156         image->x1 =     image->x0 + (OPJ_UINT32)(width  - 1U) * (OPJ_UINT32)parameters->subsampling_dx + 1U;
157         image->y1 = image->y0 + (OPJ_UINT32)(height - 1U) * (OPJ_UINT32)parameters->subsampling_dy + 1U;
158         
159         /* set image data */
160         
161         /* Place the cursor at the beginning of the image information */
162         fseek(IN, 0, SEEK_SET);
163         fseek(IN, (long)File_h->bfOffBits, SEEK_SET);
164         
165         stride = width * 3U;
166         /* line is 32 bits aligned */
167         if (stride & 3U) {
168                 stride += 4U - (stride & 3U);
169         }
170         
171         pData = (OPJ_UINT8 *)malloc(stride * height * sizeof(OPJ_UINT8));
172         
173         if ( fread(pData, sizeof(OPJ_UINT8), stride * height, IN) != (stride * height) )
174         {
175                 free(pData);
176                 opj_image_destroy(image);
177                 fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
178                 return NULL;
179         }
180         
181         index = 0;
182         pSrc = pData + (height - 1U) * stride;
183         for(y = 0; y < height; y++)
184         {
185                 for(x = 0; x < width; x++)
186                 {
187                         image->comps[0].data[index] = pSrc[3*x+2];      /* R */
188                         image->comps[1].data[index] = pSrc[3*x+1];      /* G */
189                         image->comps[2].data[index] = pSrc[3*x+0];      /* B */
190                         index++;
191                 }
192                 pSrc -= stride;
193         }
194         free(pData);
195         return image;
196 }
197
198 static opj_image_t* bmp8toimage(FILE *IN, const OPJ_BITMAPFILEHEADER* File_h, const OPJ_BITMAPINFOHEADER* Info_h, const opj_cparameters_t *parameters)
199 {
200         OPJ_UINT8 lut_R[256], lut_G[256], lut_B[256];
201         opj_image_cmptparm_t cmptparm[3];       /* maximum of 3 components */
202         opj_image_t * image = NULL;
203         OPJ_SIZE_T index;
204         OPJ_UINT32 i, palette_len;
205         OPJ_UINT32 width, height, stride;
206         OPJ_UINT8 *pData = NULL;
207         const OPJ_UINT8 *pSrc = NULL;
208         OPJ_UINT32 numcmpts = 1U; /* grayscale by default */
209         
210         width  = Info_h->biWidth;
211         height = Info_h->biHeight;
212         
213         /* initialize */
214         memset(&cmptparm[0], 0, sizeof(cmptparm));
215         memset(&lut_R[0], 0, sizeof(lut_R));
216         memset(&lut_G[0], 0, sizeof(lut_G));
217         memset(&lut_B[0], 0, sizeof(lut_B));
218         
219         palette_len = Info_h->biClrUsed;
220         if ((palette_len == 0U) || (palette_len > 256U)) {
221                 palette_len = 256U;
222         }
223         
224         /* Load palette */
225         {
226                 OPJ_UINT8 has_color = 0U;
227                 for (i = 0; i < palette_len; i++) {
228                         lut_B[i] = (OPJ_UINT8)getc(IN);
229                         lut_G[i] = (OPJ_UINT8)getc(IN);
230                         lut_R[i] = (OPJ_UINT8)getc(IN);
231                         getc(IN); /* padding */
232                         has_color |= lut_B[i] ^ (lut_G[i] | lut_R[i]);
233                 }
234                 if(has_color) {
235                         numcmpts = 3;
236                 }
237         }
238         
239         
240         for(i = 0; i < numcmpts; i++)
241         {
242                 cmptparm[i].prec = 8;
243                 cmptparm[i].bpp  = 8;
244                 cmptparm[i].sgnd = 0;
245                 cmptparm[i].dx   = (OPJ_UINT32)parameters->subsampling_dx;
246                 cmptparm[i].dy   = (OPJ_UINT32)parameters->subsampling_dy;
247                 cmptparm[i].w    = width;
248                 cmptparm[i].h    = height;
249         }
250         /* create the image */
251         image = opj_image_create(numcmpts, &cmptparm[0], (numcmpts == 1U) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB);
252         if(!image)
253         {
254                 return NULL;
255         }
256         
257         /* set image offset and reference grid */
258         image->x0 = (OPJ_UINT32)parameters->image_offset_x0;
259         image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
260         image->x1 =     image->x0 + (width  - 1U) * (OPJ_UINT32)parameters->subsampling_dx + 1U;
261         image->y1 = image->y0 + (height - 1U) * (OPJ_UINT32)parameters->subsampling_dy + 1U;
262         
263         /* set image data */
264         
265         /* Place the cursor at the beginning of the image information */
266         fseek(IN, 0, SEEK_SET);
267         fseek(IN, (long)File_h->bfOffBits, SEEK_SET);
268         
269         stride = width;
270         /* line is 32 bits aligned */
271         if (stride & 3U) {
272                 stride += 4U - (stride & 3U);
273         }
274         
275         pData = (OPJ_UINT8 *)malloc(stride * height * sizeof(OPJ_UINT8));
276         
277         if ( fread(pData, sizeof(OPJ_UINT8), stride * height, IN) != (stride * height) )
278         {
279                 free(pData);
280                 opj_image_destroy(image);
281                 fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
282                 return NULL;
283         }
284         
285         index = 0;
286         pSrc = pData + (height - 1U) * stride;
287         if (numcmpts == 1U) {
288                 opj_applyLUT8u_8u32s_C1R(pSrc, -(OPJ_INT32)stride, image->comps[0].data, (OPJ_INT32)width, lut_R, width, height);
289         }
290         else {
291                 OPJ_INT32* pDst[] = { image->comps[0].data, image->comps[1].data, image->comps[2].data };
292                 OPJ_INT32  pDstStride[] = { (OPJ_INT32)width, (OPJ_INT32)width, (OPJ_INT32)width };
293                 OPJ_UINT8 const* pLUT[] = { lut_R, lut_G, lut_B };
294                 
295                 opj_applyLUT8u_8u32s_C1P3R(pSrc, -(OPJ_INT32)stride, pDst, pDstStride, pLUT, width, height);
296         }
297         
298         free(pData);
299         return image;
300 }
301
302 static opj_image_t* bmprle8toimage(FILE *IN, const OPJ_BITMAPFILEHEADER* File_h, const OPJ_BITMAPINFOHEADER* Info_h, const opj_cparameters_t *parameters)
303 {
304         OPJ_UINT8 lut_R[256], lut_G[256], lut_B[256];
305         opj_image_cmptparm_t cmptparm[3];       /* maximum of 3 components */
306         opj_image_t * image = NULL;
307         OPJ_SIZE_T index;
308         OPJ_UINT32 i, palette_len;
309         OPJ_UINT32 x, y, width, height;
310         OPJ_UINT8 *pData = NULL, *pix;
311         const OPJ_UINT8 *beyond;
312         OPJ_UINT32 numcmpts = 1U; /* grayscale by default */
313         
314         width  = Info_h->biWidth;
315         height = Info_h->biHeight;
316         
317         /* initialize */
318         memset(&cmptparm[0], 0, sizeof(cmptparm));
319         memset(&lut_R[0], 0, sizeof(lut_R));
320         memset(&lut_G[0], 0, sizeof(lut_G));
321         memset(&lut_B[0], 0, sizeof(lut_B));
322         
323         palette_len = Info_h->biClrUsed;
324         if ((palette_len == 0U) || (palette_len > 256U)) {
325                 palette_len = 256U;
326         }
327         
328         /* Load palette */
329         {
330                 OPJ_UINT8 has_color = 0U;
331                 for (i = 0; i < palette_len; i++) {
332                         lut_B[i] = (OPJ_UINT8)getc(IN);
333                         lut_G[i] = (OPJ_UINT8)getc(IN);
334                         lut_R[i] = (OPJ_UINT8)getc(IN);
335                         getc(IN); /* padding */
336                         has_color |= lut_B[i] ^ (lut_G[i] | lut_R[i]);
337                 }
338                 if(has_color) {
339                         numcmpts = 3;
340                 }
341         }
342         
343         
344         for(i = 0; i < numcmpts; i++)
345         {
346                 cmptparm[i].prec = 8;
347                 cmptparm[i].bpp  = 8;
348                 cmptparm[i].sgnd = 0;
349                 cmptparm[i].dx   = (OPJ_UINT32)parameters->subsampling_dx;
350                 cmptparm[i].dy   = (OPJ_UINT32)parameters->subsampling_dy;
351                 cmptparm[i].w    = width;
352                 cmptparm[i].h    = height;
353         }
354         /* create the image */
355         image = opj_image_create(numcmpts, &cmptparm[0], (numcmpts == 1U) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB);
356         if(!image)
357         {
358                 return NULL;
359         }
360         
361         /* set image offset and reference grid */
362         image->x0 = (OPJ_UINT32)parameters->image_offset_x0;
363         image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
364         image->x1 =     image->x0 + (width  - 1U) * (OPJ_UINT32)parameters->subsampling_dx + 1U;
365         image->y1 = image->y0 + (height - 1U) * (OPJ_UINT32)parameters->subsampling_dy + 1U;
366         
367         /* set image data */
368         
369         /* Place the cursor at the beginning of the image information */
370         fseek(IN, 0, SEEK_SET);
371         fseek(IN, (long)File_h->bfOffBits, SEEK_SET);
372         
373         pData = (OPJ_UINT8 *) calloc(1, width * height * sizeof(OPJ_UINT8));
374         beyond = pData + width * height;
375         pix = (OPJ_UINT8 *)(beyond - width);
376         x = y = 0U;
377         while (y < height)
378         {
379                 int c = getc(IN);
380                 
381                 if (c) {
382                         int j;
383                         OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN);
384                         
385                         for (j = 0; (j < c) && (x < width) && ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
386                                 *pix = c1;
387                         }
388                 }
389                 else {
390                         c = getc(IN);
391                         if (c == 0x00) { /* EOL */
392                                 x = 0;
393                                 ++y;
394                                 pix = pData + (height - y - 1U) * width + x;
395                         }
396                         else if (c == 0x01) { /* EOP */
397                                 break;
398                         }
399                         else if (c == 0x02) { /* MOVE by dxdy */
400                                 c = getc(IN);
401                                 x += (OPJ_UINT32)c;
402                                 c = getc(IN);
403                                 y += (OPJ_UINT32)c;
404                                 pix = pData + (height - y - 1U) * width + x;
405                         }
406                         else /* 03 .. 255 */
407                         {
408                                 int j;
409                                 for (j = 0; (j < c) && (x < width) && ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++)
410                                 {
411                                         OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN);
412                                         *pix = c1;
413                                 }
414                                 if ((OPJ_UINT32)c & 1U) { /* skip padding byte */
415                                         getc(IN);
416                                 }
417                         }
418                 }
419         }/* while() */
420         
421         index = 0;
422         if (numcmpts == 1) {
423                 opj_applyLUT8u_8u32s_C1R(pData, (OPJ_INT32)width, image->comps[0].data, (OPJ_INT32)width, lut_R, width, height);
424         }
425         else {
426                 OPJ_INT32* pDst[] = { image->comps[0].data, image->comps[1].data, image->comps[2].data };
427                 OPJ_INT32  pDstStride[] = { (OPJ_INT32)width, (OPJ_INT32)width, (OPJ_INT32)width };
428                 OPJ_UINT8 const* pLUT[] = { lut_R, lut_G, lut_B };
429                 
430                 opj_applyLUT8u_8u32s_C1P3R(pData, (OPJ_INT32)width, pDst, pDstStride, pLUT, width, height);
431         }
432         
433         free(pData);
434         return image;
435 }
436
437 opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters)
438 {
439         opj_image_t * image = NULL;
440
441         FILE *IN;
442         OPJ_BITMAPFILEHEADER File_h;
443         OPJ_BITMAPINFOHEADER Info_h;
444
445         IN = fopen(filename, "rb");
446         if (!IN)
447         {
448                 fprintf(stderr, "Failed to open %s for reading !!\n", filename);
449                 return NULL;
450         }
451
452         File_h.bfType = (OPJ_UINT16)getc(IN);
453         File_h.bfType = (OPJ_UINT16)((getc(IN) << 8) + File_h.bfType);
454
455         if (File_h.bfType != 19778) {
456                 fprintf(stderr,"Error, not a BMP file!\n");
457                 fclose(IN);
458                 return NULL;
459         }
460         
461         /* FILE HEADER */
462         /* ------------- */
463         File_h.bfSize = (OPJ_UINT32)getc(IN);
464         File_h.bfSize = (OPJ_UINT32)(getc(IN) << 8) + File_h.bfSize;
465         File_h.bfSize = (OPJ_UINT32)(getc(IN) << 16) + File_h.bfSize;
466         File_h.bfSize = (OPJ_UINT32)(getc(IN) << 24) + File_h.bfSize;
467         
468         File_h.bfReserved1 = (OPJ_UINT16)getc(IN);
469         File_h.bfReserved1 = (OPJ_UINT16)((getc(IN) << 8) + File_h.bfReserved1);
470
471         File_h.bfReserved2 = (OPJ_UINT16)getc(IN);
472         File_h.bfReserved2 = (OPJ_UINT16)((getc(IN) << 8) + File_h.bfReserved2);
473
474         File_h.bfOffBits = (OPJ_UINT32)getc(IN);
475         File_h.bfOffBits = (OPJ_UINT32)(getc(IN) << 8) + File_h.bfOffBits;
476         File_h.bfOffBits = (OPJ_UINT32)(getc(IN) << 16) + File_h.bfOffBits;
477         File_h.bfOffBits = (OPJ_UINT32)(getc(IN) << 24) + File_h.bfOffBits;
478
479         /* INFO HEADER */
480         /* ------------- */
481
482         Info_h.biSize = (OPJ_UINT32)getc(IN);
483         Info_h.biSize = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biSize;
484         Info_h.biSize = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biSize;
485         Info_h.biSize = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biSize;
486
487         if(Info_h.biSize != 40) {
488                 fprintf(stderr,"Error, unknown BMP header size %d\n", Info_h.biSize);
489                 fclose(IN);
490                 return NULL;
491         }
492         
493         Info_h.biWidth = (OPJ_UINT32)getc(IN);
494         Info_h.biWidth = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biWidth;
495         Info_h.biWidth = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biWidth;
496         Info_h.biWidth = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biWidth;
497
498         Info_h.biHeight = (OPJ_UINT32)getc(IN);
499         Info_h.biHeight = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biHeight;
500         Info_h.biHeight = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biHeight;
501         Info_h.biHeight = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biHeight;
502
503         Info_h.biPlanes = (OPJ_UINT16)getc(IN);
504         Info_h.biPlanes = (OPJ_UINT16)((getc(IN) << 8) + Info_h.biPlanes);
505
506         Info_h.biBitCount = (OPJ_UINT16)getc(IN);
507         Info_h.biBitCount = (OPJ_UINT16)((getc(IN) << 8) + Info_h.biBitCount);
508
509         Info_h.biCompression = (OPJ_UINT32)getc(IN);
510         Info_h.biCompression = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biCompression;
511         Info_h.biCompression = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biCompression;
512         Info_h.biCompression = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biCompression;
513
514         Info_h.biSizeImage = (OPJ_UINT32)getc(IN);
515         Info_h.biSizeImage = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biSizeImage;
516         Info_h.biSizeImage = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biSizeImage;
517         Info_h.biSizeImage = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biSizeImage;
518
519         Info_h.biXpelsPerMeter = (OPJ_UINT32)getc(IN);
520         Info_h.biXpelsPerMeter = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biXpelsPerMeter;
521         Info_h.biXpelsPerMeter = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biXpelsPerMeter;
522         Info_h.biXpelsPerMeter = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biXpelsPerMeter;
523
524         Info_h.biYpelsPerMeter = (OPJ_UINT32)getc(IN);
525         Info_h.biYpelsPerMeter = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biYpelsPerMeter;
526         Info_h.biYpelsPerMeter = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biYpelsPerMeter;
527         Info_h.biYpelsPerMeter = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biYpelsPerMeter;
528
529         Info_h.biClrUsed = (OPJ_UINT32)getc(IN);
530         Info_h.biClrUsed = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biClrUsed;
531         Info_h.biClrUsed = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biClrUsed;
532         Info_h.biClrUsed = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biClrUsed;
533
534         Info_h.biClrImportant = (OPJ_UINT32)getc(IN);
535         Info_h.biClrImportant = (OPJ_UINT32)(getc(IN) << 8) + Info_h.biClrImportant;
536         Info_h.biClrImportant = (OPJ_UINT32)(getc(IN) << 16) + Info_h.biClrImportant;
537         Info_h.biClrImportant = (OPJ_UINT32)(getc(IN) << 24) + Info_h.biClrImportant;
538         
539         /* Read the data */
540         if (Info_h.biBitCount == 24) { /*RGB */
541                 image = bmp24toimage(IN, &File_h, &Info_h, parameters);
542         }
543         else if (Info_h.biBitCount == 8 && Info_h.biCompression == 0) { /* RGB 8bpp Indexed */
544                 image = bmp8toimage(IN, &File_h, &Info_h, parameters);
545         }
546         else if (Info_h.biBitCount == 8 && Info_h.biCompression == 1) { /*RLE8*/
547                 image = bmprle8toimage(IN, &File_h, &Info_h, parameters);
548         }
549         else {
550                 fprintf(stderr, "Other system than 24 bits/pixels or 8 bits (no RLE coding) is not yet implemented [%d]\n", Info_h.biBitCount);
551         }
552         fclose(IN);
553         return image;
554 }
555
556 int imagetobmp(opj_image_t * image, const char *outfile) {
557     int w, h;
558     int i, pad;
559     FILE *fdest = NULL;
560     int adjustR, adjustG, adjustB;
561
562     if (image->comps[0].prec < 8) {
563         fprintf(stderr, "Unsupported number of components: %d\n", image->comps[0].prec);
564         return 1;
565     }
566     if (image->numcomps >= 3 && image->comps[0].dx == image->comps[1].dx
567             && image->comps[1].dx == image->comps[2].dx
568             && image->comps[0].dy == image->comps[1].dy
569             && image->comps[1].dy == image->comps[2].dy
570             && image->comps[0].prec == image->comps[1].prec
571             && image->comps[1].prec == image->comps[2].prec) {
572
573         /* -->> -->> -->> -->>
574         24 bits color
575         <<-- <<-- <<-- <<-- */
576
577         fdest = fopen(outfile, "wb");
578         if (!fdest) {
579             fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
580             return 1;
581         }
582
583         w = (int)image->comps[0].w;
584         h = (int)image->comps[0].h;
585
586         fprintf(fdest, "BM");
587
588         /* FILE HEADER */
589         /* ------------- */
590         fprintf(fdest, "%c%c%c%c",
591                 (OPJ_UINT8) (h * w * 3 + 3 * h * (w % 2) + 54) & 0xff,
592                 (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 8) & 0xff,
593                 (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 16) & 0xff,
594                 (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 24) & 0xff);
595         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
596         fprintf(fdest, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff,((54) >> 16) & 0xff, ((54) >> 24) & 0xff);
597
598         /* INFO HEADER   */
599         /* ------------- */
600         fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff,     ((40) >> 16) & 0xff, ((40) >> 24) & 0xff);
601         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) ((w) & 0xff),
602                 (OPJ_UINT8) ((w) >> 8) & 0xff,
603                 (OPJ_UINT8) ((w) >> 16) & 0xff,
604                 (OPJ_UINT8) ((w) >> 24) & 0xff);
605         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) ((h) & 0xff),
606                 (OPJ_UINT8) ((h) >> 8) & 0xff,
607                 (OPJ_UINT8) ((h) >> 16) & 0xff,
608                 (OPJ_UINT8) ((h) >> 24) & 0xff);
609         fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
610         fprintf(fdest, "%c%c", (24) & 0xff, ((24) >> 8) & 0xff);
611         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
612         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) (3 * h * w + 3 * h * (w % 2)) & 0xff,
613                 (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2)) >> 8) & 0xff,
614                 (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2)) >> 16) & 0xff,
615                 (OPJ_UINT8) ((h * w * 3 + 3 * h * (w % 2)) >> 24) & 0xff);
616         fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
617         fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
618         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
619         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
620
621         if (image->comps[0].prec > 8) {
622             adjustR = (int)image->comps[0].prec - 8;
623             printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec);
624         }
625         else
626             adjustR = 0;
627         if (image->comps[1].prec > 8) {
628             adjustG = (int)image->comps[1].prec - 8;
629             printf("BMP CONVERSION: Truncating component 1 from %d bits to 8 bits\n", image->comps[1].prec);
630         }
631         else
632             adjustG = 0;
633         if (image->comps[2].prec > 8) {
634             adjustB = (int)image->comps[2].prec - 8;
635             printf("BMP CONVERSION: Truncating component 2 from %d bits to 8 bits\n", image->comps[2].prec);
636         }
637         else
638             adjustB = 0;
639
640         for (i = 0; i < w * h; i++) {
641             OPJ_UINT8 rc, gc, bc;
642             int r, g, b;
643
644             r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
645             r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
646             r = ((r >> adjustR)+((r >> (adjustR-1))%2));
647             if(r > 255) r = 255; else if(r < 0) r = 0;
648             rc = (OPJ_UINT8)r;
649
650             g = image->comps[1].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
651             g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
652             g = ((g >> adjustG)+((g >> (adjustG-1))%2));
653             if(g > 255) g = 255; else if(g < 0) g = 0;
654             gc = (OPJ_UINT8)g;
655
656             b = image->comps[2].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
657             b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
658             b = ((b >> adjustB)+((b >> (adjustB-1))%2));
659             if(b > 255) b = 255; else if(b < 0) b = 0;
660             bc = (OPJ_UINT8)b;
661
662             fprintf(fdest, "%c%c%c", bc, gc, rc);
663
664             if ((i + 1) % w == 0) {
665                 for (pad = (3 * w) % 4 ? 4 - (3 * w) % 4 : 0; pad > 0; pad--)   /* ADD */
666                     fprintf(fdest, "%c", 0);
667             }
668         }
669         fclose(fdest);
670     } else {                    /* Gray-scale */
671
672         /* -->> -->> -->> -->>
673         8 bits non code (Gray scale)
674         <<-- <<-- <<-- <<-- */
675
676         fdest = fopen(outfile, "wb");
677         w = (int)image->comps[0].w;
678         h = (int)image->comps[0].h;
679
680         fprintf(fdest, "BM");
681
682         /* FILE HEADER */
683         /* ------------- */
684         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) (h * w + 54 + 1024 + h * (w % 2)) & 0xff,
685                 (OPJ_UINT8) ((h * w + 54 + 1024 + h * (w % 2)) >> 8) & 0xff,
686                 (OPJ_UINT8) ((h * w + 54 + 1024 + h * (w % 2)) >> 16) & 0xff,
687                 (OPJ_UINT8) ((h * w + 54 + 1024 + w * (w % 2)) >> 24) & 0xff);
688         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
689         fprintf(fdest, "%c%c%c%c", (54 + 1024) & 0xff, ((54 + 1024) >> 8) & 0xff,
690                 ((54 + 1024) >> 16) & 0xff,
691                 ((54 + 1024) >> 24) & 0xff);
692
693         /* INFO HEADER */
694         /* ------------- */
695         fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff,     ((40) >> 16) & 0xff, ((40) >> 24) & 0xff);
696         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) ((w) & 0xff),
697                 (OPJ_UINT8) ((w) >> 8) & 0xff,
698                 (OPJ_UINT8) ((w) >> 16) & 0xff,
699                 (OPJ_UINT8) ((w) >> 24) & 0xff);
700         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) ((h) & 0xff),
701                 (OPJ_UINT8) ((h) >> 8) & 0xff,
702                 (OPJ_UINT8) ((h) >> 16) & 0xff,
703                 (OPJ_UINT8) ((h) >> 24) & 0xff);
704         fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
705         fprintf(fdest, "%c%c", (8) & 0xff, ((8) >> 8) & 0xff);
706         fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
707         fprintf(fdest, "%c%c%c%c", (OPJ_UINT8) (h * w + h * (w % 2)) & 0xff,
708                 (OPJ_UINT8) ((h * w + h * (w % 2)) >> 8) &      0xff,
709                 (OPJ_UINT8) ((h * w + h * (w % 2)) >> 16) &     0xff,
710                 (OPJ_UINT8) ((h * w + h * (w % 2)) >> 24) & 0xff);
711         fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
712         fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
713         fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, ((256) >> 16) & 0xff, ((256) >> 24) & 0xff);
714         fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, ((256) >> 16) & 0xff, ((256) >> 24) & 0xff);
715
716         if (image->comps[0].prec > 8) {
717             adjustR = (int)image->comps[0].prec - 8;
718             printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec);
719         }else
720             adjustR = 0;
721
722         for (i = 0; i < 256; i++) {
723             fprintf(fdest, "%c%c%c%c", i, i, i, 0);
724         }
725
726         for (i = 0; i < w * h; i++) {
727             int r;
728
729             r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
730             r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
731             r = ((r >> adjustR)+((r >> (adjustR-1))%2));
732             if(r > 255) r = 255; else if(r < 0) r = 0;
733
734             fprintf(fdest, "%c", (OPJ_UINT8)r);
735
736             if ((i + 1) % w == 0) {
737                 for (pad = w % 4 ? 4 - w % 4 : 0; pad > 0; pad--)       /* ADD */
738                     fprintf(fdest, "%c", 0);
739             }
740         }
741         fclose(fdest);
742     }
743
744     return 0;
745 }