123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- Unit WrPPM;
- { wrppm.c
- Copyright (C) 1991-1996, Thomas G. Lane.
- This file is part of the Independent JPEG Group's software.
- For conditions of distribution and use, see the accompanying README file.
- This file contains routines to write output images in PPM/PGM format.
- The extended 2-byte-per-sample raw PPM/PGM formats are supported.
- The PBMPLUS library is NOT required to compile this software
- (but it is highly useful as a set of PPM image manipulation programs).
- These routines may need modification for non-Unix environments or
- specialized applications. As they stand, they assume output to
- an ordinary stdio stream. }
- interface
- {$I jconfig.inc}
- uses
- jdeferr,
- jmorecfg,
- jerror,
- jpeglib,
- jinclude,
- jdmaster,
- cdjpeg; { Common decls for cjpeg/djpeg applications }
- {GLOBAL}
- function jinit_write_ppm (cinfo : j_decompress_ptr) : djpeg_dest_ptr;
- implementation
- { For 12-bit JPEG data, we either downscale the values to 8 bits
- (to write standard byte-per-sample PPM/PGM files), or output
- nonstandard word-per-sample PPM/PGM files. Downscaling is done
- if PPM_NORAWWORD is defined (this can be done in the Makefile
- or in jconfig.h).
- (When the core library supports data precision reduction, a cleaner
- implementation will be to ask for that instead.) }
- type
- CharPtr = ^char;
- {$ifdef BITS_IN_JSAMPLE_IS_8}
- procedure PUTPPMSAMPLE(var ptr : CharPtr; v : byte);
- begin
- ptr^ := char(v);
- Inc(ptr);
- end;
- const
- BYTESPERSAMPLE = 1;
- PPM_MAXVAL = 255;
- {$else}
- {$ifdef PPM_NORAWWORD}
- procedure PUTPPMSAMPLE(var ptr : CharPtr; v : byte);
- begin
- ptr^ := char (v shr (BITS_IN_JSAMPLE-8));
- Inc(ptr);
- end;
- const
- BYTESPERSAMPLE = 1;
- PPM_MAXVAL = 255;
- {$else}
- { The word-per-sample format always puts the LSB first. }
- procedure PUTPPMSAMPLE(var ptr : CharPtr; v : int);
- var
- {register} val_ : int;
- begin
- val_ := v;
- ptr^ := char (val_ and $FF);
- Inc(ptr);
- ptr^ := char ((val_ shr 8) and $FF);
- Inc(ptr);
- end;
- const
- BYTESPERSAMPLE = 2;
- PPM_MAXVAL = (1 shl BITS_IN_JSAMPLE)-1;
- {$endif}
- {$endif}
- { When JSAMPLE is the same size as char, we can just fwrite() the
- decompressed data to the PPM or PGM file. On PCs, in order to make this
- work the output buffer must be allocated in near data space, because we are
- assuming small-data memory model wherein fwrite() can't reach far memory.
- If you need to process very wide images on a PC, you might have to compile
- in large-memory model, or else replace fwrite() with a putc() loop ---
- which will be much slower. }
- { Private version of data destination object }
- type
- ppm_dest_ptr = ^ppm_dest_struct;
- ppm_dest_struct = record
- pub : djpeg_dest_struct; { public fields }
- { Usually these two pointers point to the same place: }
- iobuffer : CharPtr; { fwrite's I/O buffer }
- pixrow : JSAMPROW; { decompressor output buffer }
- buffer_width : size_t; { width of I/O buffer }
- samples_per_row : JDIMENSION; { JSAMPLEs per output row }
- end;
- { Write some pixel data.
- In this module rows_supplied will always be 1.
- put_pixel_rows handles the "normal" 8-bit case where the decompressor
- output buffer is physically the same as the fwrite buffer. }
- {METHODDEF}
- procedure put_pixel_rows (cinfo : j_decompress_ptr;
- dinfo : djpeg_dest_ptr;
- rows_supplied : JDIMENSION); far;
- var
- dest : ppm_dest_ptr;
- begin
- dest := ppm_dest_ptr(dinfo);
- {void} JFWRITE(dest^.pub.output_file, dest^.iobuffer, dest^.buffer_width);
- end;
- { This code is used when we have to copy the data and apply a pixel
- format translation. Typically this only happens in 12-bit mode. }
- {METHODDEF}
- procedure copy_pixel_rows (cinfo : j_decompress_ptr;
- dinfo : djpeg_dest_ptr;
- rows_supplied : JDIMENSION); far;
- var
- dest : ppm_dest_ptr;
- {register} bufferptr : CharPtr;
- {register} ptr : JSAMPLE_PTR;
- {register} col : JDIMENSION;
- begin
- dest := ppm_dest_ptr(dinfo);
- ptr := JSAMPLE_PTR(dest^.pub.buffer^[0]);
- bufferptr := dest^.iobuffer;
- for col := pred(dest^.samples_per_row) downto 0 do
- begin
- PUTPPMSAMPLE(bufferptr, GETJSAMPLE(ptr^));
- Inc(ptr);
- end;
- {void} JFWRITE(dest^.pub.output_file, dest^.iobuffer, dest^.buffer_width);
- end;
- { Write some pixel data when color quantization is in effect.
- We have to demap the color index values to straight data. }
- {METHODDEF}
- procedure put_demapped_rgb (cinfo : j_decompress_ptr;
- dinfo : djpeg_dest_ptr;
- rows_supplied : JDIMENSION); far;
- var
- dest : ppm_dest_ptr;
- {register} bufferptr : CharPtr;
- {register} ptr : JSAMPLE_PTR;
- {register} col : JDIMENSION;
- {register} pixval : int;
- {register} color_map0 : JSAMPROW;
- {register} color_map1 : JSAMPROW;
- {register} color_map2 : JSAMPROW;
- begin
- dest := ppm_dest_ptr(dinfo);
- ptr := JSAMPLE_PTR(dest^.pub.buffer^[0]);
- bufferptr := dest^.iobuffer;
- color_map0 := cinfo^.colormap^[0];
- color_map1 := cinfo^.colormap^[1];
- color_map2 := cinfo^.colormap^[2];
- for col := pred(cinfo^.output_width) downto 0 do
- begin
- pixval := GETJSAMPLE(ptr^);
- Inc(ptr);
- PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map0^[pixval]));
- PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map1^[pixval]));
- PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map2^[pixval]));
- end;
- {void} JFWRITE(dest^.pub.output_file, dest^.iobuffer, dest^.buffer_width);
- end;
- {METHODDEF}
- procedure put_demapped_gray (cinfo : j_decompress_ptr;
- dinfo : djpeg_dest_ptr;
- rows_supplied : JDIMENSION); far;
- var
- dest : ppm_dest_ptr;
- {register} bufferptr : CharPtr;
- {register} ptr : JSAMPLE_PTR;
- {register} color_map : JSAMPROW;
- {register} col : JDIMENSION;
- begin
- dest := ppm_dest_ptr(dinfo);
- color_map := cinfo^.colormap^[0];
- ptr := JSAMPLE_PTR(dest^.pub.buffer^[0]);
- bufferptr := dest^.iobuffer;
- for col := pred(cinfo^.output_width) downto 0 do
- begin
- PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map^[GETJSAMPLE(ptr^)]));
- Inc(ptr);
- end;
- {void} JFWRITE(dest^.pub.output_file, dest^.iobuffer, dest^.buffer_width);
- end;
- { Startup: write the file header. }
- {METHODDEF}
- procedure start_output_ppm (cinfo : j_decompress_ptr;
- dinfo : djpeg_dest_ptr); far;
- const
- LF = #10;
- var
- dest : ppm_dest_ptr;
- var
- header : string[200];
- function LongToStr(l : long) : string;
- var
- helpstr : string[20];
- begin
- Str(l, helpstr);
- LongToStr := helpstr;
- end;
- begin
- dest := ppm_dest_ptr(dinfo);
- { Emit file header }
- case (cinfo^.out_color_space) of
- JCS_GRAYSCALE:
- begin
- { emit header for raw PGM format }
- header := 'P5'+LF+LongToStr(cinfo^.output_width)+' '+
- LongToStr(cinfo^.output_height)+LF+
- LongToStr(Long(PPM_MAXVAL)) + LF;
- JFWRITE(dest^.pub.output_file, @header[1], Length(header));
- end;
- JCS_RGB:
- begin
- { emit header for raw PPM format }
- header := 'P6'+LF+LongToStr(cinfo^.output_width)+' '+
- LongToStr(cinfo^.output_height)+LF+
- LongToStr(Long(PPM_MAXVAL)) + LF;
- JFWRITE(dest^.pub.output_file, @header[1], Length(header));
- end;
- else
- ERREXIT(j_common_ptr(cinfo), JERR_PPM_COLORSPACE);
- end;
- end;
- { Finish up at the end of the file. }
- {METHODDEF}
- procedure finish_output_ppm (cinfo : j_decompress_ptr;
- dinfo : djpeg_dest_ptr); far;
- begin
- { Make sure we wrote the output file OK }
- {Flush(dinfo^.output_file^);}
- if (IOresult <> 0) then
- ERREXIT(j_common_ptr(cinfo), JERR_FILE_WRITE);
- end;
- { The module selection routine for PPM format output. }
- {GLOBAL}
- function jinit_write_ppm (cinfo : j_decompress_ptr) : djpeg_dest_ptr;
- var
- dest : ppm_dest_ptr;
- begin
- { Create module interface object, fill in method pointers }
- dest := ppm_dest_ptr (
- cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
- SIZEOF(ppm_dest_struct)) );
- dest^.pub.start_output := start_output_ppm;
- dest^.pub.finish_output := finish_output_ppm;
- { Calculate output image dimensions so we can allocate space }
- jpeg_calc_output_dimensions(cinfo);
- { Create physical I/O buffer. Note we make this near on a PC. }
- dest^.samples_per_row := cinfo^.output_width * cinfo^.out_color_components;
- dest^.buffer_width := dest^.samples_per_row * (BYTESPERSAMPLE * SIZEOF(char));
- dest^.iobuffer := CharPtr( cinfo^.mem^.alloc_small
- (j_common_ptr(cinfo), JPOOL_IMAGE, dest^.buffer_width) );
- if (cinfo^.quantize_colors) or (BITS_IN_JSAMPLE <> 8) or
- (SIZEOF(JSAMPLE) <> SIZEOF(char)) then
- begin
- { When quantizing, we need an output buffer for colormap indexes
- that's separate from the physical I/O buffer. We also need a
- separate buffer if pixel format translation must take place. }
- dest^.pub.buffer := cinfo^.mem^.alloc_sarray
- (j_common_ptr(cinfo), JPOOL_IMAGE,
- cinfo^.output_width * cinfo^.output_components, JDIMENSION(1));
- dest^.pub.buffer_height := 1;
- if (not cinfo^.quantize_colors) then
- dest^.pub.put_pixel_rows := copy_pixel_rows
- else
- if (cinfo^.out_color_space = JCS_GRAYSCALE) then
- dest^.pub.put_pixel_rows := put_demapped_gray
- else
- dest^.pub.put_pixel_rows := put_demapped_rgb;
- end
- else
- begin
- { We will fwrite() directly from decompressor output buffer. }
- { Synthesize a JSAMPARRAY pointer structure }
- { Cast here implies near^.far pointer conversion on PCs }
- dest^.pixrow := JSAMPROW(dest^.iobuffer);
- dest^.pub.buffer := JSAMPARRAY (@dest^.pixrow);
- dest^.pub.buffer_height := 1;
- dest^.pub.put_pixel_rows := put_pixel_rows;
- end;
- jinit_write_ppm := djpeg_dest_ptr(dest);
- end;
- end.
|