ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

wrbmp.c
Go to the documentation of this file.
00001 /*
00002  * wrbmp.c
00003  *
00004  * Copyright (C) 1994-1996, Thomas G. Lane.
00005  * This file is part of the Independent JPEG Group's software.
00006  * For conditions of distribution and use, see the accompanying README file.
00007  *
00008  * This file contains routines to write output images in Microsoft "BMP"
00009  * format (MS Windows 3.x and OS/2 1.x flavors).
00010  * Either 8-bit colormapped or 24-bit full-color format can be written.
00011  * No compression is supported.
00012  *
00013  * These routines may need modification for non-Unix environments or
00014  * specialized applications.  As they stand, they assume output to
00015  * an ordinary stdio stream.
00016  *
00017  * This code contributed by James Arthur Boucher.
00018  */
00019 
00020 #include "cdjpeg.h"     /* Common decls for cjpeg/djpeg applications */
00021 
00022 #ifdef BMP_SUPPORTED
00023 
00024 
00025 /*
00026  * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
00027  * This is not yet implemented.
00028  */
00029 
00030 #if BITS_IN_JSAMPLE != 8
00031   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
00032 #endif
00033 
00034 /*
00035  * Since BMP stores scanlines bottom-to-top, we have to invert the image
00036  * from JPEG's top-to-bottom order.  To do this, we save the outgoing data
00037  * in a virtual array during put_pixel_row calls, then actually emit the
00038  * BMP file during finish_output.  The virtual array contains one JSAMPLE per
00039  * pixel if the output is grayscale or colormapped, three if it is full color.
00040  */
00041 
00042 /* Private version of data destination object */
00043 
00044 typedef struct {
00045   struct djpeg_dest_struct pub; /* public fields */
00046 
00047   boolean is_os2;       /* saves the OS2 format request flag */
00048 
00049   jvirt_sarray_ptr whole_image; /* needed to reverse row order */
00050   JDIMENSION data_width;    /* JSAMPLEs per row */
00051   JDIMENSION row_width;     /* physical width of one row in the BMP file */
00052   int pad_bytes;        /* number of padding bytes needed per row */
00053   JDIMENSION cur_output_row;    /* next row# to write to virtual array */
00054 } bmp_dest_struct;
00055 
00056 typedef bmp_dest_struct * bmp_dest_ptr;
00057 
00058 
00059 /* Forward declarations */
00060 LOCAL(void) write_colormap
00061     JPP((j_decompress_ptr cinfo, bmp_dest_ptr dest,
00062          int map_colors, int map_entry_size));
00063 
00064 
00065 /*
00066  * Write some pixel data.
00067  * In this module rows_supplied will always be 1.
00068  */
00069 
00070 METHODDEF(void)
00071 put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
00072         JDIMENSION rows_supplied)
00073 /* This version is for writing 24-bit pixels */
00074 {
00075   bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
00076   JSAMPARRAY image_ptr;
00077   register JSAMPROW inptr, outptr;
00078   register JDIMENSION col;
00079   int pad;
00080 
00081   /* Access next row in virtual array */
00082   image_ptr = (*cinfo->mem->access_virt_sarray)
00083     ((j_common_ptr) cinfo, dest->whole_image,
00084      dest->cur_output_row, (JDIMENSION) 1, TRUE);
00085   dest->cur_output_row++;
00086 
00087   /* Transfer data.  Note destination values must be in BGR order
00088    * (even though Microsoft's own documents say the opposite).
00089    */
00090   inptr = dest->pub.buffer[0];
00091   outptr = image_ptr[0];
00092   for (col = cinfo->output_width; col > 0; col--) {
00093     outptr[2] = *inptr++;   /* can omit GETJSAMPLE() safely */
00094     outptr[1] = *inptr++;
00095     outptr[0] = *inptr++;
00096     outptr += 3;
00097   }
00098 
00099   /* Zero out the pad bytes. */
00100   pad = dest->pad_bytes;
00101   while (--pad >= 0)
00102     *outptr++ = 0;
00103 }
00104 
00105 METHODDEF(void)
00106 put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
00107            JDIMENSION rows_supplied)
00108 /* This version is for grayscale OR quantized color output */
00109 {
00110   bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
00111   JSAMPARRAY image_ptr;
00112   register JSAMPROW inptr, outptr;
00113   register JDIMENSION col;
00114   int pad;
00115 
00116   /* Access next row in virtual array */
00117   image_ptr = (*cinfo->mem->access_virt_sarray)
00118     ((j_common_ptr) cinfo, dest->whole_image,
00119      dest->cur_output_row, (JDIMENSION) 1, TRUE);
00120   dest->cur_output_row++;
00121 
00122   /* Transfer data. */
00123   inptr = dest->pub.buffer[0];
00124   outptr = image_ptr[0];
00125   for (col = cinfo->output_width; col > 0; col--) {
00126     *outptr++ = *inptr++;   /* can omit GETJSAMPLE() safely */
00127   }
00128 
00129   /* Zero out the pad bytes. */
00130   pad = dest->pad_bytes;
00131   while (--pad >= 0)
00132     *outptr++ = 0;
00133 }
00134 
00135 
00136 /*
00137  * Startup: normally writes the file header.
00138  * In this module we may as well postpone everything until finish_output.
00139  */
00140 
00141 METHODDEF(void)
00142 start_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
00143 {
00144   /* no work here */
00145 }
00146 
00147 
00148 /*
00149  * Finish up at the end of the file.
00150  *
00151  * Here is where we really output the BMP file.
00152  *
00153  * First, routines to write the Windows and OS/2 variants of the file header.
00154  */
00155 
00156 LOCAL(void)
00157 write_bmp_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
00158 /* Write a Windows-style BMP file header, including colormap if needed */
00159 {
00160   char bmpfileheader[14];
00161   char bmpinfoheader[40];
00162 #define PUT_2B(array,offset,value)  \
00163     (array[offset] = (char) ((value) & 0xFF), \
00164      array[offset+1] = (char) (((value) >> 8) & 0xFF))
00165 #define PUT_4B(array,offset,value)  \
00166     (array[offset] = (char) ((value) & 0xFF), \
00167      array[offset+1] = (char) (((value) >> 8) & 0xFF), \
00168      array[offset+2] = (char) (((value) >> 16) & 0xFF), \
00169      array[offset+3] = (char) (((value) >> 24) & 0xFF))
00170   INT32 headersize, bfSize;
00171   int bits_per_pixel, cmap_entries;
00172 
00173   /* Compute colormap size and total file size */
00174   if (cinfo->out_color_space == JCS_RGB) {
00175     if (cinfo->quantize_colors) {
00176       /* Colormapped RGB */
00177       bits_per_pixel = 8;
00178       cmap_entries = 256;
00179     } else {
00180       /* Unquantized, full color RGB */
00181       bits_per_pixel = 24;
00182       cmap_entries = 0;
00183     }
00184   } else {
00185     /* Grayscale output.  We need to fake a 256-entry colormap. */
00186     bits_per_pixel = 8;
00187     cmap_entries = 256;
00188   }
00189   /* File size */
00190   headersize = 14 + 40 + cmap_entries * 4; /* Header and colormap */
00191   bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
00192   
00193   /* Set unused fields of header to 0 */
00194   MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
00195   MEMZERO(bmpinfoheader, SIZEOF(bmpinfoheader));
00196 
00197   /* Fill the file header */
00198   bmpfileheader[0] = 0x42;  /* first 2 bytes are ASCII 'B', 'M' */
00199   bmpfileheader[1] = 0x4D;
00200   PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */
00201   /* we leave bfReserved1 & bfReserved2 = 0 */
00202   PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */
00203 
00204   /* Fill the info header (Microsoft calls this a BITMAPINFOHEADER) */
00205   PUT_2B(bmpinfoheader, 0, 40); /* biSize */
00206   PUT_4B(bmpinfoheader, 4, cinfo->output_width); /* biWidth */
00207   PUT_4B(bmpinfoheader, 8, cinfo->output_height); /* biHeight */
00208   PUT_2B(bmpinfoheader, 12, 1); /* biPlanes - must be 1 */
00209   PUT_2B(bmpinfoheader, 14, bits_per_pixel); /* biBitCount */
00210   /* we leave biCompression = 0, for none */
00211   /* we leave biSizeImage = 0; this is correct for uncompressed data */
00212   if (cinfo->density_unit == 2) { /* if have density in dots/cm, then */
00213     PUT_4B(bmpinfoheader, 24, (INT32) (cinfo->X_density*100)); /* XPels/M */
00214     PUT_4B(bmpinfoheader, 28, (INT32) (cinfo->Y_density*100)); /* XPels/M */
00215   }
00216   PUT_2B(bmpinfoheader, 32, cmap_entries); /* biClrUsed */
00217   /* we leave biClrImportant = 0 */
00218 
00219   if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
00220     ERREXIT(cinfo, JERR_FILE_WRITE);
00221   if (JFWRITE(dest->pub.output_file, bmpinfoheader, 40) != (size_t) 40)
00222     ERREXIT(cinfo, JERR_FILE_WRITE);
00223 
00224   if (cmap_entries > 0)
00225     write_colormap(cinfo, dest, cmap_entries, 4);
00226 }
00227 
00228 
00229 LOCAL(void)
00230 write_os2_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
00231 /* Write an OS2-style BMP file header, including colormap if needed */
00232 {
00233   char bmpfileheader[14];
00234   char bmpcoreheader[12];
00235   INT32 headersize, bfSize;
00236   int bits_per_pixel, cmap_entries;
00237 
00238   /* Compute colormap size and total file size */
00239   if (cinfo->out_color_space == JCS_RGB) {
00240     if (cinfo->quantize_colors) {
00241       /* Colormapped RGB */
00242       bits_per_pixel = 8;
00243       cmap_entries = 256;
00244     } else {
00245       /* Unquantized, full color RGB */
00246       bits_per_pixel = 24;
00247       cmap_entries = 0;
00248     }
00249   } else {
00250     /* Grayscale output.  We need to fake a 256-entry colormap. */
00251     bits_per_pixel = 8;
00252     cmap_entries = 256;
00253   }
00254   /* File size */
00255   headersize = 14 + 12 + cmap_entries * 3; /* Header and colormap */
00256   bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
00257   
00258   /* Set unused fields of header to 0 */
00259   MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
00260   MEMZERO(bmpcoreheader, SIZEOF(bmpcoreheader));
00261 
00262   /* Fill the file header */
00263   bmpfileheader[0] = 0x42;  /* first 2 bytes are ASCII 'B', 'M' */
00264   bmpfileheader[1] = 0x4D;
00265   PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */
00266   /* we leave bfReserved1 & bfReserved2 = 0 */
00267   PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */
00268 
00269   /* Fill the info header (Microsoft calls this a BITMAPCOREHEADER) */
00270   PUT_2B(bmpcoreheader, 0, 12); /* bcSize */
00271   PUT_2B(bmpcoreheader, 4, cinfo->output_width); /* bcWidth */
00272   PUT_2B(bmpcoreheader, 6, cinfo->output_height); /* bcHeight */
00273   PUT_2B(bmpcoreheader, 8, 1);  /* bcPlanes - must be 1 */
00274   PUT_2B(bmpcoreheader, 10, bits_per_pixel); /* bcBitCount */
00275 
00276   if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
00277     ERREXIT(cinfo, JERR_FILE_WRITE);
00278   if (JFWRITE(dest->pub.output_file, bmpcoreheader, 12) != (size_t) 12)
00279     ERREXIT(cinfo, JERR_FILE_WRITE);
00280 
00281   if (cmap_entries > 0)
00282     write_colormap(cinfo, dest, cmap_entries, 3);
00283 }
00284 
00285 
00286 /*
00287  * Write the colormap.
00288  * Windows uses BGR0 map entries; OS/2 uses BGR entries.
00289  */
00290 
00291 LOCAL(void)
00292 write_colormap (j_decompress_ptr cinfo, bmp_dest_ptr dest,
00293         int map_colors, int map_entry_size)
00294 {
00295   JSAMPARRAY colormap = cinfo->colormap;
00296   int num_colors = cinfo->actual_number_of_colors;
00297   FILE * outfile = dest->pub.output_file;
00298   int i;
00299 
00300   if (colormap != NULL) {
00301     if (cinfo->out_color_components == 3) {
00302       /* Normal case with RGB colormap */
00303       for (i = 0; i < num_colors; i++) {
00304     putc(GETJSAMPLE(colormap[2][i]), outfile);
00305     putc(GETJSAMPLE(colormap[1][i]), outfile);
00306     putc(GETJSAMPLE(colormap[0][i]), outfile);
00307     if (map_entry_size == 4)
00308       putc(0, outfile);
00309       }
00310     } else {
00311       /* Grayscale colormap (only happens with grayscale quantization) */
00312       for (i = 0; i < num_colors; i++) {
00313     putc(GETJSAMPLE(colormap[0][i]), outfile);
00314     putc(GETJSAMPLE(colormap[0][i]), outfile);
00315     putc(GETJSAMPLE(colormap[0][i]), outfile);
00316     if (map_entry_size == 4)
00317       putc(0, outfile);
00318       }
00319     }
00320   } else {
00321     /* If no colormap, must be grayscale data.  Generate a linear "map". */
00322     for (i = 0; i < 256; i++) {
00323       putc(i, outfile);
00324       putc(i, outfile);
00325       putc(i, outfile);
00326       if (map_entry_size == 4)
00327     putc(0, outfile);
00328     }
00329   }
00330   /* Pad colormap with zeros to ensure specified number of colormap entries */ 
00331   if (i > map_colors)
00332     ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, i);
00333   for (; i < map_colors; i++) {
00334     putc(0, outfile);
00335     putc(0, outfile);
00336     putc(0, outfile);
00337     if (map_entry_size == 4)
00338       putc(0, outfile);
00339   }
00340 }
00341 
00342 
00343 METHODDEF(void)
00344 finish_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
00345 {
00346   bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
00347   register FILE * outfile = dest->pub.output_file;
00348   JSAMPARRAY image_ptr;
00349   register JSAMPROW data_ptr;
00350   JDIMENSION row;
00351   register JDIMENSION col;
00352   cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
00353 
00354   /* Write the header and colormap */
00355   if (dest->is_os2)
00356     write_os2_header(cinfo, dest);
00357   else
00358     write_bmp_header(cinfo, dest);
00359 
00360   /* Write the file body from our virtual array */
00361   for (row = cinfo->output_height; row > 0; row--) {
00362     if (progress != NULL) {
00363       progress->pub.pass_counter = (long) (cinfo->output_height - row);
00364       progress->pub.pass_limit = (long) cinfo->output_height;
00365       (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
00366     }
00367     image_ptr = (*cinfo->mem->access_virt_sarray)
00368       ((j_common_ptr) cinfo, dest->whole_image, row-1, (JDIMENSION) 1, FALSE);
00369     data_ptr = image_ptr[0];
00370     for (col = dest->row_width; col > 0; col--) {
00371       putc(GETJSAMPLE(*data_ptr), outfile);
00372       data_ptr++;
00373     }
00374   }
00375   if (progress != NULL)
00376     progress->completed_extra_passes++;
00377 
00378   /* Make sure we wrote the output file OK */
00379   fflush(outfile);
00380   if (ferror(outfile))
00381     ERREXIT(cinfo, JERR_FILE_WRITE);
00382 }
00383 
00384 
00385 /*
00386  * The module selection routine for BMP format output.
00387  */
00388 
00389 GLOBAL(djpeg_dest_ptr)
00390 jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2)
00391 {
00392   bmp_dest_ptr dest;
00393   JDIMENSION row_width;
00394 
00395   /* Create module interface object, fill in method pointers */
00396   dest = (bmp_dest_ptr)
00397       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00398                   SIZEOF(bmp_dest_struct));
00399   dest->pub.start_output = start_output_bmp;
00400   dest->pub.finish_output = finish_output_bmp;
00401   dest->is_os2 = is_os2;
00402 
00403   if (cinfo->out_color_space == JCS_GRAYSCALE) {
00404     dest->pub.put_pixel_rows = put_gray_rows;
00405   } else if (cinfo->out_color_space == JCS_RGB) {
00406     if (cinfo->quantize_colors)
00407       dest->pub.put_pixel_rows = put_gray_rows;
00408     else
00409       dest->pub.put_pixel_rows = put_pixel_rows;
00410   } else {
00411     ERREXIT(cinfo, JERR_BMP_COLORSPACE);
00412   }
00413 
00414   /* Calculate output image dimensions so we can allocate space */
00415   jpeg_calc_output_dimensions(cinfo);
00416 
00417   /* Determine width of rows in the BMP file (padded to 4-byte boundary). */
00418   row_width = cinfo->output_width * cinfo->output_components;
00419   dest->data_width = row_width;
00420   while ((row_width & 3) != 0) row_width++;
00421   dest->row_width = row_width;
00422   dest->pad_bytes = (int) (row_width - dest->data_width);
00423 
00424   /* Allocate space for inversion array, prepare for write pass */
00425   dest->whole_image = (*cinfo->mem->request_virt_sarray)
00426     ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
00427      row_width, cinfo->output_height, (JDIMENSION) 1);
00428   dest->cur_output_row = 0;
00429   if (cinfo->progress != NULL) {
00430     cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
00431     progress->total_extra_passes++; /* count file input as separate pass */
00432   }
00433 
00434   /* Create decompressor output buffer. */
00435   dest->pub.buffer = (*cinfo->mem->alloc_sarray)
00436     ((j_common_ptr) cinfo, JPOOL_IMAGE, row_width, (JDIMENSION) 1);
00437   dest->pub.buffer_height = 1;
00438 
00439   return (djpeg_dest_ptr) dest;
00440 }
00441 
00442 #endif /* BMP_SUPPORTED */

Generated on Sat May 26 2012 04:18:15 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.