1 Unit wrbmp;
2
3 { Copyright (C) 1994-1996, Thomas G. Lane.
4 This code contributed by James Arthur Boucher.
5
6 This file contains routines to write output images in Microsoft "BMP"
7 format (MS Windows 3.x and OS/2 1.x flavors).
8 Either 8-bit colormapped or 24-bit full-color format can be written.
9 No compression is supported. }
10
11 interface
12
13 {$I jconfig.inc}
14
15 uses
16 jmorecfg,
17 jpeglib,
18 jinclude,
19 jdeferr,
20 jerror,
21 jdmaster,
22 cdjpeg; { Common decls for cjpeg/djpeg applications }
23
24 { The module selection routine for BMP format output. }
25
26 {GLOBAL}
jinit_write_bmpnull27 function jinit_write_bmp (cinfo : j_decompress_ptr;
28 is_os2 : boolean) : djpeg_dest_ptr;
29
30 implementation
31
32 { To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
33 This is not yet implemented. }
34
35 {$ifndef BITS_IN_JSAMPLE_IS_8}
36 Sorry, this code only copes with 8-bit JSAMPLEs. { deliberate syntax err }
37 {$endif}
38
39 { Since BMP stores scanlines bottom-to-top, we have to invert the image
40 from JPEG's top-to-bottom order. To do this, we save the outgoing data
41 in a virtual array during put_pixel_row calls, then actually emit the
42 BMP file during finish_output. The virtual array contains one JSAMPLE per
43 pixel if the output is grayscale or colormapped, three if it is full color.}
44
45 { Private version of data destination object }
46
47 type
48 bmp_dest_ptr = ^bmp_dest_struct;
49 bmp_dest_struct = record
50 pub : djpeg_dest_struct; { public fields }
51
52 is_os2 : boolean; { saves the OS2 format request flag }
53
54 whole_image : jvirt_sarray_ptr; { needed to reverse row order }
55 data_width : JDIMENSION; { JSAMPLEs per row }
56 row_width : JDIMENSION; { physical width of one row in the BMP file }
57 pad_bytes : int; { number of padding bytes needed per row }
58 cur_output_row : JDIMENSION; { next row# to write to virtual array }
59 end;
60
61 { Forward declarations }
62 {LOCAL}
63 procedure write_colormap(cinfo : j_decompress_ptr;
64 dest : bmp_dest_ptr;
65 map_colors : int;
66 map_entry_size : int); forward;
67
68 { Write some pixel data.
69 In this module rows_supplied will always be 1. }
70
71 {METHODDEF}
72 procedure put_pixel_rows (cinfo : j_decompress_ptr;
73 dinfo : djpeg_dest_ptr;
74 rows_supplied : JDIMENSION); far;
75 { This version is for writing 24-bit pixels }
76 var
77 dest : bmp_dest_ptr;
78 image_ptr : JSAMPARRAY;
79 {register} inptr : JSAMPLE_PTR;
80 outptr : BGRptr;
81 {register} col : JDIMENSION;
82 pad : int;
83 begin
84 dest := bmp_dest_ptr (dinfo);
85
86 { Access next row in virtual array }
87 image_ptr := cinfo^.mem^.access_virt_sarray
88 (j_common_ptr(cinfo), dest^.whole_image,
89 dest^.cur_output_row, JDIMENSION (1), TRUE);
90 Inc(dest^.cur_output_row);
91
92
93 { Transfer data. Note destination values must be in BGR order
94 (even though Microsoft's own documents say the opposite). }
95
96 inptr := JSAMPLE_PTR(dest^.pub.buffer^[0]);
97 outptr := BGRptr(image_ptr^[0]);
98 for col := pred(cinfo^.output_width) downto 0 do
99 begin
100 outptr^.r := inptr^; { can omit GETJSAMPLE() safely }
101 Inc(inptr);
102 outptr^.g := inptr^;
103 Inc(inptr);
104 outptr^.b := inptr^;
105 Inc(inptr);
106 Inc(outptr);
107 end;
108
109 { Zero out the pad bytes. }
110 pad := dest^.pad_bytes;
111 while (pad > 0) do
112 begin
113 Dec(pad);
114 JSAMPLE_PTR(outptr)^ := 0;
115 Inc(JSAMPLE_PTR(outptr));
116 end;
117 end;
118
119 {METHODDEF}
120 procedure put_gray_rows (cinfo : j_decompress_ptr;
121 dinfo : djpeg_dest_ptr;
122 rows_supplied : JDIMENSION); far;
123 { This version is for grayscale OR quantized color output }
124 var
125 dest : bmp_dest_ptr;
126 image_ptr : JSAMPARRAY;
127 {register} inptr, outptr : JSAMPLE_PTR;
128 {register} col : JDIMENSION;
129 pad : int;
130 begin
131 dest := bmp_dest_ptr (dinfo);
132
133 { Access next row in virtual array }
134 image_ptr := cinfo^.mem^.access_virt_sarray
135 (j_common_ptr(cinfo), dest^.whole_image,
136 dest^.cur_output_row, JDIMENSION (1), TRUE);
137 Inc(dest^.cur_output_row);
138
139 { Transfer data. }
140 inptr := JSAMPLE_PTR(dest^.pub.buffer^[0]);
141 outptr := JSAMPLE_PTR(image_ptr^[0]);
142 for col := pred(cinfo^.output_width) downto 0 do
143 begin
144 outptr^ := inptr^; { can omit GETJSAMPLE() safely }
145 Inc(outptr);
146 Inc(inptr);
147 end;
148
149 { Zero out the pad bytes. }
150 pad := dest^.pad_bytes;
151 while (pad > 0) do
152 begin
153 Dec(pad);
154 outptr^ := 0;
155 Inc(outptr);
156 end;
157 end;
158
159
160 { Startup: normally writes the file header.
161 In this module we may as well postpone everything until finish_output. }
162
163 {METHODDEF}
164 procedure start_output_bmp (cinfo : j_decompress_ptr;
165 dinfo : djpeg_dest_ptr); far;
166 begin
167 { no work here }
168 end;
169
170
171 { Finish up at the end of the file.
172
173 Here is where we really output the BMP file.
174
175 First, routines to write the Windows and OS/2 variants of the file header. }
176
177
178 {LOCAL}
179 procedure write_bmp_header (cinfo : j_decompress_ptr;
180 dest : bmp_dest_ptr);
181 { Write a Windows-style BMP file header, including colormap if needed }
182 var
183 bmpfileheader : packed array[0..14-1] of byte;
184 bmpinfoheader : packed array[0..40-1] of byte;
185 var
186 headersize, bfSize : INT32 ;
187 bits_per_pixel, cmap_entries : int;
188 begin
189 { Compute colormap size and total file size }
190 if (cinfo^.out_color_space = JCS_RGB) then
191 begin
192 if (cinfo^.quantize_colors) then
193 begin
194 { Colormapped RGB }
195 bits_per_pixel := 8;
196 cmap_entries := 256;
197 end
198 else
199 begin
200 { Unquantized, full color RGB }
201 bits_per_pixel := 24;
202 cmap_entries := 0;
203 end;
204 end
205 else
206 begin
207 { Grayscale output. We need to fake a 256-entry colormap. }
208 bits_per_pixel := 8;
209 cmap_entries := 256;
210 end;
211 { File size }
212 headersize := 14 + 40 + cmap_entries * 4; { Header and colormap }
213 bfSize := headersize + INT32 (dest^.row_width) * INT32 (cinfo^.output_height);
214
215 { Set unused fields of header to 0 }
216 MEMZERO(@bmpfileheader, SIZEOF(bmpfileheader));
217 MEMZERO(@bmpinfoheader, SIZEOF(bmpinfoheader));
218
219 { Fill the file header }
220 bmpfileheader[0] := $42; { first 2 bytes are ASCII 'B', 'M' }
221 bmpfileheader[1] := $4D;
222 {PUT_4B(bmpfileheader, 2, bfSize);} { bfSize }
223 bmpfileheader[2] := byte ((bfSize) and $FF);
224 bmpfileheader[2+1] := byte (((bfSize) shr 8) and $FF);
225 bmpfileheader[2+2] := byte (((bfSize) shr 16) and $FF);
226 bmpfileheader[2+3] := byte (((bfSize) shr 24) and $FF);
227 { we leave bfReserved1 & bfReserved2 = 0 }
228 {PUT_4B(bmpfileheader, 10, headersize);} { bfOffBits }
229 bmpfileheader[10] := byte (headersize and $FF);
230 bmpfileheader[10+1] := byte ((headersize shr 8) and $FF);
231 bmpfileheader[10+2] := byte ((headersize shr 16) and $FF);
232 bmpfileheader[10+3] := byte ((headersize shr 24) and $FF);
233
234 { Fill the info header (Microsoft calls this a BITMAPINFOHEADER) }
235 {PUT_2B(bmpinfoheader, 0, 40);} { biSize }
236 bmpinfoheader[0] := byte ((40) and $FF);
237 bmpinfoheader[0+1] := byte (((40) shr 8) and $FF);
238
239 {PUT_4B(bmpinfoheader, 4, cinfo^.output_width);} { biWidth }
240 bmpinfoheader[4] := byte ((cinfo^.output_width) and $FF);
241 bmpinfoheader[4+1] := byte ((cinfo^.output_width shr 8) and $FF);
242 bmpinfoheader[4+2] := byte ((cinfo^.output_width shr 16) and $FF);
243 bmpinfoheader[4+3] := byte ((cinfo^.output_width shr 24) and $FF);
244 {PUT_4B(bmpinfoheader, 8, cinfo^.output_height);} { biHeight }
245 bmpinfoheader[8] := byte (cinfo^.output_height and $FF);
246 bmpinfoheader[8+1] := byte ((cinfo^.output_height shr 8) and $FF);
247 bmpinfoheader[8+2] := byte ((cinfo^.output_height shr 16) and $FF);
248 bmpinfoheader[8+3] := byte ((cinfo^.output_height shr 24) and $FF);
249 {PUT_2B(bmpinfoheader, 12, 1);} { biPlanes - must be 1 }
250 bmpinfoheader[12] := byte (1 and $FF);
251 bmpinfoheader[12+1] := byte ((1 shr 8) and $FF);
252
253 {PUT_2B(bmpinfoheader, 14, bits_per_pixel);} { biBitCount }
254 bmpinfoheader[14] := byte (bits_per_pixel and $FF);
255 bmpinfoheader[14+1] := byte ((bits_per_pixel shr 8) and $FF);
256 { we leave biCompression = 0, for none }
257 { we leave biSizeImage = 0; this is correct for uncompressed data }
258 if (cinfo^.density_unit = 2) then
259 begin { if have density in dots/cm, then }
260 {PUT_4B(bmpinfoheader, 24, INT32 (cinfo^.X_density*100));} { XPels/M }
261 bmpinfoheader[24] := byte (INT32 (cinfo^.X_density*100) and $FF);
262 bmpinfoheader[24+1] := byte ((INT32 (cinfo^.X_density*100) shr 8) and $FF);
263 bmpinfoheader[24+2] := byte ((INT32 (cinfo^.X_density*100) shr 16) and $FF);
264 bmpinfoheader[24+3] := byte ((INT32 (cinfo^.X_density*100) shr 24) and $FF);
265 {PUT_4B(bmpinfoheader, 28, INT32 (cinfo^.Y_density*100));} { XPels/M }
266 bmpinfoheader[28] := byte (INT32 (cinfo^.Y_density*100) and $FF);
267 bmpinfoheader[28+1] := byte ((INT32 (cinfo^.Y_density*100) shr 8) and $FF);
268 bmpinfoheader[28+2] := byte ((INT32 (cinfo^.Y_density*100) shr 16) and $FF);
269 bmpinfoheader[28+3] := byte ((INT32 (cinfo^.Y_density*100) shr 24) and $FF);
270 end;
271 {PUT_2B(bmpinfoheader, 32, cmap_entries);} { biClrUsed }
272 bmpinfoheader[32] := byte (cmap_entries and $FF);
273 bmpinfoheader[32+1] := byte ((cmap_entries shr 8) and $FF);
274 { we leave biClrImportant := 0 }
275
276 if (JFWRITE(dest^.pub.output_file, @bmpfileheader, 14) <> size_t (14)) then
277 ERREXIT(j_common_ptr(cinfo), JERR_FILE_WRITE);
278 if (JFWRITE(dest^.pub.output_file, @bmpinfoheader, 40) <> size_t (40)) then
279 ERREXIT(j_common_ptr(cinfo), JERR_FILE_WRITE);
280
281 if (cmap_entries > 0) then
282 write_colormap(cinfo, dest, cmap_entries, 4);
283 end;
284
285
286 {LOCAL}
287 procedure write_os2_header (cinfo : j_decompress_ptr;
288 dest : bmp_dest_ptr);
289 { Write an OS2-style BMP file header, including colormap if needed }
290 var
291 bmpfileheader : array[0..14-1] of byte;
292 bmpcoreheader : array[0..12-1] of byte;
293 headersize, bfSize : INT32;
294 bits_per_pixel, cmap_entries : int;
295 begin
296 { Compute colormap size and total file size }
297 if (cinfo^.out_color_space = JCS_RGB) then
298 begin
299 if (cinfo^.quantize_colors) then
300 begin
301 { Colormapped RGB }
302 bits_per_pixel := 8;
303 cmap_entries := 256;
304 end
305 else
306 begin
307 { Unquantized, full color RGB }
308 bits_per_pixel := 24;
309 cmap_entries := 0;
310 end;
311 end
312 else
313 begin
314 { Grayscale output. We need to fake a 256-entry colormap. }
315 bits_per_pixel := 8;
316 cmap_entries := 256;
317 end;
318 { File size }
319 headersize := 14 + 12 + cmap_entries * 3; { Header and colormap }
320 bfSize := headersize + INT32 (dest^.row_width) * INT32 (cinfo^.output_height);
321
322 { Set unused fields of header to 0 }
323 MEMZERO(@bmpfileheader, SIZEOF(bmpfileheader));
324 MEMZERO(@bmpcoreheader, SIZEOF(bmpcoreheader));
325
326 { Fill the file header }
327 bmpfileheader[0] := $42; { first 2 bytes are ASCII 'B', 'M' }
328 bmpfileheader[1] := $4D;
329 {PUT_4B(bmpfileheader, 2, bfSize);} { bfSize }
330 bmpfileheader[2] := byte ((bfSize) and $FF);
331 bmpfileheader[2+1] := byte (((bfSize) shr 8) and $FF);
332 bmpfileheader[2+2] := byte (((bfSize) shr 16) and $FF);
333 bmpfileheader[2+3] := byte (((bfSize) shr 24) and $FF);
334 { we leave bfReserved1 & bfReserved2 := 0 }
335 {PUT_4B(bmpfileheader, 10, headersize);} { bfOffBits }
336 bmpfileheader[10] := byte ((headersize) and $FF);
337 bmpfileheader[10+1] := byte (((headersize) shr 8) and $FF);
338 bmpfileheader[10+2] := byte (((headersize) shr 16) and $FF);
339 bmpfileheader[10+3] := byte (((headersize) shr 24) and $FF);
340
341 { Fill the info header (Microsoft calls this a BITMAPCOREHEADER) }
342 {PUT_2B(bmpcoreheader, 0, 12);} { bcSize }
343 bmpcoreheader[0] := byte (12 and $FF);
344 bmpcoreheader[0+1] := byte ((12 shr 8) and $FF);
345 {PUT_2B(bmpcoreheader, 4, cinfo^.output_width);} { bcWidth }
346 bmpcoreheader[4] := byte (cinfo^.output_width and $FF);
347 bmpcoreheader[4+1] := byte ((cinfo^.output_width shr 8) and $FF);
348 {PUT_2B(bmpcoreheader, 6, cinfo^.output_height);} { bcHeight }
349 bmpcoreheader[6] := byte (cinfo^.output_height and $FF);
350 bmpcoreheader[6+1] := byte ((cinfo^.output_height shr 8) and $FF);
351 {PUT_2B(bmpcoreheader, 8, 1);} { bcPlanes - must be 1 }
352 bmpcoreheader[8] := byte (1 and $FF);
353 bmpcoreheader[8+1] := byte ((1 shr 8) and $FF);
354 {PUT_2B(bmpcoreheader, 10, bits_per_pixel);} { bcBitCount }
355 bmpcoreheader[10] := byte (bits_per_pixel and $FF);
356 bmpcoreheader[10+1] := byte ((bits_per_pixel shr 8) and $FF);
357
358 if (JFWRITE(dest^.pub.output_file, @bmpfileheader, 14) <> size_t (14)) then
359 ERREXIT(j_common_ptr(cinfo), JERR_FILE_WRITE);
360 if (JFWRITE(dest^.pub.output_file, @bmpcoreheader, 12) <> size_t (12)) then
361 ERREXIT(j_common_ptr(cinfo), JERR_FILE_WRITE);
362
363 if (cmap_entries > 0) then
364 write_colormap(cinfo, dest, cmap_entries, 3);
365 end;
366
367
368 { Write the colormap.
369 Windows uses BGR0 map entries; OS/2 uses BGR entries. }
370
371 {LOCAL}
372 procedure write_colormap (cinfo : j_decompress_ptr;
373 dest : bmp_dest_ptr;
374 map_colors : int;
375 map_entry_size : int);
376 var
377 colormap : JSAMPARRAY;
378 num_colors : int;
379 outfile : FILEptr;
380 i : int;
381 var
382 output_color_map : Array[0..255] of BGRtype;
383 output_ext_color_map : Array[0..255] of record
384 b,g,r,a : byte;
385 end;
386 begin
387 colormap := cinfo^.colormap;
388 num_colors := cinfo^.actual_number_of_colors;
389 outfile := dest^.pub.output_file;
390
391 if (colormap <> NIL) then
392 begin
393 if (cinfo^.out_color_components = 3) then
394 begin
395 { Normal case with RGB colormap }
396 if (map_entry_size = 4) then
397 for i := 0 to pred(num_colors) do
398 with output_ext_color_map[i] do
399 begin
400 b := GETJSAMPLE(cinfo^.colormap^[2]^[i]);
401 g := GETJSAMPLE(cinfo^.colormap^[1]^[i]);
402 r := GETJSAMPLE(cinfo^.colormap^[0]^[i]);
403 a := 0;
404 end
405 else
406 for i := 0 to pred(num_colors) do
407 with output_color_map[i] do
408 begin
409 b := GETJSAMPLE(cinfo^.colormap^[2]^[i]);
410 g := GETJSAMPLE(cinfo^.colormap^[1]^[i]);
411 r := GETJSAMPLE(cinfo^.colormap^[0]^[i]);
412 end;
413 end
414 else
415 begin
416 { Grayscale colormap (only happens with grayscale quantization) }
417 if (map_entry_size = 4) then
418 for i := 0 to pred(num_colors) do
419 with output_ext_color_map[i] do
420 begin
421 b := GETJSAMPLE(cinfo^.colormap^[0]^[i]);
422 g := GETJSAMPLE(cinfo^.colormap^[0]^[i]);
423 r := GETJSAMPLE(cinfo^.colormap^[0]^[i]);
424 a := 0;
425 end
426 else
427 for i := 0 to pred(num_colors) do
428 with output_color_map[i] do
429 begin
430 b := GETJSAMPLE(cinfo^.colormap^[0]^[i]);
431 g := GETJSAMPLE(cinfo^.colormap^[0]^[i]);
432 r := GETJSAMPLE(cinfo^.colormap^[0]^[i]);
433 end;
434 end;
435 i := num_colors;
436 end
437 else
438 begin
439 { If no colormap, must be grayscale data. Generate a linear "map". }
440 { Nomssi: do not use "num_colors" here, it should be 0 }
441 if (map_entry_size = 4) then
442 for i := 0 to pred(256) do
443 with output_ext_color_map[i] do
444 begin
445 b := i;
446 g := i;
447 r := i;
448 a := 0;
449 end
450 else
451 for i := 0 to pred(256) do
452 with output_color_map[i] do
453 begin
454 b := i;
455 g := i;
456 r := i;
457 end;
458 i := 256;
459 end;
460 { Pad colormap with zeros to ensure specified number of colormap entries }
461
462 if (i > map_colors) then
463 ERREXIT1(j_common_ptr(cinfo), JERR_TOO_MANY_COLORS, i);
464 while (i < map_colors) do
465 begin
466 if (map_entry_size = 4) then
467 with output_ext_color_map[i] do
468 begin
469 b := 0;
470 g := 0;
471 r := 0;
472 a := 0;
473 end
474 else
475 with output_color_map[i] do
476 begin
477 b := 0;
478 g := 0;
479 r := 0;
480 end;
481 Inc(i);
482 end;
483 if (map_entry_size = 4) then
484 JFWRITE(outfile, @output_ext_color_map, map_colors*4)
485 else
486 JFWRITE(outfile, @output_color_map, map_colors*3);
487 end;
488
489
490 {METHODDEF}
491 procedure finish_output_bmp (cinfo : j_decompress_ptr;
492 dinfo : djpeg_dest_ptr); far;
493 var
494 dest : bmp_dest_ptr;
495 {register} outfile : FILEptr;
496 image_ptr : JSAMPARRAY;
497 {register} data_ptr : JSAMPLE_PTR;
498 row : JDIMENSION;
499 {register} { col : JDIMENSION; }
500 progress : cd_progress_ptr;
501 begin
502 dest := bmp_dest_ptr (dinfo);
503 outfile := dest^.pub.output_file;
504 progress := cd_progress_ptr (cinfo^.progress);
505
506 { Write the header and colormap }
507 if (dest^.is_os2) then
508 write_os2_header(cinfo, dest)
509 else
510 write_bmp_header(cinfo, dest);
511
512 { Write the file body from our virtual array }
513 for row := cinfo^.output_height downto 1 do
514 begin
515 if (progress <> NIL) then
516 begin
517 progress^.pub.pass_counter := long (cinfo^.output_height - row);
518 progress^.pub.pass_limit := long (cinfo^.output_height);
519 progress^.pub.progress_monitor (j_common_ptr(cinfo));
520 end;
521 image_ptr := cinfo^.mem^.access_virt_sarray
522 (j_common_ptr(cinfo), dest^.whole_image, row-1, JDIMENSION(1), FALSE);
523 data_ptr := JSAMPLE_PTR(image_ptr^[0]);
524 { Nomssi - This won't work for 12bit samples }
525 JFWRITE(outfile, data_ptr, dest^.row_width);
526 {
527 for col := pred(dest^.row_width) downto 0 do
528 begin
529 putc(GETJSAMPLE(data_ptr^), outfile);
530 Inc(data_ptr);
531 end;
532 }
533 end;
534 if (progress <> NIL) then
535 Inc(progress^.completed_extra_passes);
536
537 { Make sure we wrote the output file OK }
538 {fflush(outfile);
539 if (ferror(outfile)) then
540 ERREXIT(cinfo, JERR_FILE_WRITE);}
541 end;
542
543
544 { The module selection routine for BMP format output. }
545
546 {GLOBAL}
jinit_write_bmpnull547 function jinit_write_bmp (cinfo : j_decompress_ptr;
548 is_os2 : boolean) : djpeg_dest_ptr;
549 var
550 dest : bmp_dest_ptr;
551 row_width : JDIMENSION;
552 var
553 progress : cd_progress_ptr;
554 begin
555 { Create module interface object, fill in method pointers }
556 dest := bmp_dest_ptr (
557 cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
558 SIZEOF(bmp_dest_struct)) );
559 dest^.pub.start_output := start_output_bmp;
560 dest^.pub.finish_output := finish_output_bmp;
561 dest^.is_os2 := is_os2;
562
563 if (cinfo^.out_color_space = JCS_GRAYSCALE) then
564 begin
565 dest^.pub.put_pixel_rows := put_gray_rows;
566 end
567 else
568 if (cinfo^.out_color_space = JCS_RGB) then
569 begin
570 if (cinfo^.quantize_colors) then
571 dest^.pub.put_pixel_rows := put_gray_rows
572 else
573 dest^.pub.put_pixel_rows := put_pixel_rows;
574 end
575 else
576 ERREXIT(j_common_ptr(cinfo), JERR_BMP_COLORSPACE);
577
578 { Calculate output image dimensions so we can allocate space }
579 jpeg_calc_output_dimensions(cinfo);
580
581 { Determine width of rows in the BMP file (padded to 4-byte boundary). }
582 row_width := cinfo^.output_width * cinfo^.output_components;
583 dest^.data_width := row_width;
584 while ((row_width and 3) <> 0) do
585 Inc(row_width);
586 dest^.row_width := row_width;
587 dest^.pad_bytes := int (row_width - dest^.data_width);
588
589 { Allocate space for inversion array, prepare for write pass }
590 dest^.whole_image := cinfo^.mem^.request_virt_sarray
591 (j_common_ptr(cinfo), JPOOL_IMAGE, FALSE,
592 row_width, cinfo^.output_height, JDIMENSION (1));
593 dest^.cur_output_row := 0;
594 if (cinfo^.progress <> NIL) then
595 begin
596 progress := cd_progress_ptr (cinfo^.progress);
597 Inc(progress^.total_extra_passes); { count file input as separate pass }
598 end;
599
600 { Create decompressor output buffer. }
601 dest^.pub.buffer := cinfo^.mem^.alloc_sarray
602 (j_common_ptr(cinfo), JPOOL_IMAGE, row_width, JDIMENSION (1));
603 dest^.pub.buffer_height := 1;
604
605 jinit_write_bmp := djpeg_dest_ptr(dest);
606 end;
607
608 end. { BMP_SUPPORTED }
609