unit UCutFigure_JPG;
//JPG 切图
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls,Math, jpeg
;
//向左旋转X度
procedure Rotate(Srcbmp, DestBmp: TBitmap; dbTheta: Double);
//毫米单位转换为英寸单位
function MmToInch(Length: Extended): Extended;
//英寸单位转换为毫米单位
function InchToMm(Length: Extended): Extended;
function CutFigure_JPG(图片文件名:string;旋转角度:integer;切边_上,切边_下,切边_左,切边_右:real;缩放_宽,缩放_高:real):Integer;
implementation
function CutFigure_JPG(图片文件名:string;旋转角度:integer;切边_上,切边_下,切边_左,切边_右:real;缩放_宽,缩放_高:real):Integer;
var
JpgSrc,JpgDest : TJpegImage;
BmpSrc, BmpDest: TBitmap;
F_上,F_下,F_左,F_右,F_长,F_宽:integer;//切边值
F_缩放比率:real;
F_处理状态:boolean;
begin
//文件名,含全路径
if not FileExists(图片文件名) then exit;//文件不存在则退出
JpgSrc := TJpegImage.Create;
JpgDest:=TJpegImage.Create ;
BmpSrc:=TBitmap.Create;
BmpDest:=TBitmap.Create ;
JpgSrc.LoadFromFile(图片文件名);//加载文件
BmpSrc.Assign(JpgSrc);
F_处理状态:=False;//未处理过
if 旋转角度>0 then
begin
Rotate(BmpSrc, BmpDest,旋转角度); //由于函数是左向旋转,所以这里角度设置为270。
F_处理状态:=true;
end;
if (切边_上>0) or (切边_下>0) or (切边_左>0) or (切边_右>0) then
begin
//需要切边
if F_处理状态=true then
BmpSrc.Assign(BmpDest);
//切边传进来的参数,为cm
if 切边_上<0 then 切边_上:=0;
if 切边_下<0 then 切边_下:=0;
if 切边_左<0 then 切边_左:=0;
if 切边_右<0 then 切边_右:=0;
F_上:=Round(MmToInch(切边_上)*10*96);
F_下:=Round(MmToInch(切边_下)*10*96);
F_左:=Round(MmToInch(切边_左)*10*96);
F_右:=Round(MmToInch(切边_右)*10*96);
if (F_上+F_下=BmpSrc.Width ) then
begin //值超范围,不处理
BmpDest.Height:=BmpSrc.Height-(F_上+F_下);
BmpDest.Width:=BmpSrc.Width-(F_左+F_右);
SetStretchBltMode(BmpDest.Canvas.Handle,HALFTONE);//设置指位图拉伸模式
stretchblt(BmpDest.Canvas.Handle,0,0,BmpDest.Width,BmpDest.Height,BmpSrc.Canvas.Handle,F_左,F_上,BmpDest.Width,BmpDest.Height,srccopy); //从源矩形中复制一个位图到目标矩形并适当压缩
F_处理状态:=true;
end ;
end;
if (缩放_高>0) or (缩放_宽>0) then
begin
//需要缩放
if F_处理状态=true then
BmpSrc.Assign(BmpDest);
F_长:=Round(MmToInch(缩放_高)*10*96);
F_宽:=Round(MmToInch(缩放_宽)*10*96);
if (F_长>0) and (F_宽>0) and (BmpSrc.Height>F_长) and (BmpSrc.Width >F_宽) then
begin
//如果都超过,则等比缩小到其中较大的一个值等于目标值
if (F_长/BmpSrc.Height)>(F_宽/BmpSrc.Width) then
begin
F_缩放比率:=F_宽/BmpSrc.Width;
end
else
begin
F_缩放比率:=F_长/BmpSrc.Height;
end;
end
else
if (F_长>0) and (BmpSrc.Height>F_长) then
begin
F_缩放比率:=F_长/BmpSrc.Height;
end
else
if (F_宽>0) and (BmpSrc.Width >F_宽) then
begin
F_缩放比率:=F_宽/BmpSrc.Width;
end
else
begin
F_缩放比率:=-1;//如果没取到值,或原图已经小于设定值则不处理
end;
if F_缩放比率>0 then
begin
BmpDest.Height:=Round(BmpSrc.Height*F_缩放比率);
BmpDest.Width:=Round(BmpSrc.Width *F_缩放比率);
SetStretchBltMode(BmpDest.Canvas.Handle,HALFTONE);//设置指位图拉伸模式
stretchblt(BmpDest.Canvas.Handle,0,0,BmpDest.Width,BmpDest.Height,BmpSrc.Canvas.Handle,0,0,BmpSrc.Width,BmpSrc.Height,srccopy); //从源矩形中复制一个位图到目标矩形并适当压缩
F_处理状态:=true;
end;
end;
if F_处理状态=true then
begin
//处理后,保存图片
JpgDest.CompressionQuality := 100;
JpgDest.Assign(BmpDest);
JpgDest.SaveToFile(图片文件名);
end;
JpgSrc.Free;
JpgDest.free;
BmpSrc.Free;
BmpDest.Free;
end;
procedure Rotate(Srcbmp, DestBmp: TBitmap; dbTheta: Double);//此过程是网上找的,不记得原博文地址了,抱歉
var
ptOrgCenter, ptTarCenter, ptc: TPoint;
pta: array[0..3] of TPoint;
ba: array[0..3] of integer;
i: integer;
function RotateXY(dbTheda: double; p1: TPoint): TPoint;
var
dbA: double;
_cosA, _sinA, _dbLastT: double;
begin
_dbLastT := -99999.999;
_cosA :=0.0;
_sinA :=0.0;
if dbTheda <> _dbLastT then
begin
dbA := dbTheda * Pi / 180;
_sinA := sin(dbA);
_cosA := cos(dbA);
_dbLastT := dbTheda;
end;
Result.x := round(p1.x * _cosA + p1.y * _sinA);
Result.y := round(-p1.x * _sinA + p1.y * _cosA);
end;
begin
ptOrgCenter.x := Srcbmp.Width div 2;
ptOrgCenter.y := Srcbmp.Height div 2;
pta[0] := RotateXY(dbTheta,Point(0, 0));
//这里不知道原来为何减1
{pta[1]:=RotateXY(dbTheta,Point(Srcbmp.Width - 1, 0));
pta[2]:=RotateXY(dbTheta,Point(0, Srcbmp.Height - 1));
pta[3]:=RotateXY(dbTheta,Point(Srcbmp.Width - 1, Srcbmp.Height - 1));
}
pta[1] := RotateXY(dbTheta,Point(Srcbmp.Width, 0));
pta[2] := RotateXY(dbTheta,Point(0, Srcbmp.Height));
pta[3] := RotateXY(dbTheta,Point(Srcbmp.Width, Srcbmp.Height));
DestBmp.PixelFormat := pf32bit;
DestBmp.Canvas.Brush.Color := clWindow;
for i := 0 to 3 do
ba[i] := pta[i].x;
DestBmp.width := MaxIntValue(ba) - MinIntValue(ba);
for i := 0 to 3 do
ba[i] := pta[i].y;
DestBmp.Height := MaxIntValue(ba) - MinIntValue(ba);
ptc := RotateXY(dbTheta, Point(Srcbmp.Width div 2, Srcbmp.Height div 2));
ptTarCenter.x := DestBmp.Width div 2;
ptTarCenter.y := DestBmp.Height div 2;
pta[0].x := pta[0].x + ptTarCenter.x - ptc.x;
pta[0].y := pta[0].y + ptTarCenter.y - ptc.y;
pta[1].x := pta[1].x + ptTarCenter.x - ptc.x;
pta[1].y := pta[1].y + ptTarCenter.y - ptc.y;
pta[2].x := pta[2].x + ptTarCenter.x - ptc.x;
pta[2].y := pta[2].y + ptTarCenter.y - ptc.y;
if PlgBlt(DestBmp.Canvas.Handle, pta, Srcbmp.Canvas.Handle,
0, 0, Srcbmp.Width - 1, Srcbmp.Height - 1, 0, 0, 0) then
DestBmp.Canvas.Draw(0, 0, DestBmp)
else
DestBmp.Canvas.TextOut(0,0,'只支持WinNT内核操作系统.');
end;
//毫米单位转换为英寸单位
function MmToInch(Length: Extended): Extended;
begin
Result := Length/25.4;
end;
//英寸单位转换为毫米单位
function InchToMm(Length: Extended): Extended;
begin
Result := Length*25.4;
end;
end.
用中文参数变量,别笑,这样只是为了让大家更好的解读一些重点代码。
注意我这儿的图片质量,都用了高质量,如果觉得处理的大小太大,则可以降低质量来获得小一些的文件
注意:
1、参数值为0时,表示该项不处理。
2、处理为依次执行,即旋转、切边、缩放,后一项的参数,也应参考前一项,而非原图参数
3、缩放只支持等比缩放,也就是只会根据宽或高中的一个值进行缩放,根据哪一个值,则适用于大值等于设置值的处理原则。
4、切边是指对应的边去除设定值,缩放则为处理后的目标值不大于设定值。
来源:https://www.cnblogs.com/zhqian/p/8621460.html