w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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