00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "cdjpeg.h"
00025
00026 #ifdef BMP_SUPPORTED
00027
00028
00029
00030
00031 #ifdef HAVE_UNSIGNED_CHAR
00032 typedef unsigned char U_CHAR;
00033 #define UCH(x) ((int) (x))
00034 #else
00035 #ifdef CHAR_IS_UNSIGNED
00036 typedef char U_CHAR;
00037 #define UCH(x) ((int) (x))
00038 #else
00039 typedef char U_CHAR;
00040 #define UCH(x) ((int) (x) & 0xFF)
00041 #endif
00042 #endif
00043
00044
00045 #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
00046
00047
00048
00049
00050 typedef struct _bmp_source_struct * bmp_source_ptr;
00051
00052 typedef struct _bmp_source_struct {
00053 struct cjpeg_source_struct pub;
00054
00055 j_compress_ptr cinfo;
00056
00057 JSAMPARRAY colormap;
00058
00059 jvirt_sarray_ptr whole_image;
00060 JDIMENSION source_row;
00061 JDIMENSION row_width;
00062
00063 int bits_per_pixel;
00064 } bmp_source_struct;
00065
00066
00067 LOCAL(int)
00068 read_byte (bmp_source_ptr sinfo)
00069
00070 {
00071 register FILE *infile = sinfo->pub.input_file;
00072 register int c;
00073
00074 if ((c = getc(infile)) == EOF)
00075 ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
00076 return c;
00077 }
00078
00079
00080 LOCAL(void)
00081 read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize)
00082
00083 {
00084 int i;
00085
00086 switch (mapentrysize) {
00087 case 3:
00088
00089 for (i = 0; i < cmaplen; i++) {
00090 sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
00091 sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
00092 sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
00093 }
00094 break;
00095 case 4:
00096
00097 for (i = 0; i < cmaplen; i++) {
00098 sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
00099 sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
00100 sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
00101 (void) read_byte(sinfo);
00102 }
00103 break;
00104 default:
00105 ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
00106 break;
00107 }
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 METHODDEF(JDIMENSION)
00119 get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00120
00121 {
00122 bmp_source_ptr source = (bmp_source_ptr) sinfo;
00123 register JSAMPARRAY colormap = source->colormap;
00124 JSAMPARRAY image_ptr;
00125 register int t;
00126 register JSAMPROW inptr, outptr;
00127 register JDIMENSION col;
00128
00129
00130 source->source_row--;
00131 image_ptr = (*cinfo->mem->access_virt_sarray)
00132 ((j_common_ptr) cinfo, source->whole_image,
00133 source->source_row, (JDIMENSION) 1, FALSE);
00134
00135
00136 inptr = image_ptr[0];
00137 outptr = source->pub.buffer[0];
00138 for (col = cinfo->image_width; col > 0; col--) {
00139 t = GETJSAMPLE(*inptr++);
00140 *outptr++ = colormap[0][t];
00141 *outptr++ = colormap[1][t];
00142 *outptr++ = colormap[2][t];
00143 }
00144
00145 return 1;
00146 }
00147
00148
00149 METHODDEF(JDIMENSION)
00150 get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00151
00152 {
00153 bmp_source_ptr source = (bmp_source_ptr) sinfo;
00154 JSAMPARRAY image_ptr;
00155 register JSAMPROW inptr, outptr;
00156 register JDIMENSION col;
00157
00158
00159 source->source_row--;
00160 image_ptr = (*cinfo->mem->access_virt_sarray)
00161 ((j_common_ptr) cinfo, source->whole_image,
00162 source->source_row, (JDIMENSION) 1, FALSE);
00163
00164
00165
00166
00167 inptr = image_ptr[0];
00168 outptr = source->pub.buffer[0];
00169 for (col = cinfo->image_width; col > 0; col--) {
00170 outptr[2] = *inptr++;
00171 outptr[1] = *inptr++;
00172 outptr[0] = *inptr++;
00173 outptr += 3;
00174 }
00175
00176 return 1;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186 METHODDEF(JDIMENSION)
00187 preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00188 {
00189 bmp_source_ptr source = (bmp_source_ptr) sinfo;
00190 register FILE *infile = source->pub.input_file;
00191 register int c;
00192 register JSAMPROW out_ptr;
00193 JSAMPARRAY image_ptr;
00194 JDIMENSION row, col;
00195 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
00196
00197
00198 for (row = 0; row < cinfo->image_height; row++) {
00199 if (progress != NULL) {
00200 progress->pub.pass_counter = (long) row;
00201 progress->pub.pass_limit = (long) cinfo->image_height;
00202 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
00203 }
00204 image_ptr = (*cinfo->mem->access_virt_sarray)
00205 ((j_common_ptr) cinfo, source->whole_image,
00206 row, (JDIMENSION) 1, TRUE);
00207 out_ptr = image_ptr[0];
00208 for (col = source->row_width; col > 0; col--) {
00209
00210 if ((c = getc(infile)) == EOF)
00211 ERREXIT(cinfo, JERR_INPUT_EOF);
00212 *out_ptr++ = (JSAMPLE) c;
00213 }
00214 }
00215 if (progress != NULL)
00216 progress->completed_extra_passes++;
00217
00218
00219 switch (source->bits_per_pixel) {
00220 case 8:
00221 source->pub.get_pixel_rows = get_8bit_row;
00222 break;
00223 case 24:
00224 source->pub.get_pixel_rows = get_24bit_row;
00225 break;
00226 default:
00227 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
00228 }
00229 source->source_row = cinfo->image_height;
00230
00231
00232 return (*source->pub.get_pixel_rows) (cinfo, sinfo);
00233 }
00234
00235
00236
00237
00238
00239
00240 METHODDEF(void)
00241 start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00242 {
00243 bmp_source_ptr source = (bmp_source_ptr) sinfo;
00244 U_CHAR bmpfileheader[14];
00245 U_CHAR bmpinfoheader[64];
00246 #define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \
00247 (((unsigned int) UCH(array[offset+1])) << 8))
00248 #define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \
00249 (((INT32) UCH(array[offset+1])) << 8) + \
00250 (((INT32) UCH(array[offset+2])) << 16) + \
00251 (((INT32) UCH(array[offset+3])) << 24))
00252 INT32 bfOffBits;
00253 INT32 headerSize;
00254 INT32 biWidth = 0;
00255 INT32 biHeight = 0;
00256 unsigned int biPlanes;
00257 INT32 biCompression;
00258 INT32 biXPelsPerMeter,biYPelsPerMeter;
00259 INT32 biClrUsed = 0;
00260 int mapentrysize = 0;
00261 INT32 bPad;
00262 JDIMENSION row_width;
00263
00264
00265 if (! ReadOK(source->pub.input_file, bmpfileheader, 14))
00266 ERREXIT(cinfo, JERR_INPUT_EOF);
00267 if (GET_2B(bmpfileheader,0) != 0x4D42)
00268 ERREXIT(cinfo, JERR_BMP_NOT);
00269 bfOffBits = (INT32) GET_4B(bmpfileheader,10);
00270
00271
00272
00273
00274
00275 if (! ReadOK(source->pub.input_file, bmpinfoheader, 4))
00276 ERREXIT(cinfo, JERR_INPUT_EOF);
00277 headerSize = (INT32) GET_4B(bmpinfoheader,0);
00278 if (headerSize < 12 || headerSize > 64)
00279 ERREXIT(cinfo, JERR_BMP_BADHEADER);
00280 if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4))
00281 ERREXIT(cinfo, JERR_INPUT_EOF);
00282
00283 switch ((int) headerSize) {
00284 case 12:
00285
00286 biWidth = (INT32) GET_2B(bmpinfoheader,4);
00287 biHeight = (INT32) GET_2B(bmpinfoheader,6);
00288 biPlanes = GET_2B(bmpinfoheader,8);
00289 source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10);
00290
00291 switch (source->bits_per_pixel) {
00292 case 8:
00293 mapentrysize = 3;
00294 TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
00295 break;
00296 case 24:
00297 TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight);
00298 break;
00299 default:
00300 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
00301 break;
00302 }
00303 if (biPlanes != 1)
00304 ERREXIT(cinfo, JERR_BMP_BADPLANES);
00305 break;
00306 case 40:
00307 case 64:
00308
00309
00310 biWidth = GET_4B(bmpinfoheader,4);
00311 biHeight = GET_4B(bmpinfoheader,8);
00312 biPlanes = GET_2B(bmpinfoheader,12);
00313 source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14);
00314 biCompression = GET_4B(bmpinfoheader,16);
00315 biXPelsPerMeter = GET_4B(bmpinfoheader,24);
00316 biYPelsPerMeter = GET_4B(bmpinfoheader,28);
00317 biClrUsed = GET_4B(bmpinfoheader,32);
00318
00319
00320 switch (source->bits_per_pixel) {
00321 case 8:
00322 mapentrysize = 4;
00323 TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
00324 break;
00325 case 24:
00326 TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
00327 break;
00328 default:
00329 ERREXIT(cinfo, JERR_BMP_BADDEPTH);
00330 break;
00331 }
00332 if (biPlanes != 1)
00333 ERREXIT(cinfo, JERR_BMP_BADPLANES);
00334 if (biCompression != 0)
00335 ERREXIT(cinfo, JERR_BMP_COMPRESSED);
00336
00337 if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
00338
00339 cinfo->X_density = (UINT16) (biXPelsPerMeter/100);
00340 cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
00341 cinfo->density_unit = 2;
00342 }
00343 break;
00344 default:
00345 ERREXIT(cinfo, JERR_BMP_BADHEADER);
00346 break;
00347 }
00348
00349
00350 bPad = bfOffBits - (headerSize + 14);
00351
00352
00353 if (mapentrysize > 0) {
00354 if (biClrUsed <= 0)
00355 biClrUsed = 256;
00356 else if (biClrUsed > 256)
00357 ERREXIT(cinfo, JERR_BMP_BADCMAP);
00358
00359 source->colormap = (*cinfo->mem->alloc_sarray)
00360 ((j_common_ptr) cinfo, JPOOL_IMAGE,
00361 (JDIMENSION) biClrUsed, (JDIMENSION) 3);
00362
00363 read_colormap(source, (int) biClrUsed, mapentrysize);
00364
00365 bPad -= biClrUsed * mapentrysize;
00366 }
00367
00368
00369 if (bPad < 0)
00370 ERREXIT(cinfo, JERR_BMP_BADHEADER);
00371 while (--bPad >= 0) {
00372 (void) read_byte(source);
00373 }
00374
00375
00376 if (source->bits_per_pixel == 24)
00377 row_width = (JDIMENSION) (biWidth * 3);
00378 else
00379 row_width = (JDIMENSION) biWidth;
00380 while ((row_width & 3) != 0) row_width++;
00381 source->row_width = row_width;
00382
00383
00384 source->whole_image = (*cinfo->mem->request_virt_sarray)
00385 ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
00386 row_width, (JDIMENSION) biHeight, (JDIMENSION) 1);
00387 source->pub.get_pixel_rows = preload_image;
00388 if (cinfo->progress != NULL) {
00389 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
00390 progress->total_extra_passes++;
00391 }
00392
00393
00394 source->pub.buffer = (*cinfo->mem->alloc_sarray)
00395 ((j_common_ptr) cinfo, JPOOL_IMAGE,
00396 (JDIMENSION) (biWidth * 3), (JDIMENSION) 1);
00397 source->pub.buffer_height = 1;
00398
00399 cinfo->in_color_space = JCS_RGB;
00400 cinfo->input_components = 3;
00401 cinfo->data_precision = 8;
00402 cinfo->image_width = (JDIMENSION) biWidth;
00403 cinfo->image_height = (JDIMENSION) biHeight;
00404 }
00405
00406
00407
00408
00409
00410
00411 METHODDEF(void)
00412 finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
00413 {
00414
00415 }
00416
00417
00418
00419
00420
00421
00422 GLOBAL(cjpeg_source_ptr)
00423 jinit_read_bmp (j_compress_ptr cinfo)
00424 {
00425 bmp_source_ptr source;
00426
00427
00428 source = (bmp_source_ptr)
00429 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00430 SIZEOF(bmp_source_struct));
00431 source->cinfo = cinfo;
00432
00433 source->pub.start_input = start_input_bmp;
00434 source->pub.finish_input = finish_input_bmp;
00435
00436 return (cjpeg_source_ptr) source;
00437 }
00438
00439 #endif