| OLD | NEW |
| 1 /* | 1 /* |
| 2 * rdbmp.c | 2 * rdbmp.c |
| 3 * | 3 * |
| 4 * Copyright (C) 1994-1996, Thomas G. Lane. | 4 * Copyright (C) 1994-1996, Thomas G. Lane. |
| 5 * Modified 2009-2010 by Guido Vollbeding. |
| 6 * Modified 2011 by Siarhei Siamashka. |
| 5 * This file is part of the Independent JPEG Group's software. | 7 * This file is part of the Independent JPEG Group's software. |
| 6 * For conditions of distribution and use, see the accompanying README file. | 8 * For conditions of distribution and use, see the accompanying README file. |
| 7 * | 9 * |
| 8 * This file contains routines to read input images in Microsoft "BMP" | 10 * This file contains routines to read input images in Microsoft "BMP" |
| 9 * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors). | 11 * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors). |
| 10 * Currently, only 8-bit and 24-bit images are supported, not 1-bit or | 12 * Currently, only 8-bit and 24-bit images are supported, not 1-bit or |
| 11 * 4-bit (feeding such low-depth images into JPEG would be silly anyway). | 13 * 4-bit (feeding such low-depth images into JPEG would be silly anyway). |
| 12 * Also, we don't support RLE-compressed files. | 14 * Also, we don't support RLE-compressed files. |
| 13 * | 15 * |
| 14 * These routines may need modification for non-Unix environments or | 16 * These routines may need modification for non-Unix environments or |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ | 172 outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ |
| 171 outptr[1] = *inptr++; | 173 outptr[1] = *inptr++; |
| 172 outptr[0] = *inptr++; | 174 outptr[0] = *inptr++; |
| 173 outptr += 3; | 175 outptr += 3; |
| 174 } | 176 } |
| 175 | 177 |
| 176 return 1; | 178 return 1; |
| 177 } | 179 } |
| 178 | 180 |
| 179 | 181 |
| 182 METHODDEF(JDIMENSION) |
| 183 get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) |
| 184 /* This version is for reading 32-bit pixels */ |
| 185 { |
| 186 bmp_source_ptr source = (bmp_source_ptr) sinfo; |
| 187 JSAMPARRAY image_ptr; |
| 188 register JSAMPROW inptr, outptr; |
| 189 register JDIMENSION col; |
| 190 |
| 191 /* Fetch next row from virtual array */ |
| 192 source->source_row--; |
| 193 image_ptr = (*cinfo->mem->access_virt_sarray) |
| 194 ((j_common_ptr) cinfo, source->whole_image, |
| 195 source->source_row, (JDIMENSION) 1, FALSE); |
| 196 /* Transfer data. Note source values are in BGR order |
| 197 * (even though Microsoft's own documents say the opposite). |
| 198 */ |
| 199 inptr = image_ptr[0]; |
| 200 outptr = source->pub.buffer[0]; |
| 201 for (col = cinfo->image_width; col > 0; col--) { |
| 202 outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ |
| 203 outptr[1] = *inptr++; |
| 204 outptr[0] = *inptr++; |
| 205 inptr++; /* skip the 4th byte (Alpha channel) */ |
| 206 outptr += 3; |
| 207 } |
| 208 |
| 209 return 1; |
| 210 } |
| 211 |
| 212 |
| 180 /* | 213 /* |
| 181 * This method loads the image into whole_image during the first call on | 214 * This method loads the image into whole_image during the first call on |
| 182 * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call | 215 * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call |
| 183 * get_8bit_row or get_24bit_row on subsequent calls. | 216 * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls. |
| 184 */ | 217 */ |
| 185 | 218 |
| 186 METHODDEF(JDIMENSION) | 219 METHODDEF(JDIMENSION) |
| 187 preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | 220 preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) |
| 188 { | 221 { |
| 189 bmp_source_ptr source = (bmp_source_ptr) sinfo; | 222 bmp_source_ptr source = (bmp_source_ptr) sinfo; |
| 190 register FILE *infile = source->pub.input_file; | 223 register FILE *infile = source->pub.input_file; |
| 191 register int c; | |
| 192 register JSAMPROW out_ptr; | 224 register JSAMPROW out_ptr; |
| 193 JSAMPARRAY image_ptr; | 225 JSAMPARRAY image_ptr; |
| 194 JDIMENSION row, col; | 226 JDIMENSION row; |
| 195 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; | 227 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; |
| 196 | 228 |
| 197 /* Read the data into a virtual array in input-file row order. */ | 229 /* Read the data into a virtual array in input-file row order. */ |
| 198 for (row = 0; row < cinfo->image_height; row++) { | 230 for (row = 0; row < cinfo->image_height; row++) { |
| 199 if (progress != NULL) { | 231 if (progress != NULL) { |
| 200 progress->pub.pass_counter = (long) row; | 232 progress->pub.pass_counter = (long) row; |
| 201 progress->pub.pass_limit = (long) cinfo->image_height; | 233 progress->pub.pass_limit = (long) cinfo->image_height; |
| 202 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); | 234 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); |
| 203 } | 235 } |
| 204 image_ptr = (*cinfo->mem->access_virt_sarray) | 236 image_ptr = (*cinfo->mem->access_virt_sarray) |
| 205 ((j_common_ptr) cinfo, source->whole_image, | 237 ((j_common_ptr) cinfo, source->whole_image, |
| 206 row, (JDIMENSION) 1, TRUE); | 238 row, (JDIMENSION) 1, TRUE); |
| 207 out_ptr = image_ptr[0]; | 239 out_ptr = image_ptr[0]; |
| 208 for (col = source->row_width; col > 0; col--) { | 240 if (fread(out_ptr, 1, source->row_width, infile) != source->row_width) { |
| 209 /* inline copy of read_byte() for speed */ | 241 if (feof(infile)) |
| 210 if ((c = getc(infile)) == EOF) | 242 ERREXIT(cinfo, JERR_INPUT_EOF); |
| 211 » ERREXIT(cinfo, JERR_INPUT_EOF); | 243 else |
| 212 *out_ptr++ = (JSAMPLE) c; | 244 ERREXIT(cinfo, JERR_FILE_READ); |
| 213 } | 245 } |
| 214 } | 246 } |
| 215 if (progress != NULL) | 247 if (progress != NULL) |
| 216 progress->completed_extra_passes++; | 248 progress->completed_extra_passes++; |
| 217 | 249 |
| 218 /* Set up to read from the virtual array in top-to-bottom order */ | 250 /* Set up to read from the virtual array in top-to-bottom order */ |
| 219 switch (source->bits_per_pixel) { | 251 switch (source->bits_per_pixel) { |
| 220 case 8: | 252 case 8: |
| 221 source->pub.get_pixel_rows = get_8bit_row; | 253 source->pub.get_pixel_rows = get_8bit_row; |
| 222 break; | 254 break; |
| 223 case 24: | 255 case 24: |
| 224 source->pub.get_pixel_rows = get_24bit_row; | 256 source->pub.get_pixel_rows = get_24bit_row; |
| 225 break; | 257 break; |
| 258 case 32: |
| 259 source->pub.get_pixel_rows = get_32bit_row; |
| 260 break; |
| 226 default: | 261 default: |
| 227 ERREXIT(cinfo, JERR_BMP_BADDEPTH); | 262 ERREXIT(cinfo, JERR_BMP_BADDEPTH); |
| 228 } | 263 } |
| 229 source->source_row = cinfo->image_height; | 264 source->source_row = cinfo->image_height; |
| 230 | 265 |
| 231 /* And read the first row */ | 266 /* And read the first row */ |
| 232 return (*source->pub.get_pixel_rows) (cinfo, sinfo); | 267 return (*source->pub.get_pixel_rows) (cinfo, sinfo); |
| 233 } | 268 } |
| 234 | 269 |
| 235 | 270 |
| 236 /* | 271 /* |
| 237 * Read the file header; return image size and component count. | 272 * Read the file header; return image size and component count. |
| 238 */ | 273 */ |
| 239 | 274 |
| 240 METHODDEF(void) | 275 METHODDEF(void) |
| 241 start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | 276 start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) |
| 242 { | 277 { |
| 243 bmp_source_ptr source = (bmp_source_ptr) sinfo; | 278 bmp_source_ptr source = (bmp_source_ptr) sinfo; |
| 244 U_CHAR bmpfileheader[14]; | 279 U_CHAR bmpfileheader[14]; |
| 245 U_CHAR bmpinfoheader[64]; | 280 U_CHAR bmpinfoheader[64]; |
| 246 #define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \ | 281 #define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \ |
| 247 (((unsigned int) UCH(array[offset+1])) << 8)) | 282 (((unsigned int) UCH(array[offset+1])) << 8)) |
| 248 #define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \ | 283 #define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \ |
| 249 (((INT32) UCH(array[offset+1])) << 8) + \ | 284 (((INT32) UCH(array[offset+1])) << 8) + \ |
| 250 (((INT32) UCH(array[offset+2])) << 16) + \ | 285 (((INT32) UCH(array[offset+2])) << 16) + \ |
| 251 (((INT32) UCH(array[offset+3])) << 24)) | 286 (((INT32) UCH(array[offset+3])) << 24)) |
| 252 INT32 bfOffBits; | 287 INT32 bfOffBits; |
| 253 INT32 headerSize; | 288 INT32 headerSize; |
| 254 INT32 biWidth = 0;» » /* initialize to avoid compiler warning */ | 289 INT32 biWidth; |
| 255 INT32 biHeight = 0; | 290 INT32 biHeight; |
| 256 unsigned int biPlanes; | 291 unsigned int biPlanes; |
| 257 INT32 biCompression; | 292 INT32 biCompression; |
| 258 INT32 biXPelsPerMeter,biYPelsPerMeter; | 293 INT32 biXPelsPerMeter,biYPelsPerMeter; |
| 259 INT32 biClrUsed = 0; | 294 INT32 biClrUsed = 0; |
| 260 int mapentrysize = 0; /* 0 indicates no colormap */ | 295 int mapentrysize = 0; /* 0 indicates no colormap */ |
| 261 INT32 bPad; | 296 INT32 bPad; |
| 262 JDIMENSION row_width; | 297 JDIMENSION row_width; |
| 263 | 298 |
| 264 /* Read and verify the bitmap file header */ | 299 /* Read and verify the bitmap file header */ |
| 265 if (! ReadOK(source->pub.input_file, bmpfileheader, 14)) | 300 if (! ReadOK(source->pub.input_file, bmpfileheader, 14)) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 293 mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */ | 328 mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */ |
| 294 TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight); | 329 TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight); |
| 295 break; | 330 break; |
| 296 case 24: /* RGB image */ | 331 case 24: /* RGB image */ |
| 297 TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight); | 332 TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight); |
| 298 break; | 333 break; |
| 299 default: | 334 default: |
| 300 ERREXIT(cinfo, JERR_BMP_BADDEPTH); | 335 ERREXIT(cinfo, JERR_BMP_BADDEPTH); |
| 301 break; | 336 break; |
| 302 } | 337 } |
| 303 if (biPlanes != 1) | |
| 304 ERREXIT(cinfo, JERR_BMP_BADPLANES); | |
| 305 break; | 338 break; |
| 306 case 40: | 339 case 40: |
| 307 case 64: | 340 case 64: |
| 308 /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */ | 341 /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */ |
| 309 /* or OS/2 2.x header, which has additional fields that we ignore */ | 342 /* or OS/2 2.x header, which has additional fields that we ignore */ |
| 310 biWidth = GET_4B(bmpinfoheader,4); | 343 biWidth = GET_4B(bmpinfoheader,4); |
| 311 biHeight = GET_4B(bmpinfoheader,8); | 344 biHeight = GET_4B(bmpinfoheader,8); |
| 312 biPlanes = GET_2B(bmpinfoheader,12); | 345 biPlanes = GET_2B(bmpinfoheader,12); |
| 313 source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14); | 346 source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14); |
| 314 biCompression = GET_4B(bmpinfoheader,16); | 347 biCompression = GET_4B(bmpinfoheader,16); |
| 315 biXPelsPerMeter = GET_4B(bmpinfoheader,24); | 348 biXPelsPerMeter = GET_4B(bmpinfoheader,24); |
| 316 biYPelsPerMeter = GET_4B(bmpinfoheader,28); | 349 biYPelsPerMeter = GET_4B(bmpinfoheader,28); |
| 317 biClrUsed = GET_4B(bmpinfoheader,32); | 350 biClrUsed = GET_4B(bmpinfoheader,32); |
| 318 /* biSizeImage, biClrImportant fields are ignored */ | 351 /* biSizeImage, biClrImportant fields are ignored */ |
| 319 | 352 |
| 320 switch (source->bits_per_pixel) { | 353 switch (source->bits_per_pixel) { |
| 321 case 8: /* colormapped image */ | 354 case 8: /* colormapped image */ |
| 322 mapentrysize = 4; /* Windows uses RGBQUAD colormap */ | 355 mapentrysize = 4; /* Windows uses RGBQUAD colormap */ |
| 323 TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight); | 356 TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight); |
| 324 break; | 357 break; |
| 325 case 24: /* RGB image */ | 358 case 24: /* RGB image */ |
| 326 TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); | 359 TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); |
| 327 break; | 360 break; |
| 361 case 32: /* RGB image + Alpha channel */ |
| 362 TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); |
| 363 break; |
| 328 default: | 364 default: |
| 329 ERREXIT(cinfo, JERR_BMP_BADDEPTH); | 365 ERREXIT(cinfo, JERR_BMP_BADDEPTH); |
| 330 break; | 366 break; |
| 331 } | 367 } |
| 332 if (biPlanes != 1) | |
| 333 ERREXIT(cinfo, JERR_BMP_BADPLANES); | |
| 334 if (biCompression != 0) | 368 if (biCompression != 0) |
| 335 ERREXIT(cinfo, JERR_BMP_COMPRESSED); | 369 ERREXIT(cinfo, JERR_BMP_COMPRESSED); |
| 336 | 370 |
| 337 if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) { | 371 if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) { |
| 338 /* Set JFIF density parameters from the BMP data */ | 372 /* Set JFIF density parameters from the BMP data */ |
| 339 cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */ | 373 cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */ |
| 340 cinfo->Y_density = (UINT16) (biYPelsPerMeter/100); | 374 cinfo->Y_density = (UINT16) (biYPelsPerMeter/100); |
| 341 cinfo->density_unit = 2; /* dots/cm */ | 375 cinfo->density_unit = 2; /* dots/cm */ |
| 342 } | 376 } |
| 343 break; | 377 break; |
| 344 default: | 378 default: |
| 345 ERREXIT(cinfo, JERR_BMP_BADHEADER); | 379 ERREXIT(cinfo, JERR_BMP_BADHEADER); |
| 346 break; | 380 return; |
| 347 } | 381 } |
| 348 | 382 |
| 383 if (biWidth <= 0 || biHeight <= 0) |
| 384 ERREXIT(cinfo, JERR_BMP_EMPTY); |
| 385 if (biPlanes != 1) |
| 386 ERREXIT(cinfo, JERR_BMP_BADPLANES); |
| 387 |
| 349 /* Compute distance to bitmap data --- will adjust for colormap below */ | 388 /* Compute distance to bitmap data --- will adjust for colormap below */ |
| 350 bPad = bfOffBits - (headerSize + 14); | 389 bPad = bfOffBits - (headerSize + 14); |
| 351 | 390 |
| 352 /* Read the colormap, if any */ | 391 /* Read the colormap, if any */ |
| 353 if (mapentrysize > 0) { | 392 if (mapentrysize > 0) { |
| 354 if (biClrUsed <= 0) | 393 if (biClrUsed <= 0) |
| 355 biClrUsed = 256; /* assume it's 256 */ | 394 biClrUsed = 256; /* assume it's 256 */ |
| 356 else if (biClrUsed > 256) | 395 else if (biClrUsed > 256) |
| 357 ERREXIT(cinfo, JERR_BMP_BADCMAP); | 396 ERREXIT(cinfo, JERR_BMP_BADCMAP); |
| 358 /* Allocate space to store the colormap */ | 397 /* Allocate space to store the colormap */ |
| 359 source->colormap = (*cinfo->mem->alloc_sarray) | 398 source->colormap = (*cinfo->mem->alloc_sarray) |
| 360 ((j_common_ptr) cinfo, JPOOL_IMAGE, | 399 ((j_common_ptr) cinfo, JPOOL_IMAGE, |
| 361 (JDIMENSION) biClrUsed, (JDIMENSION) 3); | 400 (JDIMENSION) biClrUsed, (JDIMENSION) 3); |
| 362 /* and read it from the file */ | 401 /* and read it from the file */ |
| 363 read_colormap(source, (int) biClrUsed, mapentrysize); | 402 read_colormap(source, (int) biClrUsed, mapentrysize); |
| 364 /* account for size of colormap */ | 403 /* account for size of colormap */ |
| 365 bPad -= biClrUsed * mapentrysize; | 404 bPad -= biClrUsed * mapentrysize; |
| 366 } | 405 } |
| 367 | 406 |
| 368 /* Skip any remaining pad bytes */ | 407 /* Skip any remaining pad bytes */ |
| 369 if (bPad < 0) /* incorrect bfOffBits value? */ | 408 if (bPad < 0) /* incorrect bfOffBits value? */ |
| 370 ERREXIT(cinfo, JERR_BMP_BADHEADER); | 409 ERREXIT(cinfo, JERR_BMP_BADHEADER); |
| 371 while (--bPad >= 0) { | 410 while (--bPad >= 0) { |
| 372 (void) read_byte(source); | 411 (void) read_byte(source); |
| 373 } | 412 } |
| 374 | 413 |
| 375 /* Compute row width in file, including padding to 4-byte boundary */ | 414 /* Compute row width in file, including padding to 4-byte boundary */ |
| 376 if (source->bits_per_pixel == 24) | 415 if (source->bits_per_pixel == 24) |
| 377 row_width = (JDIMENSION) (biWidth * 3); | 416 row_width = (JDIMENSION) (biWidth * 3); |
| 417 else if (source->bits_per_pixel == 32) |
| 418 row_width = (JDIMENSION) (biWidth * 4); |
| 378 else | 419 else |
| 379 row_width = (JDIMENSION) biWidth; | 420 row_width = (JDIMENSION) biWidth; |
| 380 while ((row_width & 3) != 0) row_width++; | 421 while ((row_width & 3) != 0) row_width++; |
| 381 source->row_width = row_width; | 422 source->row_width = row_width; |
| 382 | 423 |
| 383 /* Allocate space for inversion array, prepare for preload pass */ | 424 /* Allocate space for inversion array, prepare for preload pass */ |
| 384 source->whole_image = (*cinfo->mem->request_virt_sarray) | 425 source->whole_image = (*cinfo->mem->request_virt_sarray) |
| 385 ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, | 426 ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, |
| 386 row_width, (JDIMENSION) biHeight, (JDIMENSION) 1); | 427 row_width, (JDIMENSION) biHeight, (JDIMENSION) 1); |
| 387 source->pub.get_pixel_rows = preload_image; | 428 source->pub.get_pixel_rows = preload_image; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 SIZEOF(bmp_source_struct)); | 471 SIZEOF(bmp_source_struct)); |
| 431 source->cinfo = cinfo; /* make back link for subroutines */ | 472 source->cinfo = cinfo; /* make back link for subroutines */ |
| 432 /* Fill in method ptrs, except get_pixel_rows which start_input sets */ | 473 /* Fill in method ptrs, except get_pixel_rows which start_input sets */ |
| 433 source->pub.start_input = start_input_bmp; | 474 source->pub.start_input = start_input_bmp; |
| 434 source->pub.finish_input = finish_input_bmp; | 475 source->pub.finish_input = finish_input_bmp; |
| 435 | 476 |
| 436 return (cjpeg_source_ptr) source; | 477 return (cjpeg_source_ptr) source; |
| 437 } | 478 } |
| 438 | 479 |
| 439 #endif /* BMP_SUPPORTED */ | 480 #endif /* BMP_SUPPORTED */ |
| OLD | NEW |