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

rdbmp.c
Go to the documentation of this file.
00001 /*
00002  * rdbmp.c
00003  *
00004  * Copyright (C) 1994-1996, Thomas G. Lane.
00005  * Modified 2009-2010 by Guido Vollbeding.
00006  * This file is part of the Independent JPEG Group's software.
00007  * For conditions of distribution and use, see the accompanying README file.
00008  *
00009  * This file contains routines to read input images in Microsoft "BMP"
00010  * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors).
00011  * Currently, only 8-bit and 24-bit images are supported, not 1-bit or
00012  * 4-bit (feeding such low-depth images into JPEG would be silly anyway).
00013  * Also, we don't support RLE-compressed files.
00014  *
00015  * These routines may need modification for non-Unix environments or
00016  * specialized applications.  As they stand, they assume input from
00017  * an ordinary stdio stream.  They further assume that reading begins
00018  * at the start of the file; start_input may need work if the
00019  * user interface has already read some data (e.g., to determine that
00020  * the file is indeed BMP format).
00021  *
00022  * This code contributed by James Arthur Boucher.
00023  */
00024 
00025 #include "cdjpeg.h"     /* Common decls for cjpeg/djpeg applications */
00026 
00027 #ifdef BMP_SUPPORTED
00028 
00029 
00030 /* Macros to deal with unsigned chars as efficiently as compiler allows */
00031 
00032 #ifdef HAVE_UNSIGNED_CHAR
00033 typedef unsigned char U_CHAR;
00034 #define UCH(x)  ((int) (x))
00035 #else /* !HAVE_UNSIGNED_CHAR */
00036 #ifdef CHAR_IS_UNSIGNED
00037 typedef char U_CHAR;
00038 #define UCH(x)  ((int) (x))
00039 #else
00040 typedef char U_CHAR;
00041 #define UCH(x)  ((int) (x) & 0xFF)
00042 #endif
00043 #endif /* HAVE_UNSIGNED_CHAR */
00044 
00045 
00046 #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
00047 
00048 
00049 /* Private version of data source object */
00050 
00051 typedef struct _bmp_source_struct * bmp_source_ptr;
00052 
00053 typedef struct _bmp_source_struct {
00054   struct cjpeg_source_struct pub; /* public fields */
00055 
00056   j_compress_ptr cinfo;     /* back link saves passing separate parm */
00057 
00058   JSAMPARRAY colormap;      /* BMP colormap (converted to my format) */
00059 
00060   jvirt_sarray_ptr whole_image; /* Needed to reverse row order */
00061   JDIMENSION source_row;    /* Current source row number */
00062   JDIMENSION row_width;     /* Physical width of scanlines in file */
00063 
00064   int bits_per_pixel;       /* remembers 8- or 24-bit format */
00065 } bmp_source_struct;
00066 
00067 
00068 LOCAL(int)
00069 read_byte (bmp_source_ptr sinfo)
00070 /* Read next byte from BMP file */
00071 {
00072   register FILE *infile = sinfo->pub.input_file;
00073   register int c;
00074 
00075   if ((c = getc(infile)) == EOF)
00076     ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
00077   return c;
00078 }
00079 
00080 
00081 LOCAL(void)
00082 read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize)
00083 /* Read the colormap from a BMP file */
00084 {
00085   int i;
00086 
00087   switch (mapentrysize) {
00088   case 3:
00089     /* BGR format (occurs in OS/2 files) */
00090     for (i = 0; i < cmaplen; i++) {
00091       sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
00092       sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
00093       sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
00094     }
00095     break;
00096   case 4:
00097     /* BGR0 format (occurs in MS Windows files) */
00098     for (i = 0; i < cmaplen; i++) {
00099       sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
00100       sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
00101       sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
00102       (void) read_byte(sinfo);
00103     }
00104     break;
00105   default:
00106     ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
00107     break;
00108   }
00109 }
00110 
00111 
00112 /*
00113  * Read one row of pixels.
00114  * The image has been read into the whole_image array, but is otherwise
00115  * unprocessed.  We must read it out in top-to-bottom row order, and if
00116  * it is an 8-bit image, we must expand colormapped pixels to 24bit format.
00117  */
00118 
00119 METHODDEF(JDIMENSION)
00120 get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00121 /* This version is for reading 8-bit colormap indexes */
00122 {
00123   bmp_source_ptr source = (bmp_source_ptr) sinfo;
00124   register JSAMPARRAY colormap = source->colormap;
00125   JSAMPARRAY image_ptr;
00126   register int t;
00127   register JSAMPROW inptr, outptr;
00128   register JDIMENSION col;
00129 
00130   /* Fetch next row from virtual array */
00131   source->source_row--;
00132   image_ptr = (*cinfo->mem->access_virt_sarray)
00133     ((j_common_ptr) cinfo, source->whole_image,
00134      source->source_row, (JDIMENSION) 1, FALSE);
00135 
00136   /* Expand the colormap indexes to real data */
00137   inptr = image_ptr[0];
00138   outptr = source->pub.buffer[0];
00139   for (col = cinfo->image_width; col > 0; col--) {
00140     t = GETJSAMPLE(*inptr++);
00141     *outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */
00142     *outptr++ = colormap[1][t];
00143     *outptr++ = colormap[2][t];
00144   }
00145 
00146   return 1;
00147 }
00148 
00149 
00150 METHODDEF(JDIMENSION)
00151 get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00152 /* This version is for reading 24-bit pixels */
00153 {
00154   bmp_source_ptr source = (bmp_source_ptr) sinfo;
00155   JSAMPARRAY image_ptr;
00156   register JSAMPROW inptr, outptr;
00157   register JDIMENSION col;
00158 
00159   /* Fetch next row from virtual array */
00160   source->source_row--;
00161   image_ptr = (*cinfo->mem->access_virt_sarray)
00162     ((j_common_ptr) cinfo, source->whole_image,
00163      source->source_row, (JDIMENSION) 1, FALSE);
00164 
00165   /* Transfer data.  Note source values are in BGR order
00166    * (even though Microsoft's own documents say the opposite).
00167    */
00168   inptr = image_ptr[0];
00169   outptr = source->pub.buffer[0];
00170   for (col = cinfo->image_width; col > 0; col--) {
00171     outptr[2] = *inptr++;   /* can omit GETJSAMPLE() safely */
00172     outptr[1] = *inptr++;
00173     outptr[0] = *inptr++;
00174     outptr += 3;
00175   }
00176 
00177   return 1;
00178 }
00179 
00180 
00181 METHODDEF(JDIMENSION)
00182 get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00183 /* This version is for reading 32-bit pixels */
00184 {
00185   bmp_source_ptr source = (bmp_source_ptr) sinfo;
00186   JSAMPARRAY image_ptr;
00187   register JSAMPROW inptr, outptr;
00188   register JDIMENSION col;
00189 
00190   /* Fetch next row from virtual array */
00191   source->source_row--;
00192   image_ptr = (*cinfo->mem->access_virt_sarray)
00193     ((j_common_ptr) cinfo, source->whole_image,
00194      source->source_row, (JDIMENSION) 1, FALSE);
00195   /* Transfer data.  Note source values are in BGR order
00196    * (even though Microsoft's own documents say the opposite).
00197    */
00198   inptr = image_ptr[0];
00199   outptr = source->pub.buffer[0];
00200   for (col = cinfo->image_width; col > 0; col--) {
00201     outptr[2] = *inptr++;   /* can omit GETJSAMPLE() safely */
00202     outptr[1] = *inptr++;
00203     outptr[0] = *inptr++;
00204     inptr++;            /* skip the 4th byte (Alpha channel) */
00205     outptr += 3;
00206   }
00207 
00208   return 1;
00209 }
00210 
00211 
00212 /*
00213  * This method loads the image into whole_image during the first call on
00214  * get_pixel_rows.  The get_pixel_rows pointer is then adjusted to call
00215  * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls.
00216  */
00217 
00218 METHODDEF(JDIMENSION)
00219 preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00220 {
00221   bmp_source_ptr source = (bmp_source_ptr) sinfo;
00222   register FILE *infile = source->pub.input_file;
00223   register int c;
00224   register JSAMPROW out_ptr;
00225   JSAMPARRAY image_ptr;
00226   JDIMENSION row, col;
00227   cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
00228 
00229   /* Read the data into a virtual array in input-file row order. */
00230   for (row = 0; row < cinfo->image_height; row++) {
00231     if (progress != NULL) {
00232       progress->pub.pass_counter = (long) row;
00233       progress->pub.pass_limit = (long) cinfo->image_height;
00234       (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
00235     }
00236     image_ptr = (*cinfo->mem->access_virt_sarray)
00237       ((j_common_ptr) cinfo, source->whole_image,
00238        row, (JDIMENSION) 1, TRUE);
00239     out_ptr = image_ptr[0];
00240     for (col = source->row_width; col > 0; col--) {
00241       /* inline copy of read_byte() for speed */
00242       if ((c = getc(infile)) == EOF)
00243     ERREXIT(cinfo, JERR_INPUT_EOF);
00244       *out_ptr++ = (JSAMPLE) c;
00245     }
00246   }
00247   if (progress != NULL)
00248     progress->completed_extra_passes++;
00249 
00250   /* Set up to read from the virtual array in top-to-bottom order */
00251   switch (source->bits_per_pixel) {
00252   case 8:
00253     source->pub.get_pixel_rows = get_8bit_row;
00254     break;
00255   case 24:
00256     source->pub.get_pixel_rows = get_24bit_row;
00257     break;
00258   case 32:
00259     source->pub.get_pixel_rows = get_32bit_row;
00260     break;
00261   default:
00262     ERREXIT(cinfo, JERR_BMP_BADDEPTH);
00263   }
00264   source->source_row = cinfo->image_height;
00265 
00266   /* And read the first row */
00267   return (*source->pub.get_pixel_rows) (cinfo, sinfo);
00268 }
00269 
00270 
00271 /*
00272  * Read the file header; return image size and component count.
00273  */
00274 
00275 METHODDEF(void)
00276 start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00277 {
00278   bmp_source_ptr source = (bmp_source_ptr) sinfo;
00279   U_CHAR bmpfileheader[14];
00280   U_CHAR bmpinfoheader[64];
00281 #define GET_2B(array,offset)  ((unsigned int) UCH(array[offset]) + \
00282                    (((unsigned int) UCH(array[offset+1])) << 8))
00283 #define GET_4B(array,offset)  ((INT32) UCH(array[offset]) + \
00284                    (((INT32) UCH(array[offset+1])) << 8) + \
00285                    (((INT32) UCH(array[offset+2])) << 16) + \
00286                    (((INT32) UCH(array[offset+3])) << 24))
00287   INT32 bfOffBits;
00288   INT32 headerSize;
00289   INT32 biWidth;
00290   INT32 biHeight;
00291   unsigned int biPlanes;
00292   INT32 biCompression;
00293   INT32 biXPelsPerMeter,biYPelsPerMeter;
00294   INT32 biClrUsed = 0;
00295   int mapentrysize = 0;     /* 0 indicates no colormap */
00296   INT32 bPad;
00297   JDIMENSION row_width;
00298 
00299   /* Read and verify the bitmap file header */
00300   if (! ReadOK(source->pub.input_file, bmpfileheader, 14))
00301     ERREXIT(cinfo, JERR_INPUT_EOF);
00302   if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */
00303     ERREXIT(cinfo, JERR_BMP_NOT);
00304   bfOffBits = (INT32) GET_4B(bmpfileheader,10);
00305   /* We ignore the remaining fileheader fields */
00306 
00307   /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
00308    * or 64 bytes (OS/2 2.x).  Check the first 4 bytes to find out which.
00309    */
00310   if (! ReadOK(source->pub.input_file, bmpinfoheader, 4))
00311     ERREXIT(cinfo, JERR_INPUT_EOF);
00312   headerSize = (INT32) GET_4B(bmpinfoheader,0);
00313   if (headerSize < 12 || headerSize > 64)
00314     ERREXIT(cinfo, JERR_BMP_BADHEADER);
00315   if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4))
00316     ERREXIT(cinfo, JERR_INPUT_EOF);
00317 
00318   switch ((int) headerSize) {
00319   case 12:
00320     /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
00321     biWidth = (INT32) GET_2B(bmpinfoheader,4);
00322     biHeight = (INT32) GET_2B(bmpinfoheader,6);
00323     biPlanes = GET_2B(bmpinfoheader,8);
00324     source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10);
00325 
00326     switch (source->bits_per_pixel) {
00327     case 8:         /* colormapped image */
00328       mapentrysize = 3;     /* OS/2 uses RGBTRIPLE colormap */
00329       TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
00330       break;
00331     case 24:            /* RGB image */
00332       TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight);
00333       break;
00334     default:
00335       ERREXIT(cinfo, JERR_BMP_BADDEPTH);
00336       break;
00337     }
00338     break;
00339   case 40:
00340   case 64:
00341     /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
00342     /* or OS/2 2.x header, which has additional fields that we ignore */
00343     biWidth = GET_4B(bmpinfoheader,4);
00344     biHeight = GET_4B(bmpinfoheader,8);
00345     biPlanes = GET_2B(bmpinfoheader,12);
00346     source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14);
00347     biCompression = GET_4B(bmpinfoheader,16);
00348     biXPelsPerMeter = GET_4B(bmpinfoheader,24);
00349     biYPelsPerMeter = GET_4B(bmpinfoheader,28);
00350     biClrUsed = GET_4B(bmpinfoheader,32);
00351     /* biSizeImage, biClrImportant fields are ignored */
00352 
00353     switch (source->bits_per_pixel) {
00354     case 8:         /* colormapped image */
00355       mapentrysize = 4;     /* Windows uses RGBQUAD colormap */
00356       TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
00357       break;
00358     case 24:            /* RGB image */
00359       TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
00360       break;
00361     case 32:            /* RGB image + Alpha channel */
00362       TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
00363       break;
00364     default:
00365       ERREXIT(cinfo, JERR_BMP_BADDEPTH);
00366       break;
00367     }
00368     if (biCompression != 0)
00369       ERREXIT(cinfo, JERR_BMP_COMPRESSED);
00370 
00371     if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
00372       /* Set JFIF density parameters from the BMP data */
00373       cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
00374       cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
00375       cinfo->density_unit = 2;  /* dots/cm */
00376     }
00377     break;
00378   default:
00379     ERREXIT(cinfo, JERR_BMP_BADHEADER);
00380     return;
00381   }
00382 
00383   if (biWidth <= 0 || biHeight <= 0)
00384     ERREXIT(cinfo, JERR_BMP_EMPTY);
00385   if (biPlanes != 1)
00386     ERREXIT(cinfo, JERR_BMP_BADPLANES);
00387 
00388   /* Compute distance to bitmap data --- will adjust for colormap below */
00389   bPad = bfOffBits - (headerSize + 14);
00390 
00391   /* Read the colormap, if any */
00392   if (mapentrysize > 0) {
00393     if (biClrUsed <= 0)
00394       biClrUsed = 256;      /* assume it's 256 */
00395     else if (biClrUsed > 256)
00396       ERREXIT(cinfo, JERR_BMP_BADCMAP);
00397     /* Allocate space to store the colormap */
00398     source->colormap = (*cinfo->mem->alloc_sarray)
00399       ((j_common_ptr) cinfo, JPOOL_IMAGE,
00400        (JDIMENSION) biClrUsed, (JDIMENSION) 3);
00401     /* and read it from the file */
00402     read_colormap(source, (int) biClrUsed, mapentrysize);
00403     /* account for size of colormap */
00404     bPad -= biClrUsed * mapentrysize;
00405   }
00406 
00407   /* Skip any remaining pad bytes */
00408   if (bPad < 0)         /* incorrect bfOffBits value? */
00409     ERREXIT(cinfo, JERR_BMP_BADHEADER);
00410   while (--bPad >= 0) {
00411     (void) read_byte(source);
00412   }
00413 
00414   /* Compute row width in file, including padding to 4-byte boundary */
00415   if (source->bits_per_pixel == 24)
00416     row_width = (JDIMENSION) (biWidth * 3);
00417   else if (source->bits_per_pixel == 32)
00418     row_width = (JDIMENSION) (biWidth * 4);
00419   else
00420     row_width = (JDIMENSION) biWidth;
00421   while ((row_width & 3) != 0) row_width++;
00422   source->row_width = row_width;
00423 
00424   /* Allocate space for inversion array, prepare for preload pass */
00425   source->whole_image = (*cinfo->mem->request_virt_sarray)
00426     ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
00427      row_width, (JDIMENSION) biHeight, (JDIMENSION) 1);
00428   source->pub.get_pixel_rows = preload_image;
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   /* Allocate one-row buffer for returned data */
00435   source->pub.buffer = (*cinfo->mem->alloc_sarray)
00436     ((j_common_ptr) cinfo, JPOOL_IMAGE,
00437      (JDIMENSION) (biWidth * 3), (JDIMENSION) 1);
00438   source->pub.buffer_height = 1;
00439 
00440   cinfo->in_color_space = JCS_RGB;
00441   cinfo->input_components = 3;
00442   cinfo->data_precision = 8;
00443   cinfo->image_width = (JDIMENSION) biWidth;
00444   cinfo->image_height = (JDIMENSION) biHeight;
00445 }
00446 
00447 
00448 /*
00449  * Finish up at the end of the file.
00450  */
00451 
00452 METHODDEF(void)
00453 finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00454 {
00455   /* no work */
00456 }
00457 
00458 
00459 /*
00460  * The module selection routine for BMP format input.
00461  */
00462 
00463 GLOBAL(cjpeg_source_ptr)
00464 jinit_read_bmp (j_compress_ptr cinfo)
00465 {
00466   bmp_source_ptr source;
00467 
00468   /* Create module interface object */
00469   source = (bmp_source_ptr)
00470       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00471                   SIZEOF(bmp_source_struct));
00472   source->cinfo = cinfo;    /* make back link for subroutines */
00473   /* Fill in method ptrs, except get_pixel_rows which start_input sets */
00474   source->pub.start_input = start_input_bmp;
00475   source->pub.finish_input = finish_input_bmp;
00476 
00477   return (cjpeg_source_ptr) source;
00478 }
00479 
00480 #endif /* BMP_SUPPORTED */

Generated on Sat May 26 2012 04:18:14 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.