diff options
Diffstat (limited to 'packages/pasjpeg/examples/wrppm.pas')
-rw-r--r-- | packages/pasjpeg/examples/wrppm.pas | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/packages/pasjpeg/examples/wrppm.pas b/packages/pasjpeg/examples/wrppm.pas new file mode 100644 index 0000000000..adc336243c --- /dev/null +++ b/packages/pasjpeg/examples/wrppm.pas @@ -0,0 +1,335 @@ +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. |