📄 jpegfilt.pas
字号:
(*
Copyright (c) 1998-2007 by HiComponents. All rights reserved.
This software comes without express or implied warranty.
In no case shall the author be liable for any damage or unwanted behavior of any
computer hardware and/or software.
HiComponents grants you the right to include the compiled component
in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE,
BUT YOU MAY NOT DISTRIBUTE THIS SOURCE CODE OR ITS COMPILED .DCU IN ANY FORM.
ImageEn, IEvolution and ImageEn ActiveX may not be included in any commercial,
shareware or freeware libraries or components.
email: support@hicomponents.com
http://www.hicomponents.com
*)
unit jpegfilt;
{$R-}
{$Q-}
{$I ie.inc}
interface
uses Windows, Graphics, classes, sysutils, ImageEnProc, ImageEnIO, hyiedefs, hyieutils;
procedure ReadJPegStream(Stream: TStream; TableStream: TStream; Bitmap: TIEBitmap; var IOParams: TIOParamsVals; var xProgress: TProgressRec; Preview: boolean; Raw: boolean; ReadMetaTags:boolean; invertCMYK:boolean; freeICC:boolean; loadicc:boolean; MaxRows:integer);
procedure WriteJPegStream(Stream: TStream; bitmap: TIEBitmap; var IOParams: TIOParamsVals; var xProgress: TProgressRec);
function JpegTryStream(Stream: TStream): int64;
function IEJpegInjectIPTC(InputStream, OutputStream: TStream; iptc: TIEIPTCInfoList; var xProgress: TProgressRec): boolean;
function IEJpegInjectEXIF(InputStream, OutputStream: TStream; exif: TIOParamsVals; var xProgress: TProgressRec): boolean;
procedure IEJpegLosslessTransform(InStream, OutStream: TStream; var xProgress: TProgressRec; Transform: integer; GrayScale: boolean; CopyMarkers: integer; CutRect: TRect; updateEXIF:boolean);
function IEGetJpegQuality(InputStream: TStream; var QTables: pointer): integer;
function IEGetJpegLength(InputStream: TStream): integer;
procedure IEGetJpegICC(InputStream: TStream; Params: TIOParamsVals);
procedure IEJPEG_SetNextInput(cinfo:pointer; next_input_byte:pointer; bytes_in_buffer:integer);
function IEJPEG_CreateDecompStruct:pointer;
procedure IEJPEG_FreeDecompStruct(cinfo:pointer);
function IEJPEG_CreateErrMgr(cinfo:pointer):pointer;
procedure IEJPEG_FreeErrMgr(err:pointer);
procedure IEJPEG_CreateDecompress(cinfo:pointer);
procedure IEJPEG_DestroyDecompress(cinfo:pointer);
procedure IEJPEG_SetReadStream(cinfo:pointer; stream:TStream);
procedure IEJPEG_SetFillInputBuffer(cinfo:pointer; func:pointer);
procedure IEJPEG_ReadHeader(cinfo:pointer; reqimage:boolean);
procedure IEJPEG_StartDecompress(cinfo:pointer);
procedure IEJPEG_FinishDecompress(cinfo:pointer);
function IEJPEG_GetOutputWidth(cinfo:pointer):integer;
function IEJPEG_GetOutputHeight(cinfo:pointer):integer;
function IEJPEG_GetOutputComponents(cinfo:pointer):integer;
function IEJPEG_GetOutputScanline(cinfo:pointer):integer;
function IEJPEG_AllocSArray(cinfo:pointer; pool_id:integer; samplesperrow:cardinal; numrows:cardinal):pointer;
function IEJPEG_ReadScanlines(cinfo:pointer; scanlines: pointer; max_lines: cardinal):cardinal;
var
__turboFloat: LongBool = False;
const
M_SOF0 = $C0;
M_SOF1 = $C1;
M_SOF2 = $C2;
M_SOF3 = $C3;
M_SOF5 = $C5;
M_SOF6 = $C6;
M_SOF7 = $C7;
M_JPG = $C8;
M_SOF9 = $C9;
M_SOF10 = $CA;
M_SOF11 = $CB;
M_SOF13 = $CD;
M_SOF14 = $CE;
M_SOF15 = $CF;
M_DHT = $C4;
M_DAC = $CC;
M_RST0 = $D0;
M_RST1 = $D1;
M_RST2 = $D2;
M_RST3 = $D3;
M_RST4 = $D4;
M_RST5 = $D5;
M_RST6 = $D6;
M_RST7 = $D7;
M_SOI = $D8;
M_EOI = $D9;
M_SOS = $DA;
M_DQT = $DB;
M_DNL = $DC;
M_DRI = $DD;
M_DHP = $DE;
M_EXP = $DF;
M_APP0 = $E0;
M_APP1 = $E1;
M_APP2 = $E2;
M_APP3 = $E3;
M_APP4 = $E4;
M_APP5 = $E5;
M_APP6 = $E6;
M_APP7 = $E7;
M_APP8 = $E8;
M_APP9 = $E9;
M_APP10 = $EA;
M_APP11 = $EB;
M_APP12 = $EC;
M_APP13 = $ED;
M_APP14 = $EE;
M_APP15 = $EF;
M_JPG0 = $F0;
M_JPG1 = $F1;
M_JPG2 = $F2;
M_JPG3 = $F3;
M_JPG4 = $F4;
M_JPG5 = $F5;
M_JPG6 = $F6;
M_JPG7 = $F7;
M_JPG8 = $F8;
M_JPG9 = $F9;
M_JPG10 = $FA;
M_JPG11 = $FB;
M_JPG12 = $FC;
M_JPG13 = $FD;
M_COM = $FE;
M_TEM = $01;
M_BYPASS = $00;
implementation
uses ieview, imageenview;
{$R-}
{$Z4}
type
EIEJpegException = class(Exception);
const
JPEG_LIB_VERSION = 62; { Version 6b }
JPEG_RST0 = $D0; { RST0 marker code }
JPEG_EOI = $D9; { EOI marker code }
DCTSIZE = 8; { The basic DCT block is 8x8 samples }
DCTSIZE2 = 64; { DCTSIZE squared; # of elements in a block }
NUM_QUANT_TBLS = 4; { Quantization tables are numbered 0..3 }
NUM_HUFF_TBLS = 4; { Huffman tables are numbered 0..3 }
NUM_ARITH_TBLS = 16; { Arith-coding tables are numbered 0..15 }
MAX_COMPS_IN_SCAN = 4; { JPEG limit on # of components in one scan }
MAX_SAMP_FACTOR = 4; { JPEG limit on sampling factors }
C_MAX_BLOCKS_IN_MCU = 10; { compressor's limit on blocks per MCU }
D_MAX_BLOCKS_IN_MCU = 10; { decompressor's limit on blocks per MCU }
MAX_COMPONENTS = 10; { maximum number of image components (color channels) }
MAXJSAMPLE = 255;
CENTERJSAMPLE = 128;
type
JSAMPLE = byte;
GETJSAMPLE = integer;
JCOEF = integer;
JCOEF_PTR = ^JCOEF;
UINT8 = byte;
UINT16 = Word;
UINT = Cardinal;
INT16 = SmallInt;
INT32 = Integer;
INT32PTR = ^INT32;
JDIMENSION = Cardinal;
JOCTET = Byte;
jTOctet = 0..(MaxInt div SizeOf(JOCTET)) - 1;
JOCTET_FIELD = array[jTOctet] of JOCTET;
JOCTET_FIELD_PTR = ^JOCTET_FIELD;
JOCTETPTR = ^JOCTET;
JSAMPLE_PTR = ^JSAMPLE;
JSAMPROW_PTR = ^JSAMPROW;
jTSample = 0..(MaxInt div SIZEOF(JSAMPLE)) - 1;
JSAMPLE_ARRAY = array[jTSample] of JSAMPLE; {far}
JSAMPROW = ^JSAMPLE_ARRAY; { ptr to one image row of pixel samples. }
jTRow = 0..(MaxInt div SIZEOF(JSAMPROW)) - 1;
JSAMPROW_ARRAY = array[jTRow] of JSAMPROW;
JSAMPARRAY = ^JSAMPROW_ARRAY; { ptr to some rows (a 2-D sample array) }
jTArray = 0..(MaxInt div SIZEOF(JSAMPARRAY)) - 1;
JSAMP_ARRAY = array[jTArray] of JSAMPARRAY;
JSAMPIMAGE = ^JSAMP_ARRAY; { a 3-D sample array: top index is color }
const
CSTATE_START = 100; { after create_compress }
CSTATE_SCANNING = 101; { start_compress done, write_scanlines OK }
CSTATE_RAW_OK = 102; { start_compress done, write_raw_data OK }
CSTATE_WRCOEFS = 103; { jpeg_write_coefficients done }
DSTATE_START = 200; { after create_decompress }
DSTATE_INHEADER = 201; { reading header markers, no SOS yet }
DSTATE_READY = 202; { found SOS, ready for start_decompress }
DSTATE_PRELOAD = 203; { reading multiscan file in start_decompress}
DSTATE_PRESCAN = 204; { performing dummy pass for 2-pass quant }
DSTATE_SCANNING = 205; { start_decompress done, read_scanlines OK }
DSTATE_RAW_OK = 206; { start_decompress done, read_raw_data OK }
DSTATE_BUFIMAGE = 207; { expecting jpeg_start_output }
DSTATE_BUFPOST = 208; { looking for SOS/EOI in jpeg_finish_output }
DSTATE_RDCOEFS = 209; { reading file in jpeg_read_coefficients }
DSTATE_STOPPING = 210; { looking for EOI in jpeg_finish_decompress }
{ Known color spaces. }
type
J_COLOR_SPACE = (
JCS_UNKNOWN, { error/unspecified }
JCS_GRAYSCALE, { monochrome }
JCS_RGB, { red/green/blue }
JCS_YCbCr, { Y/Cb/Cr (also known as YUV) }
JCS_CMYK, { C/M/Y/K }
JCS_YCCK { Y/Cb/Cr/K }
);
{ DCT/IDCT algorithm options. }
type
J_DCT_METHOD = (
JDCT_ISLOW, { slow but accurate integer algorithm }
JDCT_IFAST, { faster, less accurate integer method }
JDCT_FLOAT { floating-point: accurate, fast on fast HW (Pentium)}
);
{ Dithering options for decompression. }
type
J_DITHER_MODE = (
JDITHER_NONE, { no dithering }
JDITHER_ORDERED, { simple ordered dither }
JDITHER_FS { Floyd-Steinberg error diffusion dither }
);
{ Error handler }
const
JMSG_LENGTH_MAX = 200; { recommended size of format_message buffer }
JMSG_STR_PARM_MAX = 80;
JPOOL_PERMANENT = 0; // lasts until master record is destroyed
JPOOL_IMAGE = 1; // lasts until done with image/datastream
type
// The script for encoding a multiple-scan file is an array of these:
jpeg_scan_info_ptr = ^jpeg_scan_info;
jpeg_scan_info = (*packed*) record
comps_in_scan: Integer; // number of components encoded in this scan
component_index: array[0..MAX_COMPS_IN_SCAN - 1] of Integer; // their SOF/comp_info[] indexes
Ss, Se: Integer; // progressive JPEG spectral selection parms
Ah, Al: Integer; // progressive JPEG successive approx. parms
end;
// The decompressor can save APPn and COM markers in a list of these:
jpeg_saved_marker_ptr = ^jpeg_marker_struct;
jpeg_marker_struct = (*packed*) record
next: jpeg_saved_marker_ptr; // next in list, or NULL
marker: UINT8; // marker code: JPEG_COM, or JPEG_APP0+n
original_length: UINT; // # bytes of data in the file
data_length: UINT; // # bytes of data saved at data[]
data: ^JOCTET; // the data contained in the marker
// the marker length word is not counted in data_length or original_length
end;
jpeg_error_mgr_ptr = ^jpeg_error_mgr;
jpeg_progress_mgr_ptr = ^jpeg_progress_mgr;
j_common_ptr = ^jpeg_common_struct;
j_compress_ptr = ^jpeg_compress_struct;
j_decompress_ptr = ^jpeg_decompress_struct;
{ Routine signature for application-supplied marker processing methods.
Need not pass marker code since it is stored in cinfo^.unread_marker. }
jpeg_marker_parser_method = function(cinfo: j_decompress_ptr): LongBool;
{ Marker reading & parsing }
jpeg_marker_reader_ptr = ^jpeg_marker_reader;
jpeg_marker_reader = (*packed*) record
reset_marker_reader: procedure(cinfo: j_decompress_ptr);
{ Read markers until SOS or EOI.
Returns same codes as are defined for jpeg_consume_input:
JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. }
read_markers: function(cinfo: j_decompress_ptr): Integer;
{ Read a restart marker --- exported for use by entropy decoder only }
read_restart_marker: jpeg_marker_parser_method;
{ Application-overridable marker processing methods }
process_COM: jpeg_marker_parser_method;
process_APPn: array[0..16 - 1] of jpeg_marker_parser_method;
{ State of marker reader --- nominally internal, but applications
supplying COM or APPn handlers might like to know the state. }
saw_SOI: LongBool; { found SOI? }
saw_SOF: LongBool; { found SOF? }
next_restart_num: Integer; { next restart number expected (0-7) }
discarded_bytes: UINT; { # of bytes skipped looking for a marker }
end;
{int8array = Array[0..8-1] of int;}
int8array = array[0..8 - 1] of Integer;
jpeg_error_mgr = (*packed*) record
{ Error exit handler: does not return to caller }
error_exit: procedure(cinfo: j_common_ptr);
{ Conditionally emit a trace or warning message }
emit_message: procedure(cinfo: j_common_ptr; msg_level: Integer);
{ Routine that actually outputs a trace or error message }
output_message: procedure(cinfo: j_common_ptr);
{ Format a message string for the most recent JPEG error or message }
format_message: procedure(cinfo: j_common_ptr; buffer: PChar);
{ Reset error state variables at start of a new image }
reset_error_mgr: procedure(cinfo: j_common_ptr);
{ The message ID code and any parameters are saved here.
A message can have one string parameter or up to 8 int parameters. }
msg_code: Integer;
msg_parm: (*packed*) record
case byte of
0: (i: int8array);
1: (s: string[JMSG_STR_PARM_MAX]);
end;
trace_level: Integer; { max msg_level that will be displayed }
num_warnings: Integer; { number of corrupt-data warnings }
// ImageEn specific
aborting: pboolean;
end;
{ Data destination object for compression }
jpeg_destination_mgr_ptr = ^jpeg_destination_mgr;
jpeg_destination_mgr = (*packed*) record
next_output_byte: JOCTETptr; { => next byte to write in buffer }
free_in_buffer: Longint; { # of byte spaces remaining in buffer }
init_destination: procedure(cinfo: j_compress_ptr);
empty_output_buffer: function(cinfo: j_compress_ptr): LongBool;
term_destination: procedure(cinfo: j_compress_ptr);
end;
{ Data source object for decompression }
jpeg_source_mgr_ptr = ^jpeg_source_mgr;
jpeg_source_mgr = (*packed*) record
next_input_byte: JOCTETptr; { => next byte to read from buffer }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -