00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "cdjpeg.h"
00026
00027 #ifdef BMP_SUPPORTED
00028
00029
00030
00031
00032 #ifdef HAVE_UNSIGNED_CHAR
00033 typedef unsigned char U_CHAR;
00034 #define UCH(x) ((int) (x))
00035 #else
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
00044
00045
00046 #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
00047
00048
00049
00050
00051 typedef struct _bmp_source_struct * bmp_source_ptr;
00052
00053 typedef struct _bmp_source_struct {
00054 struct cjpeg_source_struct pub;
00055
00056 j_compress_ptr cinfo;
00057
00058 JSAMPARRAY colormap;
00059
00060 jvirt_sarray_ptr whole_image;
00061 JDIMENSION source_row;
00062 JDIMENSION row_width;
00063
00064 int bits_per_pixel;
00065 } bmp_source_struct;
00066
00067
00068 LOCAL(int)
00069 read_byte (bmp_source_ptr sinfo)
00070
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
00084 {
00085 int i;
00086
00087 switch (mapentrysize) {
00088 case 3:
00089
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
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
00114
00115
00116
00117
00118
00119 METHODDEF(JDIMENSION)
00120 get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00121
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
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
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];
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
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
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
00166
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++;
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
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
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
00196
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++;
00202 outptr[1] = *inptr++;
00203 outptr[0] = *inptr++;
00204 inptr++;
00205 outptr += 3;
00206 }
00207
00208 return 1;
00209 }
00210
00211
00212
00213
00214
00215
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
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
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
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
00267 return (*source->pub.get_pixel_rows) (cinfo, sinfo);
00268 }
00269
00270
00271
00272
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;
00296 INT32 bPad;
00297 JDIMENSION row_width;
00298
00299
00300 if (! ReadOK(source->pub.input_file, bmpfileheader, 14))
00301 ERREXIT(cinfo, JERR_INPUT_EOF);
00302 if (GET_2B(bmpfileheader,0) != 0x4D42)
00303 ERREXIT(cinfo, JERR_BMP_NOT);
00304 bfOffBits = (INT32) GET_4B(bmpfileheader,10);
00305
00306
00307
00308
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
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:
00328 mapentrysize = 3;
00329 TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
00330 break;
00331 case 24:
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
00342
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
00352
00353 switch (source->bits_per_pixel) {
00354 case 8:
00355 mapentrysize = 4;
00356 TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
00357 break;
00358 case 24:
00359 TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
00360 break;
00361 case 32:
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
00373 cinfo->X_density = (UINT16) (biXPelsPerMeter/100);
00374 cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
00375 cinfo->density_unit = 2;
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
00389 bPad = bfOffBits - (headerSize + 14);
00390
00391
00392 if (mapentrysize > 0) {
00393 if (biClrUsed <= 0)
00394 biClrUsed = 256;
00395 else if (biClrUsed > 256)
00396 ERREXIT(cinfo, JERR_BMP_BADCMAP);
00397
00398 source->colormap = (*cinfo->mem->alloc_sarray)
00399 ((j_common_ptr) cinfo, JPOOL_IMAGE,
00400 (JDIMENSION) biClrUsed, (JDIMENSION) 3);
00401
00402 read_colormap(source, (int) biClrUsed, mapentrysize);
00403
00404 bPad -= biClrUsed * mapentrysize;
00405 }
00406
00407
00408 if (bPad < 0)
00409 ERREXIT(cinfo, JERR_BMP_BADHEADER);
00410 while (--bPad >= 0) {
00411 (void) read_byte(source);
00412 }
00413
00414
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
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++;
00432 }
00433
00434
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
00450
00451
00452 METHODDEF(void)
00453 finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00454 {
00455
00456 }
00457
00458
00459
00460
00461
00462
00463 GLOBAL(cjpeg_source_ptr)
00464 jinit_read_bmp (j_compress_ptr cinfo)
00465 {
00466 bmp_source_ptr source;
00467
00468
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;
00473
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