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 |