00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "cdjpeg.h"
00021
00022 #ifdef BMP_SUPPORTED
00023
00024
00025
00026
00027
00028
00029
00030 #if BITS_IN_JSAMPLE != 8
00031 Sorry, this code only copes with 8-bit JSAMPLEs.
00032 #endif
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 typedef struct {
00045 struct djpeg_dest_struct pub;
00046
00047 boolean is_os2;
00048
00049 jvirt_sarray_ptr whole_image;
00050 JDIMENSION data_width;
00051 JDIMENSION row_width;
00052 int pad_bytes;
00053 JDIMENSION cur_output_row;
00054 } bmp_dest_struct;
00055
00056 typedef bmp_dest_struct * bmp_dest_ptr;
00057
00058
00059
00060 LOCAL(void) write_colormap
00061 JPP((j_decompress_ptr cinfo, bmp_dest_ptr dest,
00062 int map_colors, int map_entry_size));
00063
00064
00065
00066
00067
00068
00069
00070 METHODDEF(void)
00071 put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
00072 JDIMENSION rows_supplied)
00073
00074 {
00075 bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
00076 JSAMPARRAY image_ptr;
00077 register JSAMPROW inptr, outptr;
00078 register JDIMENSION col;
00079 int pad;
00080
00081
00082 image_ptr = (*cinfo->mem->access_virt_sarray)
00083 ((j_common_ptr) cinfo, dest->whole_image,
00084 dest->cur_output_row, (JDIMENSION) 1, TRUE);
00085 dest->cur_output_row++;
00086
00087
00088
00089
00090 inptr = dest->pub.buffer[0];
00091 outptr = image_ptr[0];
00092 for (col = cinfo->output_width; col > 0; col--) {
00093 outptr[2] = *inptr++;
00094 outptr[1] = *inptr++;
00095 outptr[0] = *inptr++;
00096 outptr += 3;
00097 }
00098
00099
00100 pad = dest->pad_bytes;
00101 while (--pad >= 0)
00102 *outptr++ = 0;
00103 }
00104
00105 METHODDEF(void)
00106 put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
00107 JDIMENSION rows_supplied)
00108
00109 {
00110 bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
00111 JSAMPARRAY image_ptr;
00112 register JSAMPROW inptr, outptr;
00113 register JDIMENSION col;
00114 int pad;
00115
00116
00117 image_ptr = (*cinfo->mem->access_virt_sarray)
00118 ((j_common_ptr) cinfo, dest->whole_image,
00119 dest->cur_output_row, (JDIMENSION) 1, TRUE);
00120 dest->cur_output_row++;
00121
00122
00123 inptr = dest->pub.buffer[0];
00124 outptr = image_ptr[0];
00125 for (col = cinfo->output_width; col > 0; col--) {
00126 *outptr++ = *inptr++;
00127 }
00128
00129
00130 pad = dest->pad_bytes;
00131 while (--pad >= 0)
00132 *outptr++ = 0;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141 METHODDEF(void)
00142 start_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
00143 {
00144
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 LOCAL(void)
00157 write_bmp_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
00158
00159 {
00160 char bmpfileheader[14];
00161 char bmpinfoheader[40];
00162 #define PUT_2B(array,offset,value) \
00163 (array[offset] = (char) ((value) & 0xFF), \
00164 array[offset+1] = (char) (((value) >> 8) & 0xFF))
00165 #define PUT_4B(array,offset,value) \
00166 (array[offset] = (char) ((value) & 0xFF), \
00167 array[offset+1] = (char) (((value) >> 8) & 0xFF), \
00168 array[offset+2] = (char) (((value) >> 16) & 0xFF), \
00169 array[offset+3] = (char) (((value) >> 24) & 0xFF))
00170 INT32 headersize, bfSize;
00171 int bits_per_pixel, cmap_entries;
00172
00173
00174 if (cinfo->out_color_space == JCS_RGB) {
00175 if (cinfo->quantize_colors) {
00176
00177 bits_per_pixel = 8;
00178 cmap_entries = 256;
00179 } else {
00180
00181 bits_per_pixel = 24;
00182 cmap_entries = 0;
00183 }
00184 } else {
00185
00186 bits_per_pixel = 8;
00187 cmap_entries = 256;
00188 }
00189
00190 headersize = 14 + 40 + cmap_entries * 4;
00191 bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
00192
00193
00194 MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
00195 MEMZERO(bmpinfoheader, SIZEOF(bmpinfoheader));
00196
00197
00198 bmpfileheader[0] = 0x42;
00199 bmpfileheader[1] = 0x4D;
00200 PUT_4B(bmpfileheader, 2, bfSize);
00201
00202 PUT_4B(bmpfileheader, 10, headersize);
00203
00204
00205 PUT_2B(bmpinfoheader, 0, 40);
00206 PUT_4B(bmpinfoheader, 4, cinfo->output_width);
00207 PUT_4B(bmpinfoheader, 8, cinfo->output_height);
00208 PUT_2B(bmpinfoheader, 12, 1);
00209 PUT_2B(bmpinfoheader, 14, bits_per_pixel);
00210
00211
00212 if (cinfo->density_unit == 2) {
00213 PUT_4B(bmpinfoheader, 24, (INT32) (cinfo->X_density*100));
00214 PUT_4B(bmpinfoheader, 28, (INT32) (cinfo->Y_density*100));
00215 }
00216 PUT_2B(bmpinfoheader, 32, cmap_entries);
00217
00218
00219 if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
00220 ERREXIT(cinfo, JERR_FILE_WRITE);
00221 if (JFWRITE(dest->pub.output_file, bmpinfoheader, 40) != (size_t) 40)
00222 ERREXIT(cinfo, JERR_FILE_WRITE);
00223
00224 if (cmap_entries > 0)
00225 write_colormap(cinfo, dest, cmap_entries, 4);
00226 }
00227
00228
00229 LOCAL(void)
00230 write_os2_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
00231
00232 {
00233 char bmpfileheader[14];
00234 char bmpcoreheader[12];
00235 INT32 headersize, bfSize;
00236 int bits_per_pixel, cmap_entries;
00237
00238
00239 if (cinfo->out_color_space == JCS_RGB) {
00240 if (cinfo->quantize_colors) {
00241
00242 bits_per_pixel = 8;
00243 cmap_entries = 256;
00244 } else {
00245
00246 bits_per_pixel = 24;
00247 cmap_entries = 0;
00248 }
00249 } else {
00250
00251 bits_per_pixel = 8;
00252 cmap_entries = 256;
00253 }
00254
00255 headersize = 14 + 12 + cmap_entries * 3;
00256 bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
00257
00258
00259 MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
00260 MEMZERO(bmpcoreheader, SIZEOF(bmpcoreheader));
00261
00262
00263 bmpfileheader[0] = 0x42;
00264 bmpfileheader[1] = 0x4D;
00265 PUT_4B(bmpfileheader, 2, bfSize);
00266
00267 PUT_4B(bmpfileheader, 10, headersize);
00268
00269
00270 PUT_2B(bmpcoreheader, 0, 12);
00271 PUT_2B(bmpcoreheader, 4, cinfo->output_width);
00272 PUT_2B(bmpcoreheader, 6, cinfo->output_height);
00273 PUT_2B(bmpcoreheader, 8, 1);
00274 PUT_2B(bmpcoreheader, 10, bits_per_pixel);
00275
00276 if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
00277 ERREXIT(cinfo, JERR_FILE_WRITE);
00278 if (JFWRITE(dest->pub.output_file, bmpcoreheader, 12) != (size_t) 12)
00279 ERREXIT(cinfo, JERR_FILE_WRITE);
00280
00281 if (cmap_entries > 0)
00282 write_colormap(cinfo, dest, cmap_entries, 3);
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 LOCAL(void)
00292 write_colormap (j_decompress_ptr cinfo, bmp_dest_ptr dest,
00293 int map_colors, int map_entry_size)
00294 {
00295 JSAMPARRAY colormap = cinfo->colormap;
00296 int num_colors = cinfo->actual_number_of_colors;
00297 FILE * outfile = dest->pub.output_file;
00298 int i;
00299
00300 if (colormap != NULL) {
00301 if (cinfo->out_color_components == 3) {
00302
00303 for (i = 0; i < num_colors; i++) {
00304 putc(GETJSAMPLE(colormap[2][i]), outfile);
00305 putc(GETJSAMPLE(colormap[1][i]), outfile);
00306 putc(GETJSAMPLE(colormap[0][i]), outfile);
00307 if (map_entry_size == 4)
00308 putc(0, outfile);
00309 }
00310 } else {
00311
00312 for (i = 0; i < num_colors; i++) {
00313 putc(GETJSAMPLE(colormap[0][i]), outfile);
00314 putc(GETJSAMPLE(colormap[0][i]), outfile);
00315 putc(GETJSAMPLE(colormap[0][i]), outfile);
00316 if (map_entry_size == 4)
00317 putc(0, outfile);
00318 }
00319 }
00320 } else {
00321
00322 for (i = 0; i < 256; i++) {
00323 putc(i, outfile);
00324 putc(i, outfile);
00325 putc(i, outfile);
00326 if (map_entry_size == 4)
00327 putc(0, outfile);
00328 }
00329 }
00330
00331 if (i > map_colors)
00332 ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, i);
00333 for (; i < map_colors; i++) {
00334 putc(0, outfile);
00335 putc(0, outfile);
00336 putc(0, outfile);
00337 if (map_entry_size == 4)
00338 putc(0, outfile);
00339 }
00340 }
00341
00342
00343 METHODDEF(void)
00344 finish_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
00345 {
00346 bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
00347 register FILE * outfile = dest->pub.output_file;
00348 JSAMPARRAY image_ptr;
00349 register JSAMPROW data_ptr;
00350 JDIMENSION row;
00351 register JDIMENSION col;
00352 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
00353
00354
00355 if (dest->is_os2)
00356 write_os2_header(cinfo, dest);
00357 else
00358 write_bmp_header(cinfo, dest);
00359
00360
00361 for (row = cinfo->output_height; row > 0; row--) {
00362 if (progress != NULL) {
00363 progress->pub.pass_counter = (long) (cinfo->output_height - row);
00364 progress->pub.pass_limit = (long) cinfo->output_height;
00365 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
00366 }
00367 image_ptr = (*cinfo->mem->access_virt_sarray)
00368 ((j_common_ptr) cinfo, dest->whole_image, row-1, (JDIMENSION) 1, FALSE);
00369 data_ptr = image_ptr[0];
00370 for (col = dest->row_width; col > 0; col--) {
00371 putc(GETJSAMPLE(*data_ptr), outfile);
00372 data_ptr++;
00373 }
00374 }
00375 if (progress != NULL)
00376 progress->completed_extra_passes++;
00377
00378
00379 fflush(outfile);
00380 if (ferror(outfile))
00381 ERREXIT(cinfo, JERR_FILE_WRITE);
00382 }
00383
00384
00385
00386
00387
00388
00389 GLOBAL(djpeg_dest_ptr)
00390 jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2)
00391 {
00392 bmp_dest_ptr dest;
00393 JDIMENSION row_width;
00394
00395
00396 dest = (bmp_dest_ptr)
00397 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00398 SIZEOF(bmp_dest_struct));
00399 dest->pub.start_output = start_output_bmp;
00400 dest->pub.finish_output = finish_output_bmp;
00401 dest->is_os2 = is_os2;
00402
00403 if (cinfo->out_color_space == JCS_GRAYSCALE) {
00404 dest->pub.put_pixel_rows = put_gray_rows;
00405 } else if (cinfo->out_color_space == JCS_RGB) {
00406 if (cinfo->quantize_colors)
00407 dest->pub.put_pixel_rows = put_gray_rows;
00408 else
00409 dest->pub.put_pixel_rows = put_pixel_rows;
00410 } else {
00411 ERREXIT(cinfo, JERR_BMP_COLORSPACE);
00412 }
00413
00414
00415 jpeg_calc_output_dimensions(cinfo);
00416
00417
00418 row_width = cinfo->output_width * cinfo->output_components;
00419 dest->data_width = row_width;
00420 while ((row_width & 3) != 0) row_width++;
00421 dest->row_width = row_width;
00422 dest->pad_bytes = (int) (row_width - dest->data_width);
00423
00424
00425 dest->whole_image = (*cinfo->mem->request_virt_sarray)
00426 ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
00427 row_width, cinfo->output_height, (JDIMENSION) 1);
00428 dest->cur_output_row = 0;
00429 if (cinfo->progress != NULL) {
00430 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
00431 progress->total_extra_passes++;
00432 }
00433
00434
00435 dest->pub.buffer = (*cinfo->mem->alloc_sarray)
00436 ((j_common_ptr) cinfo, JPOOL_IMAGE, row_width, (JDIMENSION) 1);
00437 dest->pub.buffer_height = 1;
00438
00439 return (djpeg_dest_ptr) dest;
00440 }
00441
00442 #endif