Final 350 project
Dependencies: uzair Camera_LS_Y201 F7_Ethernet LCD_DISCO_F746NG NetworkAPI SDFileSystem mbed
rdbmp.c
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 Wed Jul 13 2022 18:56:09 by 1.7.2