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.
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.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
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.
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.
38 #include "opj_apps_config.h"
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;
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;
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)
91 for (y = height; y != 0U; --y) {
94 for (x = 0; x < width; x++) {
95 pDst[x] = (OPJ_INT32)pLUT[pSrc[x]];
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)
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];
116 for (y = height; y != 0U; --y) {
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];
132 static void bmp24toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride,
136 OPJ_UINT32 width, height;
138 const OPJ_UINT8 *pSrc = NULL;
140 width = image->comps[0].w;
141 height = image->comps[0].h;
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 */
156 static void bmp_mask_get_shift_and_prec(OPJ_UINT32 mask, OPJ_UINT32* shift,
159 OPJ_UINT32 l_shift, l_prec;
161 l_shift = l_prec = 0U;
164 while ((mask & 1U) == 0U) {
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)
182 OPJ_UINT32 width, height;
184 const OPJ_UINT8 *pSrc = NULL;
186 OPJ_UINT32 redShift, redPrec;
187 OPJ_UINT32 greenShift, greenPrec;
188 OPJ_UINT32 blueShift, bluePrec;
189 OPJ_UINT32 alphaShift, alphaPrec;
191 width = image->comps[0].w;
192 height = image->comps[0].h;
194 hasAlpha = image->numcomps > 3U;
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);
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;
208 image->comps[3].bpp = alphaPrec;
209 image->comps[3].prec = alphaPrec;
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;
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;
223 image->comps[0].data[index] = (OPJ_INT32)((value & redMask) >>
225 image->comps[1].data[index] = (OPJ_INT32)((value & greenMask) >>
227 image->comps[2].data[index] = (OPJ_INT32)((value & blueMask) >>
230 image->comps[3].data[index] = (OPJ_INT32)((value & alphaMask) >>
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)
244 OPJ_UINT32 width, height;
246 const OPJ_UINT8 *pSrc = NULL;
248 OPJ_UINT32 redShift, redPrec;
249 OPJ_UINT32 greenShift, greenPrec;
250 OPJ_UINT32 blueShift, bluePrec;
251 OPJ_UINT32 alphaShift, alphaPrec;
253 width = image->comps[0].w;
254 height = image->comps[0].h;
256 hasAlpha = image->numcomps > 3U;
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);
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;
270 image->comps[3].bpp = alphaPrec;
271 image->comps[3].prec = alphaPrec;
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;
280 value |= ((OPJ_UINT32)pSrc[2 * x + 0]) << 0;
281 value |= ((OPJ_UINT32)pSrc[2 * x + 1]) << 8;
283 image->comps[0].data[index] = (OPJ_INT32)((value & redMask) >>
285 image->comps[1].data[index] = (OPJ_INT32)((value & greenMask) >>
287 image->comps[2].data[index] = (OPJ_INT32)((value & blueMask) >>
290 image->comps[3].data[index] = (OPJ_INT32)((value & alphaMask) >>
299 static opj_image_t* bmp8toimage(const OPJ_UINT8* pData, OPJ_UINT32 stride,
300 opj_image_t* image, OPJ_UINT8 const* const* pLUT)
302 OPJ_UINT32 width, height;
303 const OPJ_UINT8 *pSrc = NULL;
305 width = image->comps[0].w;
306 height = image->comps[0].h;
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);
314 OPJ_INT32 pDstStride[3];
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,
328 static OPJ_BOOL bmp_read_file_header(FILE* IN, OPJ_BITMAPFILEHEADER* header)
330 header->bfType = (OPJ_UINT16)getc(IN);
331 header->bfType |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8);
333 if (header->bfType != 19778) {
334 fprintf(stderr, "Error, not a BMP file!\n");
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;
345 header->bfReserved1 = (OPJ_UINT16)getc(IN);
346 header->bfReserved1 |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8);
348 header->bfReserved2 = (OPJ_UINT16)getc(IN);
349 header->bfReserved2 |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8);
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;
357 static OPJ_BOOL bmp_read_info_header(FILE* IN, OPJ_BITMAPINFOHEADER* header)
359 memset(header, 0, sizeof(*header));
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;
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 */
376 fprintf(stderr, "Error, unknown BMP header size %d\n", header->biSize);
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;
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;
390 header->biPlanes = (OPJ_UINT16)getc(IN);
391 header->biPlanes |= (OPJ_UINT16)((OPJ_UINT32)getc(IN) << 8);
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);
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;
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;
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;
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;
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;
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;
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;
438 if (!header->biRedMask) {
439 fprintf(stderr, "Error, invalid red mask value %d\n", header->biRedMask);
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;
448 if (!header->biGreenMask) {
449 fprintf(stderr, "Error, invalid green mask value %d\n", header->biGreenMask);
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;
458 if (!header->biBlueMask) {
459 fprintf(stderr, "Error, invalid blue mask value %d\n", header->biBlueMask);
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;
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;
475 if (fread(&(header->biColorSpaceEP), 1U, sizeof(header->biColorSpaceEP),
476 IN) != sizeof(header->biColorSpaceEP)) {
477 fprintf(stderr, "Error, can't read BMP header\n");
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;
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;
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;
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;
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;
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;
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;
521 static OPJ_BOOL bmp_read_raw_data(FILE* IN, OPJ_UINT8* pData, OPJ_UINT32 stride,
522 OPJ_UINT32 width, OPJ_UINT32 height)
524 OPJ_ARG_NOT_USED(width);
526 if (fread(pData, sizeof(OPJ_UINT8), stride * height, IN) != (stride * height)) {
528 "\nError: fread return a number of element different from the expected.\n");
534 static OPJ_BOOL bmp_read_rle8_data(FILE* IN, OPJ_UINT8* pData,
535 OPJ_UINT32 stride, OPJ_UINT32 width, OPJ_UINT32 height)
537 OPJ_UINT32 x, y, written;
539 const OPJ_UINT8 *beyond;
541 beyond = pData + stride * height;
544 x = y = written = 0U;
559 c1 = (OPJ_UINT8)c1_int;
561 for (j = 0; (j < c) && (x < width) &&
562 ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
572 if (c == 0x00) { /* EOL */
575 pix = pData + y * stride + x;
576 } else if (c == 0x01) { /* EOP */
578 } else if (c == 0x02) { /* MOVE by dxdy */
589 pix = pData + y * stride + x;
590 } else { /* 03 .. 255 */
592 for (j = 0; (j < c) && (x < width) &&
593 ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
600 c1 = (OPJ_UINT8)c1_int;
604 if ((OPJ_UINT32)c & 1U) { /* skip padding byte */
614 if (written != width * height) {
615 fprintf(stderr, "warning, image's actual size does not match advertized one\n");
622 static OPJ_BOOL bmp_read_rle4_data(FILE* IN, OPJ_UINT8* pData,
623 OPJ_UINT32 stride, OPJ_UINT32 width, OPJ_UINT32 height)
627 const OPJ_UINT8 *beyond;
629 beyond = pData + stride * height;
638 if (c) { /* encoded mode */
640 OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN);
642 for (j = 0; (j < c) && (x < width) &&
643 ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
644 *pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU));
646 } else { /* absolute mode */
652 if (c == 0x00) { /* EOL */
655 pix = pData + y * stride;
656 } else if (c == 0x01) { /* EOP */
658 } else if (c == 0x02) { /* MOVE by dxdy */
663 pix = pData + y * stride + x;
664 } else { /* 03 .. 255 : absolute mode */
668 for (j = 0; (j < c) && (x < width) &&
669 ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
671 c1 = (OPJ_UINT8)getc(IN);
673 *pix = (OPJ_UINT8)((j & 1) ? (c1 & 0x0fU) : ((c1 >> 4) & 0x0fU));
675 if (((c & 3) == 1) || ((c & 3) == 2)) { /* skip padding byte */
680 } /* while(y < height) */
684 opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters)
686 opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */
687 OPJ_UINT8 lut_R[256], lut_G[256], lut_B[256];
688 OPJ_UINT8 const* pLUT[3];
689 opj_image_t * image = NULL;
691 OPJ_BITMAPFILEHEADER File_h;
692 OPJ_BITMAPINFOHEADER Info_h;
693 OPJ_UINT32 i, palette_len, numcmpts = 1U;
694 OPJ_BOOL l_result = OPJ_FALSE;
695 OPJ_UINT8* pData = NULL;
702 IN = fopen(filename, "rb");
704 fprintf(stderr, "Failed to open %s for reading !!\n", filename);
708 if (!bmp_read_file_header(IN, &File_h)) {
712 if (!bmp_read_info_header(IN, &Info_h)) {
718 if (Info_h.biBitCount <= 8U) {
719 memset(&lut_R[0], 0, sizeof(lut_R));
720 memset(&lut_G[0], 0, sizeof(lut_G));
721 memset(&lut_B[0], 0, sizeof(lut_B));
723 palette_len = Info_h.biClrUsed;
724 if ((palette_len == 0U) && (Info_h.biBitCount <= 8U)) {
725 palette_len = (1U << Info_h.biBitCount);
727 if (palette_len > 256U) {
730 if (palette_len > 0U) {
731 OPJ_UINT8 has_color = 0U;
732 for (i = 0U; i < palette_len; i++) {
733 lut_B[i] = (OPJ_UINT8)getc(IN);
734 lut_G[i] = (OPJ_UINT8)getc(IN);
735 lut_R[i] = (OPJ_UINT8)getc(IN);
736 (void)getc(IN); /* padding */
737 has_color |= (lut_B[i] ^ lut_G[i]) | (lut_G[i] ^ lut_R[i]);
745 if ((Info_h.biCompression == 3) && (Info_h.biAlphaMask != 0U)) {
750 if (Info_h.biWidth == 0 || Info_h.biHeight == 0) {
755 if (Info_h.biBitCount > (((OPJ_UINT32) - 1) - 31) / Info_h.biWidth) {
759 stride = ((Info_h.biWidth * Info_h.biBitCount + 31U) / 32U) *
760 4U; /* rows are aligned on 32bits */
761 if (Info_h.biBitCount == 4 &&
762 Info_h.biCompression == 2) { /* RLE 4 gets decoded as 8 bits data for now... */
763 if (8 > (((OPJ_UINT32) - 1) - 31) / Info_h.biWidth) {
767 stride = ((Info_h.biWidth * 8U + 31U) / 32U) * 4U;
770 if (stride > ((OPJ_UINT32) - 1) / sizeof(OPJ_UINT8) / Info_h.biHeight) {
774 pData = (OPJ_UINT8 *) calloc(1, sizeof(OPJ_UINT8) * stride * Info_h.biHeight);
779 /* Place the cursor at the beginning of the image information */
780 fseek(IN, 0, SEEK_SET);
781 fseek(IN, (long)File_h.bfOffBits, SEEK_SET);
783 switch (Info_h.biCompression) {
787 l_result = bmp_read_raw_data(IN, pData, stride, Info_h.biWidth,
792 l_result = bmp_read_rle8_data(IN, pData, stride, Info_h.biWidth,
797 l_result = bmp_read_rle4_data(IN, pData, stride, Info_h.biWidth,
801 fprintf(stderr, "Unsupported BMP compression\n");
802 l_result = OPJ_FALSE;
811 /* create the image */
812 memset(&cmptparm[0], 0, sizeof(cmptparm));
813 for (i = 0; i < 4U; i++) {
814 cmptparm[i].prec = 8;
816 cmptparm[i].sgnd = 0;
817 cmptparm[i].dx = (OPJ_UINT32)parameters->subsampling_dx;
818 cmptparm[i].dy = (OPJ_UINT32)parameters->subsampling_dy;
819 cmptparm[i].w = Info_h.biWidth;
820 cmptparm[i].h = Info_h.biHeight;
823 image = opj_image_create(numcmpts, &cmptparm[0],
824 (numcmpts == 1U) ? OPJ_CLRSPC_GRAY : OPJ_CLRSPC_SRGB);
830 if (numcmpts == 4U) {
831 image->comps[3].alpha = 1;
834 /* set image offset and reference grid */
835 image->x0 = (OPJ_UINT32)parameters->image_offset_x0;
836 image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
837 image->x1 = image->x0 + (Info_h.biWidth - 1U) * (OPJ_UINT32)
838 parameters->subsampling_dx + 1U;
839 image->y1 = image->y0 + (Info_h.biHeight - 1U) * (OPJ_UINT32)
840 parameters->subsampling_dy + 1U;
843 if (Info_h.biBitCount == 24 && Info_h.biCompression == 0) { /*RGB */
844 bmp24toimage(pData, stride, image);
845 } else if (Info_h.biBitCount == 8 &&
846 Info_h.biCompression == 0) { /* RGB 8bpp Indexed */
847 bmp8toimage(pData, stride, image, pLUT);
848 } else if (Info_h.biBitCount == 8 && Info_h.biCompression == 1) { /*RLE8*/
849 bmp8toimage(pData, stride, image, pLUT);
850 } else if (Info_h.biBitCount == 4 && Info_h.biCompression == 2) { /*RLE4*/
851 bmp8toimage(pData, stride, image,
852 pLUT); /* RLE 4 gets decoded as 8 bits data for now */
853 } else if (Info_h.biBitCount == 32 && Info_h.biCompression == 0) { /* RGBX */
854 bmpmask32toimage(pData, stride, image, 0x00FF0000U, 0x0000FF00U, 0x000000FFU,
856 } else if (Info_h.biBitCount == 32 && Info_h.biCompression == 3) { /* bitmask */
857 if ((Info_h.biRedMask == 0U) && (Info_h.biGreenMask == 0U) &&
858 (Info_h.biBlueMask == 0U)) {
859 Info_h.biRedMask = 0x00FF0000U;
860 Info_h.biGreenMask = 0x0000FF00U;
861 Info_h.biBlueMask = 0x000000FFU;
863 bmpmask32toimage(pData, stride, image, Info_h.biRedMask, Info_h.biGreenMask,
864 Info_h.biBlueMask, Info_h.biAlphaMask);
865 } else if (Info_h.biBitCount == 16 && Info_h.biCompression == 0) { /* RGBX */
866 bmpmask16toimage(pData, stride, image, 0x7C00U, 0x03E0U, 0x001FU, 0x0000U);
867 } else if (Info_h.biBitCount == 16 && Info_h.biCompression == 3) { /* bitmask */
868 if ((Info_h.biRedMask == 0U) && (Info_h.biGreenMask == 0U) &&
869 (Info_h.biBlueMask == 0U)) {
870 Info_h.biRedMask = 0xF800U;
871 Info_h.biGreenMask = 0x07E0U;
872 Info_h.biBlueMask = 0x001FU;
874 bmpmask16toimage(pData, stride, image, Info_h.biRedMask, Info_h.biGreenMask,
875 Info_h.biBlueMask, Info_h.biAlphaMask);
877 opj_image_destroy(image);
880 "Other system than 24 bits/pixels or 8 bits (no RLE coding) is not yet implemented [%d]\n",
888 int imagetobmp(opj_image_t * image, const char *outfile)
893 int adjustR, adjustG, adjustB;
895 if (image->comps[0].prec < 8) {
896 fprintf(stderr, "imagetobmp: Unsupported precision: %d\n",
897 image->comps[0].prec);
900 if (image->numcomps >= 3 && image->comps[0].dx == image->comps[1].dx
901 && image->comps[1].dx == image->comps[2].dx
902 && image->comps[0].dy == image->comps[1].dy
903 && image->comps[1].dy == image->comps[2].dy
904 && image->comps[0].prec == image->comps[1].prec
905 && image->comps[1].prec == image->comps[2].prec
906 && image->comps[0].sgnd == image->comps[1].sgnd
907 && image->comps[1].sgnd == image->comps[2].sgnd) {
909 /* -->> -->> -->> -->>
911 <<-- <<-- <<-- <<-- */
913 fdest = fopen(outfile, "wb");
915 fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
919 w = (int)image->comps[0].w;
920 h = (int)image->comps[0].h;
922 fprintf(fdest, "BM");
926 fprintf(fdest, "%c%c%c%c",
927 (OPJ_UINT8)(h * w * 3 + 3 * h * (w % 2) + 54) & 0xff,
928 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2) + 54) >> 8) & 0xff,
929 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2) + 54) >> 16) & 0xff,
930 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2) + 54) >> 24) & 0xff);
931 fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
933 fprintf(fdest, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff, ((54) >> 16) & 0xff,
934 ((54) >> 24) & 0xff);
938 fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff,
939 ((40) >> 24) & 0xff);
940 fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((w) & 0xff),
941 (OPJ_UINT8)((w) >> 8) & 0xff,
942 (OPJ_UINT8)((w) >> 16) & 0xff,
943 (OPJ_UINT8)((w) >> 24) & 0xff);
944 fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((h) & 0xff),
945 (OPJ_UINT8)((h) >> 8) & 0xff,
946 (OPJ_UINT8)((h) >> 16) & 0xff,
947 (OPJ_UINT8)((h) >> 24) & 0xff);
948 fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
949 fprintf(fdest, "%c%c", (24) & 0xff, ((24) >> 8) & 0xff);
950 fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
952 fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)(3 * h * w + 3 * h * (w % 2)) & 0xff,
953 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2)) >> 8) & 0xff,
954 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2)) >> 16) & 0xff,
955 (OPJ_UINT8)((h * w * 3 + 3 * h * (w % 2)) >> 24) & 0xff);
956 fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
957 ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
958 fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
959 ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
960 fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
962 fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
965 if (image->comps[0].prec > 8) {
966 adjustR = (int)image->comps[0].prec - 8;
967 printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n",
968 image->comps[0].prec);
972 if (image->comps[1].prec > 8) {
973 adjustG = (int)image->comps[1].prec - 8;
974 printf("BMP CONVERSION: Truncating component 1 from %d bits to 8 bits\n",
975 image->comps[1].prec);
979 if (image->comps[2].prec > 8) {
980 adjustB = (int)image->comps[2].prec - 8;
981 printf("BMP CONVERSION: Truncating component 2 from %d bits to 8 bits\n",
982 image->comps[2].prec);
987 for (i = 0; i < w * h; i++) {
988 OPJ_UINT8 rc, gc, bc;
991 r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
992 r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
994 r = ((r >> adjustR) + ((r >> (adjustR - 1)) % 2));
1003 g = image->comps[1].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
1004 g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
1006 g = ((g >> adjustG) + ((g >> (adjustG - 1)) % 2));
1015 b = image->comps[2].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
1016 b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
1018 b = ((b >> adjustB) + ((b >> (adjustB - 1)) % 2));
1027 fprintf(fdest, "%c%c%c", bc, gc, rc);
1029 if ((i + 1) % w == 0) {
1030 for (pad = ((3 * w) % 4) ? (4 - (3 * w) % 4) : 0; pad > 0; pad--) { /* ADD */
1031 fprintf(fdest, "%c", 0);
1036 } else { /* Gray-scale */
1038 /* -->> -->> -->> -->>
1039 8 bits non code (Gray scale)
1040 <<-- <<-- <<-- <<-- */
1042 fdest = fopen(outfile, "wb");
1044 fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
1047 if (image->numcomps > 1) {
1048 fprintf(stderr, "imagetobmp: only first component of %d is used.\n",
1051 w = (int)image->comps[0].w;
1052 h = (int)image->comps[0].h;
1054 fprintf(fdest, "BM");
1058 fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)(h * w + 54 + 1024 + h * (w % 2)) & 0xff,
1059 (OPJ_UINT8)((h * w + 54 + 1024 + h * (w % 2)) >> 8) & 0xff,
1060 (OPJ_UINT8)((h * w + 54 + 1024 + h * (w % 2)) >> 16) & 0xff,
1061 (OPJ_UINT8)((h * w + 54 + 1024 + w * (w % 2)) >> 24) & 0xff);
1062 fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
1063 ((0) >> 24) & 0xff);
1064 fprintf(fdest, "%c%c%c%c", (54 + 1024) & 0xff, ((54 + 1024) >> 8) & 0xff,
1065 ((54 + 1024) >> 16) & 0xff,
1066 ((54 + 1024) >> 24) & 0xff);
1070 fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff,
1071 ((40) >> 24) & 0xff);
1072 fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((w) & 0xff),
1073 (OPJ_UINT8)((w) >> 8) & 0xff,
1074 (OPJ_UINT8)((w) >> 16) & 0xff,
1075 (OPJ_UINT8)((w) >> 24) & 0xff);
1076 fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)((h) & 0xff),
1077 (OPJ_UINT8)((h) >> 8) & 0xff,
1078 (OPJ_UINT8)((h) >> 16) & 0xff,
1079 (OPJ_UINT8)((h) >> 24) & 0xff);
1080 fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
1081 fprintf(fdest, "%c%c", (8) & 0xff, ((8) >> 8) & 0xff);
1082 fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff,
1083 ((0) >> 24) & 0xff);
1084 fprintf(fdest, "%c%c%c%c", (OPJ_UINT8)(h * w + h * (w % 2)) & 0xff,
1085 (OPJ_UINT8)((h * w + h * (w % 2)) >> 8) & 0xff,
1086 (OPJ_UINT8)((h * w + h * (w % 2)) >> 16) & 0xff,
1087 (OPJ_UINT8)((h * w + h * (w % 2)) >> 24) & 0xff);
1088 fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
1089 ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
1090 fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
1091 ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
1092 fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff,
1093 ((256) >> 16) & 0xff, ((256) >> 24) & 0xff);
1094 fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff,
1095 ((256) >> 16) & 0xff, ((256) >> 24) & 0xff);
1097 if (image->comps[0].prec > 8) {
1098 adjustR = (int)image->comps[0].prec - 8;
1099 printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n",
1100 image->comps[0].prec);
1105 for (i = 0; i < 256; i++) {
1106 fprintf(fdest, "%c%c%c%c", i, i, i, 0);
1109 for (i = 0; i < w * h; i++) {
1112 r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
1113 r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
1115 r = ((r >> adjustR) + ((r >> (adjustR - 1)) % 2));
1123 fprintf(fdest, "%c", (OPJ_UINT8)r);
1125 if ((i + 1) % w == 0) {
1126 for (pad = (w % 4) ? (4 - w % 4) : 0; pad > 0; pad--) { /* ADD */
1127 fprintf(fdest, "%c", 0);