ReactOS 0.4.16-dev-122-g325d74c
rdbmp.c
Go to the documentation of this file.
1/*
2 * rdbmp.c
3 *
4 * Copyright (C) 1994-1996, Thomas G. Lane.
5 * Modified 2009-2019 by Guido Vollbeding.
6 * This file is part of the Independent JPEG Group's software.
7 * For conditions of distribution and use, see the accompanying README file.
8 *
9 * This file contains routines to read input images in Microsoft "BMP"
10 * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors).
11 * Currently, only 8-, 24-, and 32-bit images are supported, not 1-bit or
12 * 4-bit (feeding such low-depth images into JPEG would be silly anyway).
13 * Also, we don't support RLE-compressed files.
14 *
15 * These routines may need modification for non-Unix environments or
16 * specialized applications. As they stand, they assume input from
17 * an ordinary stdio stream. They further assume that reading begins
18 * at the start of the file; start_input may need work if the
19 * user interface has already read some data (e.g., to determine that
20 * the file is indeed BMP format).
21 *
22 * This code contributed by James Arthur Boucher.
23 */
24
25#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
26
27#ifdef BMP_SUPPORTED
28
29
30/* Macros to deal with unsigned chars as efficiently as compiler allows */
31
32#ifdef HAVE_UNSIGNED_CHAR
33typedef unsigned char U_CHAR;
34#define UCH(x) ((int) (x))
35#else /* !HAVE_UNSIGNED_CHAR */
36typedef char U_CHAR;
37#ifdef CHAR_IS_UNSIGNED
38#define UCH(x) ((int) (x))
39#else
40#define UCH(x) ((int) (x) & 0xFF)
41#endif
42#endif /* HAVE_UNSIGNED_CHAR */
43
44
45#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
46
47
48/* Private version of data source object */
49
50typedef struct _bmp_source_struct * bmp_source_ptr;
51
52typedef struct _bmp_source_struct {
53 struct cjpeg_source_struct pub; /* public fields */
54
55 j_compress_ptr cinfo; /* back link saves passing separate parm */
56
57 JSAMPARRAY colormap; /* BMP colormap (converted to my format) */
58
59 jvirt_sarray_ptr whole_image; /* Needed to reverse row order */
60 JDIMENSION source_row; /* Current source row number */
61 JDIMENSION row_width; /* Physical width of scanlines in file */
62
63 int bits_per_pixel; /* remembers 8-, 24-, or 32-bit format */
64 int cmap_length; /* colormap length */
65} bmp_source_struct;
66
67
68LOCAL(int)
69read_byte (bmp_source_ptr sinfo)
70/* Read next byte from BMP file */
71{
72 register FILE *infile = sinfo->pub.input_file;
73 register int c;
74
75 if ((c = getc(infile)) == EOF)
76 ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
77 return c;
78}
79
80
81LOCAL(void)
82read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize)
83/* Read the colormap from a BMP file */
84{
85 int i;
86
87 switch (mapentrysize) {
88 case 3:
89 /* BGR format (occurs in OS/2 files) */
90 for (i = 0; i < cmaplen; i++) {
91 sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
92 sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
93 sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
94 }
95 break;
96 case 4:
97 /* BGR0 format (occurs in MS Windows files) */
98 for (i = 0; i < cmaplen; i++) {
99 sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
100 sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
101 sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
103 }
104 break;
105 default:
106 ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
107 }
108}
109
110
111/*
112 * Read one row of pixels.
113 * The image has been read into the whole_image array, but is otherwise
114 * unprocessed. We must read it out in top-to-bottom row order, and if
115 * it is an 8-bit image, we must expand colormapped pixels to 24bit format.
116 */
117
119get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
120/* This version is for reading 8-bit colormap indexes */
121{
122 bmp_source_ptr source = (bmp_source_ptr) sinfo;
123 register JSAMPROW inptr, outptr;
124 register JSAMPARRAY colormap;
125 register JDIMENSION col;
126 register int t;
127 int cmaplen;
128
129 /* Fetch next row from virtual array */
130 source->source_row--;
131 inptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo,
132 source->whole_image, source->source_row, (JDIMENSION) 1, FALSE);
133
134 /* Expand the colormap indexes to real data */
135 outptr = source->pub.buffer[0];
136 colormap = source->colormap;
137 cmaplen = source->cmap_length;
138 for (col = cinfo->image_width; col > 0; col--) {
139 t = GETJSAMPLE(*inptr++);
140 if (t >= cmaplen)
141 ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
142 *outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */
143 *outptr++ = colormap[1][t];
144 *outptr++ = colormap[2][t];
145 }
146
147 return 1;
148}
149
151get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
152/* This version is for reading 24-bit pixels */
153{
154 bmp_source_ptr source = (bmp_source_ptr) sinfo;
155 register JSAMPROW inptr, outptr;
156 register JDIMENSION col;
157
158 /* Fetch next row from virtual array */
159 source->source_row--;
160 inptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo,
161 source->whole_image, source->source_row, (JDIMENSION) 1, FALSE);
162
163 /* Transfer data. Note source values are in BGR order
164 * (even though Microsoft's own documents say the opposite).
165 */
166 outptr = source->pub.buffer[0];
167 for (col = cinfo->image_width; col > 0; col--) {
168 outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
169 outptr[1] = *inptr++;
170 outptr[0] = *inptr++;
171 outptr += 3;
172 }
173
174 return 1;
175}
176
178get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
179/* This version is for reading 32-bit pixels */
180{
181 bmp_source_ptr source = (bmp_source_ptr) sinfo;
182 register JSAMPROW inptr, outptr;
183 register JDIMENSION col;
184
185 /* Fetch next row from virtual array */
186 source->source_row--;
187 inptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo,
188 source->whole_image, source->source_row, (JDIMENSION) 1, FALSE);
189
190 /* Transfer data. Note source values are in BGR order
191 * (even though Microsoft's own documents say the opposite).
192 */
193 outptr = source->pub.buffer[0];
194 for (col = cinfo->image_width; col > 0; col--) {
195 outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
196 outptr[1] = *inptr++;
197 outptr[0] = *inptr++;
198 inptr++; /* skip the 4th byte (Alpha channel) */
199 outptr += 3;
200 }
201
202 return 1;
203}
204
205
206/*
207 * This method loads the image into whole_image during the first call on
208 * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
209 * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls.
210 */
211
213preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
214{
215 bmp_source_ptr source = (bmp_source_ptr) sinfo;
216 register FILE *infile = source->pub.input_file;
217 register int c;
218 register JSAMPROW out_ptr;
219 JDIMENSION row, col;
220 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
221
222 /* Read the data into a virtual array in input-file row order. */
223 for (row = 0; row < cinfo->image_height; row++) {
224 if (progress != NULL) {
225 progress->pub.pass_counter = (long) row;
226 progress->pub.pass_limit = (long) cinfo->image_height;
227 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
228 }
229 out_ptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo,
230 source->whole_image, row, (JDIMENSION) 1, TRUE);
231 for (col = source->row_width; col > 0; col--) {
232 /* inline copy of read_byte() for speed */
233 if ((c = getc(infile)) == EOF)
234 ERREXIT(cinfo, JERR_INPUT_EOF);
235 *out_ptr++ = (JSAMPLE) c;
236 }
237 }
238 if (progress != NULL)
240
241 /* Set up to read from the virtual array in top-to-bottom order */
242 switch (source->bits_per_pixel) {
243 case 8:
244 source->pub.get_pixel_rows = get_8bit_row;
245 break;
246 case 24:
247 source->pub.get_pixel_rows = get_24bit_row;
248 break;
249 case 32:
250 source->pub.get_pixel_rows = get_32bit_row;
251 break;
252 default:
253 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
254 }
255 source->source_row = cinfo->image_height;
256
257 /* And read the first row */
258 return (*source->pub.get_pixel_rows) (cinfo, sinfo);
259}
260
261
262/*
263 * Read the file header; return image size and component count.
264 */
265
266METHODDEF(void)
267start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
268{
269 bmp_source_ptr source = (bmp_source_ptr) sinfo;
270 U_CHAR bmpfileheader[14];
271 U_CHAR bmpinfoheader[64];
272#define GET_2B(array, offset) ((unsigned int) UCH(array[offset]) + \
273 (((unsigned int) UCH(array[offset+1])) << 8))
274#define GET_4B(array, offset) ((INT32) UCH(array[offset]) + \
275 (((INT32) UCH(array[offset+1])) << 8) + \
276 (((INT32) UCH(array[offset+2])) << 16) + \
277 (((INT32) UCH(array[offset+3])) << 24))
278 INT32 bfOffBits;
279 INT32 headerSize;
280 INT32 biWidth;
281 INT32 biHeight;
282 unsigned int biPlanes;
283 INT32 biCompression;
284 INT32 biXPelsPerMeter,biYPelsPerMeter;
285 INT32 biClrUsed = 0;
286 int mapentrysize = 0; /* 0 indicates no colormap */
287 INT32 bPad;
288 JDIMENSION row_width;
289
290 /* Read and verify the bitmap file header */
291 if (! ReadOK(source->pub.input_file, bmpfileheader, 14))
292 ERREXIT(cinfo, JERR_INPUT_EOF);
293 if (GET_2B(bmpfileheader, 0) != 0x4D42) /* 'BM' */
294 ERREXIT(cinfo, JERR_BMP_NOT);
295 bfOffBits = GET_4B(bmpfileheader, 10);
296 /* We ignore the remaining fileheader fields */
297
298 /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
299 * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which.
300 */
301 if (! ReadOK(source->pub.input_file, bmpinfoheader, 4))
302 ERREXIT(cinfo, JERR_INPUT_EOF);
303 headerSize = GET_4B(bmpinfoheader, 0);
304 if (headerSize < 12 || headerSize > 64)
305 ERREXIT(cinfo, JERR_BMP_BADHEADER);
306 if (! ReadOK(source->pub.input_file, bmpinfoheader + 4, headerSize - 4))
307 ERREXIT(cinfo, JERR_INPUT_EOF);
308
309 switch ((int) headerSize) {
310 case 12:
311 /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
312 biWidth = (INT32) GET_2B(bmpinfoheader, 4);
313 biHeight = (INT32) GET_2B(bmpinfoheader, 6);
314 biPlanes = GET_2B(bmpinfoheader, 8);
315 source->bits_per_pixel = (int) GET_2B(bmpinfoheader, 10);
316
317 switch (source->bits_per_pixel) {
318 case 8: /* colormapped image */
319 mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */
320 TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
321 break;
322 case 24: /* RGB image */
323 case 32: /* RGB image + Alpha channel */
324 TRACEMS3(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight,
325 source->bits_per_pixel);
326 break;
327 default:
328 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
329 }
330 break;
331 case 40:
332 case 64:
333 /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
334 /* or OS/2 2.x header, which has additional fields that we ignore */
335 biWidth = GET_4B(bmpinfoheader, 4);
336 biHeight = GET_4B(bmpinfoheader, 8);
337 biPlanes = GET_2B(bmpinfoheader, 12);
338 source->bits_per_pixel = (int) GET_2B(bmpinfoheader, 14);
339 biCompression = GET_4B(bmpinfoheader, 16);
340 biXPelsPerMeter = GET_4B(bmpinfoheader, 24);
341 biYPelsPerMeter = GET_4B(bmpinfoheader, 28);
342 biClrUsed = GET_4B(bmpinfoheader, 32);
343 /* biSizeImage, biClrImportant fields are ignored */
344
345 switch (source->bits_per_pixel) {
346 case 8: /* colormapped image */
347 mapentrysize = 4; /* Windows uses RGBQUAD colormap */
348 TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
349 break;
350 case 24: /* RGB image */
351 case 32: /* RGB image + Alpha channel */
352 TRACEMS3(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight,
353 source->bits_per_pixel);
354 break;
355 default:
356 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
357 }
358 if (biCompression != 0)
359 ERREXIT(cinfo, JERR_BMP_COMPRESSED);
360
361 if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
362 /* Set JFIF density parameters from the BMP data */
363 cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
364 cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
365 cinfo->density_unit = 2; /* dots/cm */
366 }
367 break;
368 default:
369 ERREXIT(cinfo, JERR_BMP_BADHEADER);
370 return; /* avoid compiler warnings for uninitialized variables */
371 }
372
373 if (biPlanes != 1)
374 ERREXIT(cinfo, JERR_BMP_BADPLANES);
375 /* Sanity check for buffer allocation below */
376 if (biWidth <= 0 || biHeight <= 0 || (biWidth >> 24) || (biHeight >> 24))
377 ERREXIT(cinfo, JERR_BMP_OUTOFRANGE);
378
379 /* Compute distance to bitmap data --- will adjust for colormap below */
380 bPad = bfOffBits - (headerSize + 14);
381
382 /* Read the colormap, if any */
383 if (mapentrysize > 0) {
384 if (biClrUsed <= 0)
385 biClrUsed = 256; /* assume it's 256 */
386 else if (biClrUsed > 256)
387 ERREXIT(cinfo, JERR_BMP_BADCMAP);
388 /* Allocate space to store the colormap */
389 source->colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo,
390 JPOOL_IMAGE, (JDIMENSION) biClrUsed, (JDIMENSION) 3);
391 source->cmap_length = (int) biClrUsed;
392 /* and read it from the file */
393 read_colormap(source, (int) biClrUsed, mapentrysize);
394 /* account for size of colormap */
395 bPad -= biClrUsed * mapentrysize;
396 }
397
398 /* Skip any remaining pad bytes */
399 if (bPad < 0) /* incorrect bfOffBits value? */
400 ERREXIT(cinfo, JERR_BMP_BADHEADER);
401 while (--bPad >= 0) {
403 }
404
405 /* Compute row width in file, including padding to 4-byte boundary */
406 if (source->bits_per_pixel == 24)
407 row_width = (JDIMENSION) (biWidth * 3);
408 else if (source->bits_per_pixel == 32)
409 row_width = (JDIMENSION) (biWidth * 4);
410 else
411 row_width = (JDIMENSION) biWidth;
412 while ((row_width & 3) != 0) row_width++;
413 source->row_width = row_width;
414
415 /* Allocate space for inversion array, prepare for preload pass */
416 source->whole_image = (*cinfo->mem->request_virt_sarray)
417 ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
418 row_width, (JDIMENSION) biHeight, (JDIMENSION) 1);
419 source->pub.get_pixel_rows = preload_image;
420 if (cinfo->progress != NULL) {
421 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
422 progress->total_extra_passes++; /* count file input as separate pass */
423 }
424
425 /* Allocate one-row buffer for returned data */
426 source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo,
427 JPOOL_IMAGE, (JDIMENSION) (biWidth * 3), (JDIMENSION) 1);
428 source->pub.buffer_height = 1;
429
430 cinfo->in_color_space = JCS_RGB;
431 cinfo->input_components = 3;
432 cinfo->data_precision = 8;
433 cinfo->image_width = (JDIMENSION) biWidth;
434 cinfo->image_height = (JDIMENSION) biHeight;
435}
436
437
438/*
439 * Finish up at the end of the file.
440 */
441
442METHODDEF(void)
443finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
444{
445 /* no work */
446}
447
448
449/*
450 * The module selection routine for BMP format input.
451 */
452
454jinit_read_bmp (j_compress_ptr cinfo)
455{
456 bmp_source_ptr source;
457
458 /* Create module interface object */
459 source = (bmp_source_ptr) (*cinfo->mem->alloc_small)
460 ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(bmp_source_struct));
461 source->cinfo = cinfo; /* make back link for subroutines */
462 /* Fill in method ptrs, except get_pixel_rows which start_input sets */
463 source->pub.start_input = start_input_bmp;
464 source->pub.finish_input = finish_input_bmp;
465
466 return &source->pub;
467}
468
469#endif /* BMP_SUPPORTED */
unsigned short UINT16
signed int INT32
#define SIZEOF(_ar)
Definition: calc.h:97
cd_progress_ptr progress
Definition: cdjpeg.h:152
struct cdjpeg_progress_mgr * cd_progress_ptr
Definition: cdjpeg.h:90
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static int read_byte(struct input_stream *in, unsigned char *byte)
Definition: gifformat.c:1933
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
GLdouble GLdouble t
Definition: gl.h:2047
const GLubyte * c
Definition: glext.h:8905
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_ _CRTIMP int __cdecl getc(_Inout_ FILE *_File)
#define EOF
Definition: stdio.h:24
#define TRACEMS2(cinfo, lvl, code, p1, p2)
Definition: jerror.h:272
#define TRACEMS3(cinfo, lvl, code, p1, p2, p3)
Definition: jerror.h:277
unsigned int JDIMENSION
Definition: jmorecfg.h:229
char JSAMPLE
Definition: jmorecfg.h:74
#define LOCAL(type)
Definition: jmorecfg.h:289
#define METHODDEF(type)
Definition: jmorecfg.h:287
#define GLOBAL(type)
Definition: jmorecfg.h:291
#define GETJSAMPLE(value)
Definition: jmorecfg.h:78
int source_row
Definition: jpegint.h:419
struct jpeg_common_struct * j_common_ptr
Definition: jpeglib.h:284
@ JCS_RGB
Definition: jpeglib.h:223
JSAMPROW * JSAMPARRAY
Definition: jpeglib.h:76
JSAMPLE FAR * JSAMPROW
Definition: jpeglib.h:75
#define JPOOL_IMAGE
Definition: jpeglib.h:808
#define c
Definition: ke_i.h:80
#define for
Definition: utility.h:88
#define long
Definition: qsort.c:33
#define ERREXIT(msg)
Definition: rdjpgcom.c:72
static FILE * infile
Definition: rdjpgcom.c:65
int total_extra_passes
Definition: cdjpeg.h:85
struct jpeg_progress_mgr pub
Definition: cdjpeg.h:83
int completed_extra_passes
Definition: cdjpeg.h:84
JDIMENSION image_height
Definition: jpeglib.h:303
J_COLOR_SPACE in_color_space
Definition: jpeglib.h:305
JDIMENSION image_width
Definition: jpeglib.h:302
Definition: general.c:220
#define ReadOK(tif, buf, size)
Definition: tiffiop.h:252