📄 jpegfilt.pas
字号:
IOParams.JPEG_Progressive := cinfo.progressive_mode;
IOParams.JPEG_OriginalWidth := cinfo.image_width;
IOParams.JPEG_OriginalHeight := cinfo.image_height;
cinfo.scale_num := 1;
case IOParams.JPEG_Scale of
ioJPEG_FULLSIZE: cinfo.scale_denom := 1;
ioJPEG_HALF: cinfo.scale_denom := 2;
ioJPEG_QUARTER: cinfo.scale_denom := 4;
ioJPEG_EIGHTH: cinfo.scale_denom := 8;
ioJPEG_AUTOCALC:
begin
// Calc from IOParams.Width and IOParmas.Height
if (IOParams.Width > 0) and (IOParams.Height > 0) then
begin
bst := 0;
for xx := 3 downto 0 do
begin
dv := 1 shl xx;
if ((integer(cinfo.image_width) div dv) >= IOParams.Width) and ((integer(cinfo.image_height) div dv) >= IOParams.Height) then
begin
bst := xx;
break;
end;
end;
cinfo.scale_denom := 1 shl bst;
end
else
cinfo.scale_denom := 1;
end;
end;
IOParams.JPEG_Scale_Used := cinfo.scale_denom;
if Preview then
begin
IOParams.Width := cinfo.image_width;
IOParams.Height := cinfo.image_height;
exit;
end;
//
try
jpeg_start_decompress(cinfo);
except
xProgress.Aborting^ := true;
exit;
end;
if xProgress.Aborting^ then
exit;
IOParams.Width := cinfo.output_width;
IOParams.Height := cinfo.output_height;
getmem(buff, cinfo.output_width * 4);
if IOParams.IsNativePixelFormat then
begin
case cinfo.out_color_space of
JCS_GRAYSCALE: Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie8g);
JCS_RGB: Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie24RGB);
JCS_YCbCr: Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie24RGB);
JCS_CMYK: Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ieCMYK);
JCS_YCCK: Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie24RGB);
end;
end
else
Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie24RGB);
if MaxRows<0 then
MaxRows:=Bitmap.Height;
xProgress.per1 := 100 / cinfo.output_height;
xProgress.val := 0;
try
tlr := 0;
LinesRead := 1;
while (cinfo.output_scanline < cinfo.output_height) and (tlr<MaxRows) do
begin
DestScanline := Bitmap.Scanline[tlr];
case cinfo.out_color_space of
JCS_GRAYSCALE:
begin
if Bitmap.PixelFormat=ie8g then
LinesRead := jpeg_read_scanlines(cinfo, @DestScanline, 1)
else
begin
LinesRead := jpeg_read_scanlines(cinfo, @buff, 1);
xrgb:=DestScanline;
pb:=buff;
for xx:=0 to cinfo.output_width-1 do
begin
with xrgb^ do
begin
r:=pb^;
g:=pb^;
b:=pb^;
end;
inc(pb);
inc(xrgb);
end;
end;
end;
JCS_YCCK:
begin
// this should be never happens because YCCK is converted to CMYK
end;
JCS_YCbCr:
begin
if Raw then
begin
LinesRead := jpeg_read_scanlines(cinfo, @DestScanline, 1);
if cinfo.jpeg_color_space=JCS_RGB then
_BGR2RGB(PRGB(DestScanline), Bitmap.Width);
end;
end;
JCS_CMYK:
begin
if Bitmap.PixelFormat=ie24RGB then
begin
// convert CMYK->RGB
LinesRead := jpeg_read_scanlines(cinfo, @buff, 1);
if xProgress.Aborting^ then
break;
if invertCMYK then
begin
pb:=buff;
for xx:=0 to (cinfo.output_width-1)*4 do
begin
pb^:=255-pb^;
inc(pb);
end;
end;
IEConvertColorFunction(buff, iecmsCMYK, DestScanline, iecmsBGR, cinfo.output_width, IOParams);
end
else
begin
// native CMYK format
LinesRead := jpeg_read_scanlines(cinfo, @DestScanline, 1);
if xProgress.Aborting^ then
break;
end;
end;
JCS_RGB:
begin
if HasICC then
begin
LinesRead := jpeg_read_scanlines(cinfo, @buff, 1);
// 2.2.8
if cinfo.jpeg_color_space=JCS_RGB then
IEConvertColorFunction(buff, iecmsRGB, DestScanline, iecmsBGR, cinfo.output_width, IOParams)
else
IEConvertColorFunction(buff, iecmsBGR, DestScanline, iecmsBGR, cinfo.output_width, IOParams);
end
else
begin
LinesRead := jpeg_read_scanlines(cinfo, @DestScanline, 1);
if cinfo.jpeg_color_space=JCS_RGB then
_BGR2RGB(PRGB(DestScanline), Bitmap.Width);
end;
end;
end;
inc(tlr, LinesRead);
// OnProgress
with xProgress do
begin
inc(val, LinesRead);
if assigned(fOnProgress) then
fOnProgress(Sender, trunc(per1 * val));
end;
if xProgress.Aborting^ then
break;
end;
except
xProgress.Aborting^ := true;
exit;
end;
if tlr < MaxRows then
begin
xProgress.Aborting^ := true;
exit;
end;
finally
// save markers to IOParams.JPEG_MarkerList
IOParams.JPEG_MarkerList.Clear;
markers := cinfo.marker_list;
bo := false;
while markers <> nil do
begin
if (markers.marker <> JPEG_APP0) or bo then // this remove first APP0 (the header + RGB thumbnail)
IOParams.JPEG_MarkerList.AddMarker(markers.marker, pchar(markers.data), markers.data_length);
if markers.marker = JPEG_APP0 then
bo:=true;
markers := markers^.next;
end;
// ICC profile applied: free CMS transform and remove jpeg ICC markers
if freeICC and HasICC and (IOParams.InputICCProfile.IsTransforming) then
begin
IOParams.InputICCProfile.FreeTransform;
while true do
begin
i:=IOParams.JPEG_MarkerList.IndexOf( M_APP2 );
if i=-1 then
break;
IOParams.JPEG_MarkerList.DeleteMarker( i );
end;
end;
//
if (not xProgress.Aborting^) and not Preview then
begin
jerr.aborting := nil; // from this point decoder can't generate aborting
try
jpeg_finish_decompress(cinfo);
except
end;
end;
jpeg_destroy_decompress(cinfo);
if buff <> nil then
freemem(buff);
//
if cinfo.common.err.num_warnings <> 0 then
begin
IOParams.JPEG_WarningTot := cinfo.common.err.num_warnings;
IOParams.JPEG_WarningCode := cinfo.common.err.msg_code;
end;
jpeg_ie_src_free(@cinfo);
if ReadMetaTags then
begin
with IOParams.JPEG_MarkerList do
begin
// IPTC
mi := IndexOf(JPEG_APP13);
if mi >= 0 then
IOParams.IPTC_Info.LoadFromStandardBuffer(MarkerData[mi], MarkerLength[mi]);
// EXIF
mi := IndexOf(JPEG_APP1);
if mi >= 0 then
begin
// we saves current DPI because LoadEXIFFromStandardBuffer will change them
xdpi:=IOParams.DpiX;
ydpi:=IOParams.DpiY;
if LoadEXIFFromStandardBuffer(MarkerData[mi], MarkerLength[mi], IOParams) then
begin
// exif found
if (xdpi = 1) and (ydpi = 1) then
begin
// use dpi of the Exif
if IOParams.EXIF_ResolutionUnit = 3 then
dd := 2.54
else
dd := 1;
IOParams.DpiX := trunc(IOParams.EXIF_XResolution * dd);
IOParams.DpiY := trunc(IOParams.EXIF_YResolution * dd);
end
else
begin
IOParams.DpiX:=xdpi;
IOParams.DpiY:=ydpi;
end;
//IEChangeYCbCrCoefficients(Bitmap, 0.299,0.587,0.114, IOParams.EXIF_YCbCrCoefficients[0],IOParams.EXIF_YCbCrCoefficients[1],IOParams.EXIF_YCbCrCoefficients[2]);
if IOParams.JPEG_EnableAdjustOrientation then
IEAdjustEXIFOrientation(Bitmap,IOParams.EXIF_Orientation);
end;
end;
// XMP
for mi:=0 to Count-1 do
if (MarkerType[mi]=JPEG_APP1) and (IEFindXMPFromJpegTag(MarkerData[mi], MarkerLength[mi])<>nil) then
begin
IELoadXMPFromJpegTag(MarkerData[mi], MarkerLength[mi], IOParams);
break;
end;
end;
end;
end;
{$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
// write jpeg stream
procedure WriteJPegStream(Stream: TStream; bitmap: TIEBitmap; var IOParams: TIOParamsVals; var xProgress: TProgressRec);
var
cinfo: jpeg_compress_struct;
jerr: jpeg_error_mgr;
SrcScanLine: pbyte;
buff, xbuff: PRGB;
xrgb, yrgb: PRGB;
xx: integer;
LinesPerCall, LinesWritten: integer;
FreeW: boolean;
WBitmap: TIEBitmap;
colspc: J_COLOR_SPACE;
nullpr: TProgressRec;
tlr: integer;
begin
{$ifdef IEPROFILE} try IEProfileBegin('WriteJPegStream'); {$endif}
with nullpr do
begin
Aborting := xProgress.Aborting;
fOnProgress := nil;
Sender := nil;
end;
// adjust Bitmap
if Bitmap.PixelFormat <> ie24RGB then
begin
WBitmap := TIEBitmap.Create;
WBitmap.Assign(Bitmap);
WBitmap.PixelFormat := ie24RGB; // converts to 24bit
FreeW := true;
end
else
begin
WBitmap := Bitmap;
FreeW := false;
end;
//
buff := nil;
if (bitmap.Width = 0) or (bitmap.Height = 0) then
begin
xProgress.Aborting^ := true;
exit;
end;
jerr.aborting := xProgress.Aborting;
jerr := jpeg_std_error;
cinfo.common.err := @jerr;
jpeg_Create
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -