ReactOS 0.4.15-dev-7834-g00c4b3d
wrbmp.c
Go to the documentation of this file.
1/*
2 * wrbmp.c
3 *
4 * Copyright (C) 1994-1996, Thomas G. Lane.
5 * Modified 2017-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 write output images in Microsoft "BMP"
10 * format (MS Windows 3.x and OS/2 1.x flavors).
11 * Either 8-bit colormapped or 24-bit full-color format can be written.
12 * No compression is supported.
13 *
14 * These routines may need modification for non-Unix environments or
15 * specialized applications. As they stand, they assume output to
16 * an ordinary stdio stream.
17 *
18 * This code contributed by James Arthur Boucher.
19 */
20
21#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
22
23#ifdef BMP_SUPPORTED
24
25
26/*
27 * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
28 * This is not yet implemented.
29 */
30
31#if BITS_IN_JSAMPLE != 8
32 Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
33#endif
34
35/*
36 * Since BMP stores scanlines bottom-to-top, we have to invert the image
37 * from JPEG's top-to-bottom order. To do this, we save the outgoing data
38 * in a virtual array during put_pixel_row calls, then actually emit the
39 * BMP file during finish_output. The virtual array contains one JSAMPLE per
40 * pixel if the output is grayscale or colormapped, three if it is full color.
41 */
42
43/* Private version of data destination object */
44
45typedef struct {
46 struct djpeg_dest_struct pub; /* public fields */
47
48 boolean is_os2; /* saves the OS2 format request flag */
49
50 jvirt_sarray_ptr whole_image; /* needed to reverse row order */
51 JDIMENSION data_width; /* JSAMPLEs per row */
52 JDIMENSION row_width; /* physical width of one row in the BMP file */
53 int pad_bytes; /* number of padding bytes needed per row */
54 JDIMENSION cur_output_row; /* next row# to write to virtual array */
55} bmp_dest_struct;
56
57typedef bmp_dest_struct * bmp_dest_ptr;
58
59
60/* Forward declarations */
61LOCAL(void) write_colormap
62 JPP((j_decompress_ptr cinfo, bmp_dest_ptr dest,
63 int map_colors, int map_entry_size));
64
65
66/*
67 * Write some pixel data.
68 * In this module rows_supplied will always be 1.
69 */
70
71METHODDEF(void)
72put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
73 JDIMENSION rows_supplied)
74/* This version is for writing 24-bit pixels */
75{
76 bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
77 register JSAMPROW inptr, outptr;
78 register JDIMENSION col;
79 int pad;
80
81 /* Access next row in virtual array */
82 outptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo,
83 dest->whole_image, dest->cur_output_row, (JDIMENSION) 1, TRUE);
84 dest->cur_output_row++;
85
86 /* Transfer data. Note destination values must be in BGR order
87 * (even though Microsoft's own documents say the opposite).
88 */
89 inptr = dest->pub.buffer[0];
90 for (col = cinfo->output_width; col > 0; col--) {
91 outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
92 outptr[1] = *inptr++;
93 outptr[0] = *inptr++;
94 outptr += 3;
95 }
96
97 /* Zero out the pad bytes. */
98 pad = dest->pad_bytes;
99 while (--pad >= 0)
100 *outptr++ = 0;
101}
102
103METHODDEF(void)
104put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
105 JDIMENSION rows_supplied)
106/* This version is for grayscale OR quantized color output */
107{
108 bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
109 register JSAMPROW inptr, outptr;
110 register JDIMENSION col;
111 int pad;
112
113 /* Access next row in virtual array */
114 outptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo,
115 dest->whole_image, dest->cur_output_row, (JDIMENSION) 1, TRUE);
116 dest->cur_output_row++;
117
118 /* Transfer data. */
119 inptr = dest->pub.buffer[0];
120 for (col = cinfo->output_width; col > 0; col--) {
121 *outptr++ = *inptr++; /* can omit GETJSAMPLE() safely */
122 }
123
124 /* Zero out the pad bytes. */
125 pad = dest->pad_bytes;
126 while (--pad >= 0)
127 *outptr++ = 0;
128}
129
130
131/*
132 * Startup: normally writes the file header.
133 * In this module we may as well postpone everything until finish_output.
134 */
135
136METHODDEF(void)
137start_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
138{
139 /* no work here */
140}
141
142
143/*
144 * Finish up at the end of the file.
145 *
146 * Here is where we really output the BMP file.
147 *
148 * First, routines to write the Windows and OS/2 variants of the file header.
149 */
150
151LOCAL(void)
152write_bmp_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
153/* Write a Windows-style BMP file header, including colormap if needed */
154{
155 char bmpfileheader[14];
156 char bmpinfoheader[40];
157#define PUT_2B(array, offset, value) \
158 (array[offset] = (char) ((value) & 0xFF), \
159 array[offset+1] = (char) (((value) >> 8) & 0xFF))
160#define PUT_4B(array, offset, value) \
161 (array[offset] = (char) ((value) & 0xFF), \
162 array[offset+1] = (char) (((value) >> 8) & 0xFF), \
163 array[offset+2] = (char) (((value) >> 16) & 0xFF), \
164 array[offset+3] = (char) (((value) >> 24) & 0xFF))
165 INT32 headersize, bfSize;
166 int bits_per_pixel, cmap_entries;
167
168 /* Compute colormap size and total file size */
169 if (cinfo->out_color_space == JCS_RGB) {
170 if (cinfo->quantize_colors) {
171 /* Colormapped RGB */
172 bits_per_pixel = 8;
173 cmap_entries = 256;
174 } else {
175 /* Unquantized, full color RGB */
176 bits_per_pixel = 24;
177 cmap_entries = 0;
178 }
179 } else {
180 /* Grayscale output. We need to fake a 256-entry colormap. */
181 bits_per_pixel = 8;
182 cmap_entries = 256;
183 }
184 /* File size */
185 headersize = 14 + 40 + cmap_entries * 4; /* Header and colormap */
186 bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
187
188 /* Set unused fields of header to 0 */
189 MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
190 MEMZERO(bmpinfoheader, SIZEOF(bmpinfoheader));
191
192 /* Fill the file header */
193 bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */
194 bmpfileheader[1] = 0x4D;
195 PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */
196 /* we leave bfReserved1 & bfReserved2 = 0 */
197 PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */
198
199 /* Fill the info header (Microsoft calls this a BITMAPINFOHEADER) */
200 PUT_2B(bmpinfoheader, 0, 40); /* biSize */
201 PUT_4B(bmpinfoheader, 4, cinfo->output_width); /* biWidth */
202 PUT_4B(bmpinfoheader, 8, cinfo->output_height); /* biHeight */
203 PUT_2B(bmpinfoheader, 12, 1); /* biPlanes - must be 1 */
204 PUT_2B(bmpinfoheader, 14, bits_per_pixel); /* biBitCount */
205 /* we leave biCompression = 0, for none */
206 /* we leave biSizeImage = 0; this is correct for uncompressed data */
207 if (cinfo->density_unit == 2) { /* if have density in dots/cm, then */
208 PUT_4B(bmpinfoheader, 24, (INT32) (cinfo->X_density*100)); /* XPels/M */
209 PUT_4B(bmpinfoheader, 28, (INT32) (cinfo->Y_density*100)); /* XPels/M */
210 }
211 PUT_2B(bmpinfoheader, 32, cmap_entries); /* biClrUsed */
212 /* we leave biClrImportant = 0 */
213
214 if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
215 ERREXIT(cinfo, JERR_FILE_WRITE);
216 if (JFWRITE(dest->pub.output_file, bmpinfoheader, 40) != (size_t) 40)
217 ERREXIT(cinfo, JERR_FILE_WRITE);
218
219 if (cmap_entries > 0)
220 write_colormap(cinfo, dest, cmap_entries, 4);
221}
222
223
224LOCAL(void)
225write_os2_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
226/* Write an OS2-style BMP file header, including colormap if needed */
227{
228 char bmpfileheader[14];
229 char bmpcoreheader[12];
230 INT32 headersize, bfSize;
231 int bits_per_pixel, cmap_entries;
232
233 /* Compute colormap size and total file size */
234 if (cinfo->out_color_space == JCS_RGB) {
235 if (cinfo->quantize_colors) {
236 /* Colormapped RGB */
237 bits_per_pixel = 8;
238 cmap_entries = 256;
239 } else {
240 /* Unquantized, full color RGB */
241 bits_per_pixel = 24;
242 cmap_entries = 0;
243 }
244 } else {
245 /* Grayscale output. We need to fake a 256-entry colormap. */
246 bits_per_pixel = 8;
247 cmap_entries = 256;
248 }
249 /* File size */
250 headersize = 14 + 12 + cmap_entries * 3; /* Header and colormap */
251 bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
252
253 /* Set unused fields of header to 0 */
254 MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
255 MEMZERO(bmpcoreheader, SIZEOF(bmpcoreheader));
256
257 /* Fill the file header */
258 bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */
259 bmpfileheader[1] = 0x4D;
260 PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */
261 /* we leave bfReserved1 & bfReserved2 = 0 */
262 PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */
263
264 /* Fill the info header (Microsoft calls this a BITMAPCOREHEADER) */
265 PUT_2B(bmpcoreheader, 0, 12); /* bcSize */
266 PUT_2B(bmpcoreheader, 4, cinfo->output_width); /* bcWidth */
267 PUT_2B(bmpcoreheader, 6, cinfo->output_height); /* bcHeight */
268 PUT_2B(bmpcoreheader, 8, 1); /* bcPlanes - must be 1 */
269 PUT_2B(bmpcoreheader, 10, bits_per_pixel); /* bcBitCount */
270
271 if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
272 ERREXIT(cinfo, JERR_FILE_WRITE);
273 if (JFWRITE(dest->pub.output_file, bmpcoreheader, 12) != (size_t) 12)
274 ERREXIT(cinfo, JERR_FILE_WRITE);
275
276 if (cmap_entries > 0)
277 write_colormap(cinfo, dest, cmap_entries, 3);
278}
279
280
281/*
282 * Write the colormap.
283 * Windows uses BGR0 map entries; OS/2 uses BGR entries.
284 */
285
286LOCAL(void)
287write_colormap (j_decompress_ptr cinfo, bmp_dest_ptr dest,
288 int map_colors, int map_entry_size)
289{
290 JSAMPARRAY colormap = cinfo->colormap;
291 int num_colors = cinfo->actual_number_of_colors;
292 FILE * outfile = dest->pub.output_file;
293 int i;
294
295 if (colormap != NULL) {
296 if (cinfo->out_color_components == 3) {
297 /* Normal case with RGB colormap */
298 for (i = 0; i < num_colors; i++) {
299 putc(GETJSAMPLE(colormap[2][i]), outfile);
300 putc(GETJSAMPLE(colormap[1][i]), outfile);
301 putc(GETJSAMPLE(colormap[0][i]), outfile);
302 if (map_entry_size == 4)
303 putc(0, outfile);
304 }
305 } else {
306 /* Grayscale colormap (only happens with grayscale quantization) */
307 for (i = 0; i < num_colors; i++) {
308 putc(GETJSAMPLE(colormap[0][i]), outfile);
309 putc(GETJSAMPLE(colormap[0][i]), outfile);
310 putc(GETJSAMPLE(colormap[0][i]), outfile);
311 if (map_entry_size == 4)
312 putc(0, outfile);
313 }
314 }
315 } else {
316 /* If no colormap, must be grayscale data. Generate a linear "map". */
317 for (i = 0; i < 256; i++) {
318 putc(i, outfile);
319 putc(i, outfile);
320 putc(i, outfile);
321 if (map_entry_size == 4)
322 putc(0, outfile);
323 }
324 }
325 /* Pad colormap to ensure specified number of colormap entries */
326 if (i > map_colors)
327 ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, i);
328 for (; i < map_colors; i++) {
332 if (map_entry_size == 4)
333 putc(0, outfile);
334 }
335}
336
337
338METHODDEF(void)
339finish_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
340{
341 bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
342 register FILE * outfile = dest->pub.output_file;
343 register JSAMPROW data_ptr;
345 register JDIMENSION col;
346 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
347
348 /* Write the header and colormap */
349 if (dest->is_os2)
350 write_os2_header(cinfo, dest);
351 else
352 write_bmp_header(cinfo, dest);
353
354 /* Write the file body from our virtual array */
355 for (row = cinfo->output_height; row > 0; row--) {
356 if (progress != NULL) {
357 progress->pub.pass_counter = (long) (cinfo->output_height - row);
358 progress->pub.pass_limit = (long) cinfo->output_height;
359 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
360 }
361 data_ptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo,
362 dest->whole_image, row - 1, (JDIMENSION) 1, FALSE);
363 for (col = dest->row_width; col > 0; col--) {
364 putc(GETJSAMPLE(*data_ptr), outfile);
365 data_ptr++;
366 }
367 }
368 if (progress != NULL)
370
371 /* Make sure we wrote the output file OK */
373 if (JFERROR(outfile))
374 ERREXIT(cinfo, JERR_FILE_WRITE);
375}
376
377
378/*
379 * The module selection routine for BMP format output.
380 */
381
383jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2)
384{
385 bmp_dest_ptr dest;
386 JDIMENSION row_width;
387
388 /* Create module interface object, fill in method pointers */
389 dest = (bmp_dest_ptr) (*cinfo->mem->alloc_small)
390 ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(bmp_dest_struct));
391 dest->pub.start_output = start_output_bmp;
392 dest->pub.finish_output = finish_output_bmp;
393 dest->is_os2 = is_os2;
394
395 switch (cinfo->out_color_space) {
396 case JCS_GRAYSCALE:
397 dest->pub.put_pixel_rows = put_gray_rows;
398 break;
399 case JCS_RGB:
400 if (cinfo->quantize_colors)
401 dest->pub.put_pixel_rows = put_gray_rows;
402 else
403 dest->pub.put_pixel_rows = put_pixel_rows;
404 break;
405 default:
406 ERREXIT(cinfo, JERR_BMP_COLORSPACE);
407 }
408
409 /* Calculate output image dimensions so we can allocate space */
411
412 /* Determine width of rows in the BMP file (padded to 4-byte boundary). */
413 row_width = cinfo->output_width * cinfo->output_components;
414 dest->data_width = row_width;
415 while ((row_width & 3) != 0) row_width++;
416 dest->row_width = row_width;
417 dest->pad_bytes = (int) (row_width - dest->data_width);
418
419 /* Allocate space for inversion array, prepare for write pass */
420 dest->whole_image = (*cinfo->mem->request_virt_sarray)
421 ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
422 row_width, cinfo->output_height, (JDIMENSION) 1);
423 dest->cur_output_row = 0;
424 if (cinfo->progress != NULL) {
425 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
426 progress->total_extra_passes++; /* count file input as separate pass */
427 }
428
429 /* Create decompressor output buffer. */
430 dest->pub.buffer = (*cinfo->mem->alloc_sarray)
431 ((j_common_ptr) cinfo, JPOOL_IMAGE, row_width, (JDIMENSION) 1);
432 dest->pub.buffer_height = 1;
433
434 return &dest->pub;
435}
436
437#endif /* BMP_SUPPORTED */
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
boolean is_os2
Definition: cdjpeg.h:123
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
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
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_opt_ _CRTIMP int __cdecl putc(_In_ int _Ch, _Inout_ FILE *_File)
Sorry
Definition: jdcolor.c:19
jpeg_calc_output_dimensions(j_decompress_ptr cinfo)
Definition: jdmaster.c:101
#define ERREXIT1(cinfo, code, p1)
Definition: jerror.h:212
#define JFFLUSH(file)
Definition: jinclude.h:96
#define JFERROR(file)
Definition: jinclude.h:97
#define JFWRITE(file, buf, sizeofbuf)
Definition: jinclude.h:94
unsigned int JDIMENSION
Definition: jmorecfg.h:229
#define LOCAL(type)
Definition: jmorecfg.h:289
#define METHODDEF(type)
Definition: jmorecfg.h:287
#define CENTERJSAMPLE
Definition: jmorecfg.h:84
#define GLOBAL(type)
Definition: jmorecfg.h:291
#define GETJSAMPLE(value)
Definition: jmorecfg.h:78
struct jpeg_common_struct * j_common_ptr
Definition: jpeglib.h:284
#define JPP(arglist)
Definition: jpeglib.h:877
@ JCS_GRAYSCALE
Definition: jpeglib.h:222
@ 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
if(dx< 0)
Definition: linetemp.h:194
static char * dest
Definition: rtl.c:135
#define long
Definition: qsort.c:33
#define ERREXIT(msg)
Definition: rdjpgcom.c:72
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
Definition: inflate.c:139
JDIMENSION output_height
Definition: jpeglib.h:508
JSAMPARRAY colormap
Definition: jpeglib.h:527
boolean quantize_colors
Definition: jpeglib.h:491
J_COLOR_SPACE out_color_space
Definition: jpeglib.h:478
JDIMENSION output_width
Definition: jpeglib.h:507
#define MEMZERO(addr, type, size)
Definition: svc_dg.c:324
static FILE * outfile
Definition: wrjpgcom.c:81