📄 jpegfilt.pas
字号:
const
OUTPUT_BUF_SIZE = 65536;
procedure init_destination(cinfo: J_COMPRESS_PTR);
var
dest: PIEJPEGDESTMGR;
begin
{$ifdef IEPROFILE} try IEProfileBegin('init_destination'); {$endif}
dest := PIEJPEGDESTMGR(cinfo^.dest);
getmem(dest^.buffer, OUTPUT_BUF_SIZE * sizeof(JOCTET));
dest^.pub.next_output_byte := dest^.buffer;
dest^.pub.free_in_buffer := OUTPUT_BUF_SIZE;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
function empty_output_buffer(cinfo: J_COMPRESS_PTR): boolean;
var
dest: PIEJPEGDESTMGR;
begin
{$ifdef IEPROFILE} try IEProfileBegin('empty_output_buffer'); {$endif}
dest := PIEJPEGDESTMGR(cinfo^.dest);
if dest^.fs.write(pbyte(dest^.buffer)^, OUTPUT_BUF_SIZE) <> OUTPUT_BUF_SIZE then
if assigned(dest^.aborting) then
dest^.aborting^ := true;
dest^.pub.next_output_byte := dest^.buffer;
dest^.pub.free_in_buffer := OUTPUT_BUF_SIZE;
result := true;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
procedure term_destination(cinfo: J_COMPRESS_PTR);
var
dest: PIEJPEGDESTMGR;
datacount: integer;
begin
{$ifdef IEPROFILE} try IEProfileBegin('term_destination'); {$endif}
dest := PIEJPEGDESTMGR(cinfo^.dest);
datacount := OUTPUT_BUF_SIZE - dest^.pub.free_in_buffer;
if datacount > 0 then
begin
if dest^.fs.write(pbyte(dest^.buffer)^, datacount) <> datacount then
if assigned(dest^.aborting) then
dest^.aborting^ := true;
end;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
procedure jpeg_ie_dest(cinfo: J_COMPRESS_PTR; fs: TStream; aborting: pboolean);
var
dest: PIEJPEGDESTMGR;
begin
{$ifdef IEPROFILE} try IEProfileBegin('jpeg_ie_dest'); {$endif}
if cinfo^.dest = nil then
getmem(cinfo^.dest, sizeof(TIEJPEGDESTMGR));
dest := PIEJPEGDESTMGR(cinfo^.dest);
dest^.pub.init_destination := @init_destination;
dest^.pub.empty_output_buffer := @empty_output_buffer;
dest^.pub.term_destination := @term_destination;
dest^.fs := fs;
dest^.aborting := aborting;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
procedure jpeg_ie_dest_free(cinfo: J_COMPRESS_PTR);
var
dest: PIEJPEGDESTMGR;
begin
{$ifdef IEPROFILE} try IEProfileBegin('jpeg_ie_dest_free'); {$endif}
dest := PIEJPEGDESTMGR(cinfo^.dest);
freemem(dest^.buffer);
freemem(cinfo^.dest);
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
/////////////////////////////////////////////////////////////////////////////////////
// source manager
const
INPUT_BUF_SIZE = 65536;
procedure init_source(cinfo: J_DECOMPRESS_PTR);
var
src: PIEJPEGSOURCEMGR;
begin
{$ifdef IEPROFILE} try IEProfileBegin('init_source'); {$endif}
src := PIEJPEGSOURCEMGR(cinfo^.src);
src^.start_of_file := true;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
function fill_input_buffer(cinfo: J_DECOMPRESS_PTR): longbool;
var
src: PIEJPEGSOURCEMGR;
nbytes: integer;
begin
{$ifdef IEPROFILE} try IEProfileBegin('fill_input_buffer'); {$endif}
src := PIEJPEGSOURCEMGR(cinfo^.src);
nbytes := src^.fs.Read(pbyte(src^.buffer)^, INPUT_BUF_SIZE);
if nbytes <= 0 then
begin
if src^.start_of_file then
if assigned(src^.aborting) then
src^.aborting^ := true;
pbytearray(src^.buffer)^[0] := $FF;
pbytearray(src^.buffer)^[1] := JPEG_EOI;
nbytes := 2;
end;
src^.pub.next_input_byte := src^.buffer;
src^.pub.bytes_in_buffer := nbytes;
src^.start_of_file := false;
result := true;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
procedure skip_input_data(cinfo: J_DECOMPRESS_PTR; num_bytes: integer);
var
src: PIEJPEGSOURCEMGR;
begin
{$ifdef IEPROFILE} try IEProfileBegin('skip_input_data'); {$endif}
src := PIEJPEGSOURCEMGR(cinfo^.src);
if num_bytes > 0 then
begin
while num_bytes > src^.pub.bytes_in_buffer do
begin
dec(num_bytes, src^.pub.bytes_in_buffer);
fill_input_buffer(cinfo);
end;
inc(src^.pub.next_input_byte, num_bytes);
dec(src^.pub.bytes_in_buffer, num_bytes);
end;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
procedure term_source(cinfo: J_DECOMPRESS_PTR);
begin
end;
procedure jpeg_ie_src(cinfo: J_DECOMPRESS_PTR; fs: TStream; aborting: pboolean);
var
src: PIEJPEGSOURCEMGR;
begin
{$ifdef IEPROFILE} try IEProfileBegin('jpeg_ie_src'); {$endif}
if cinfo^.src = nil then
begin
getmem(cinfo^.src, sizeof(TIEJPEGSOURCEMGR));
src := PIEJPEGSOURCEMGR(cinfo^.src);
getmem(src^.buffer, INPUT_BUF_SIZE * sizeof(JOCTET));
end;
src := PIEJPEGSOURCEMGR(cinfo^.src);
src^.pub.init_source := init_source;
src^.pub.fill_input_buffer := fill_input_buffer;
src^.pub.skip_input_data := skip_input_data;
src^.pub.resync_to_restart := jpeg_resync_to_restart;
src^.pub.term_source := term_source;
src^.fs := fs;
src^.pub.bytes_in_buffer := 0;
src^.pub.next_input_byte := nil;
src^.aborting := aborting;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
procedure jpeg_ie_src_free(cinfo: J_DECOMPRESS_PTR);
var
src: PIEJPEGSOURCEMGR;
begin
{$ifdef IEPROFILE} try IEProfileBegin('jpeg_ie_src_free'); {$endif}
src := PIEJPEGSOURCEMGR(cinfo^.src);
if src <> nil then
begin
freemem(src^.buffer);
freemem(cinfo^.src);
end;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
/////////////////////////////////////////////////////////////////////////////////////////
// read stream jpeg
// TableStream contains Q tables. It is nil if all is inside Stream.
// Raw=true doesn't convert to RGB but get the original color format
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);
var
cinfo: jpeg_decompress_struct;
jerr: jpeg_error_mgr;
DestScanLine: pointer;
LinesRead: integer;
buff: pbyte;
pb:pbyte;
xrgb: PRGB;
//yrgb: PRGB;
xx: integer;
bo: boolean;
i, bst, dv: integer;
markers: jpeg_saved_marker_ptr;
spos: int64;
tlr: integer; // total lines read
mi: integer;
b1,b2:byte;
dd: double;
HasICC:boolean;
xdpi,ydpi:integer;
oWidth,oHeight:integer;
begin
{$ifdef IEPROFILE} try IEProfileBegin('ReadJPegStream'); {$endif}
if IOParams.JPEG_GetExifThumbnail then
begin
// try to load the EXIF thumbnail
if IOParams.EXIF_Bitmap<>nil then
IOParams.EXIF_Bitmap.FreeImage(true);
IOParams.JPEG_GetExifThumbnail:=false;
oWidth:=IOParams.Width; // save requested width because it is changed by ReadJpegStream
oHeight:=IOParams.Height;
ReadJpegStream(Stream,TableStream,Bitmap,IOParams,xProgress,true,Raw,true,invertCMYK,freeICC,false,-1); // 2.2.4rc2
Stream.Position:=0;
IOParams.JPEG_GetExifThumbnail:=true;
if assigned(IOParams.EXIF_Bitmap) and not IOParams.EXIF_Bitmap.IsEmpty then
begin
Bitmap.Assign( IOParams.EXIF_Bitmap );
// thumbnails should be already oriented
//if IOParams.EXIF_HasEXIFData and IOParams.JPEG_EnableAdjustOrientation then
// IEAdjustEXIFOrientation(Bitmap,IOParams.EXIF_Orientation);
exit;
end;
Stream.Position:=0;
IOParams.Width:=oWidth;
IOParams.Height:=oHeight;
end;
IOParams.JPEG_WarningTot := 0;
IOParams.JPEG_WarningCode := 0;
spos := JpegTryStream(Stream);
if spos = -1 then
begin
xProgress.Aborting^ := true;
exit;
end;
Stream.Position := spos;
// load ICC, if present
if loadicc then
IEGetJpegICC(Stream, IOParams);
HasICC:=assigned(IOParams) and assigned(IOParams.fInputICC) and iegEnableCMS;
try
buff := nil;
jerr := jpeg_std_error;
jerr.aborting := xProgress.Aborting;
cinfo.common.err := @jerr;
jpeg_CreateDecompress(cinfo, JPEG_LIB_VERSION, sizeof(cinfo));
if xProgress.Aborting^ then
exit;
if (TableStream <> nil) and (TableStream <> Stream) then
begin
// load tables from TableStream
jpeg_ie_src(@cinfo, TableStream, xProgress.Aborting);
jpeg_read_header(cinfo, FALSE);
end;
jpeg_ie_src(@cinfo, Stream, xProgress.Aborting);
if xProgress.Aborting^ then
exit;
try
jpeg_save_markers(cinfo, JPEG_COM, $FFFF);
for xx := JPEG_APP0 to JPEG_APP15 do
jpeg_save_markers(cinfo, xx, $FFFF);
jpeg_read_header(cinfo, TRUE);
except
xProgress.Aborting^ := true;
exit;
end;
//
if xProgress.Aborting^ then
exit;
IOParams.BitsPerSample := 8;
cinfo.out_color_space := cinfo.jpeg_color_space;
case cinfo.jpeg_color_space of
JCS_RGB:
begin
IOParams.JPEG_ColorSpace := ioJPEG_RGB;
IOParams.SamplesPerPixel := 3;
end;
JCS_GRAYSCALE:
begin
IOParams.JPEG_ColorSpace := ioJPEG_GRAYLEV;
IOParams.SamplesPerPixel := 1;
end;
JCS_YCbCr:
begin
IOParams.JPEG_ColorSpace := ioJPEG_YCbCr;
IOParams.SamplesPerPixel := 3;
cinfo.out_color_space := JCS_RGB;
end;
JCS_CMYK:
begin
IOParams.JPEG_ColorSpace := ioJPEG_CMYK;
IOParams.SamplesPerPixel := 4;
end;
JCS_YCCK:
begin
IOParams.JPEG_ColorSpace := ioJPEG_YCbCrK;
IOParams.SamplesPerPixel := 4;
cinfo.out_color_space := JCS_CMYK;
end;
end;
if Raw then
cinfo.out_color_space := JCS_YCbCr;
case IOParams.JPEG_DCTMethod of
ioJPEG_ISLOW: cinfo.dct_method := JDCT_ISLOW;
ioJPEG_IFAST: cinfo.dct_method := JDCT_IFAST;
ioJPEG_FLOAT: cinfo.dct_method := JDCT_FLOAT;
end;
case cinfo.density_unit of
0, 1: // unknown or inches
begin
IOParams.DpiX := cinfo.X_density;
IOParams.DpiY := cinfo.Y_density;
end;
2: // centimeters
begin
IOParams.DpiX := trunc(cinfo.X_density / 2.54);
IOParams.DpiY := trunc(cinfo.Y_density / 2.54);
end;
end;
if IOParams.ColorMap <> nil then
begin
freemem(IOParams.ColorMap);
IOParams.fColorMap := nil;
IOParams.fColorMapCount := 0;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -