使用Canvas.stretchdraw或StretchBlt函数,图像压缩后总是一锯齿,图像不好看,需要经过柔化处理。以下代码实现柔化压缩:
procedure RHStretchDraw(DestRect : TRect;Canvas : TCanvas; SourceBmp : TBitmap);
var
i,j, k: Integer;
SourceBuf,DestBufffer : pointer;
W, W3, H, WS3
Word;
Y,X1,X2,X3,X4,X5,X6,X7,X8,X9 : PByte;
C, B : DWord;
Zx, Zy : Single;
Bmp : TBitmap;
ARect : TRect;
BmpInfo11 : BITMAPINFO;
begin
ARect := DestRect;
W := ARect.Right - ARect.Left;
H := ARect.Bottom - ARect.Top;
if (W = 0) or (H = 0 ) then exit;
Zx := SourceBmp.Width / W; //x方向的压缩比例
Zy := SourceBmp.Height / H; //y方向的压缩比例
if (Zx = 1) and (Zy = 1) then
begin
Canvas.Draw(DestRect.Left,DestRect.Top, SourceBmp) ;
exit;
end;
if (Zx > 1) and (Zy > 1 ) then //图像缩小
begin
{ if (Zx < 1.5) and (Zy < 1.5 ) then //图像缩小
begin
Canvas.StretchDraw(Rect(0,0,W,H),SourceBmp); ;
exit;
end; }
//W := (W + 3) div 4 * 4;
W3 := (W * 3+3) div 4 * 4;
WS3 := (SourceBmp.Width* 3+3) div 4 * 4;
SourceBmp.PixelFormat := pf24bit;
try
Getmem(SourceBuf,(WS3+12) * SourceBmp.Height );
except
exit;
end;
GetBitmapBits(SourceBmp.Handle, WS3 * SourceBmp.Height , SourceBuf);
C := W3 * H ;
try
Getmem(DestBufffer, C+1000);
except
exit;
end;
//Copymemory(DestBufffer, SourceBuf, C);
try
for j:=0 to H - 1 do
begin
for i:=0 to W - 1 do
begin
for k := 0 to 2 do //Blue, Green, Red
begin
Y := PByte(DWORD(DestBufffer)+ (j) * W3 + i * 3 + K); //H-j-1
//四个相邻点
B := DWORD(SourceBuf)+ trunc(j * Zy) * WS3+ trunc(i * Zx) * 3 + K;
if (j = 0) or (i = 0) then // (Zx < 2.5)or
begin
X1 := PByte(B);
X2 := PByte(B+WS3);
X3 := PByte(B+3);
X4 := PByte(B+WS3+3);
Y^ := (X1^ + X2^ + X3^ + X4^ ) div 4;
end else
begin
//9个相邻点取平均值
X1 := PByte(B - WS3 - 3);
X2 := PByte(B - WS3);
X3 := PByte(B - WS3 + 3);
X4 := PByte(B - 3);
X5 := PByte(B);
X6 := PByte(B + 3);
X7 := PByte(B + WS3 - 3);
X8 := PByte(B + WS3);
X9 := PByte(B + WS3 + 3);
Y^ := (X1^ + X2^ + X3^ + X4^ +X5^ * 5 + X6^ + X7^ + X8^ + X9^) div 13;
//Y^ := ( X1^ + X3^ + X5^*2 + X7^ + X9^ ) div 6;
//Y^ := X5^ ;
end;
end;
end;
end;
BmpInfo11.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
BmpInfo11.bmiHeader.biCompression := BI_RGB;
BmpInfo11.bmiHeader.biPlanes := 1;
BmpInfo11.bmiHeader.biBitCount := 24;
BmpInfo11.bmiHeader.biWidth := W;
BmpInfo11.bmiHeader.biHeight := H;
BmpInfo11.bmiHeader.biSizeImage := BmpInfo11.bmiHeader.biWidth*BmpInfo11.bmiHeader.biHeight*BmpInfo11.bmiHeader.biPlanes*(BmpInfo11.bmiHeader.biBitCount div 8);
BmpInfo11.bmiHeader.biXPelsPerMeter := 0;
BmpInfo11.bmiHeader.biYPelsPerMeter := 0;
BmpInfo11.bmiHeader.biClrUsed := 0;
BmpInfo11.bmiHeader.biClrImportant := 0;
StretchDIBits(Canvas.Handle, 0, 0, W, H, 0, 0, W, H,
DestBufffer, BmpInfo11 , DIB_RGB_COLORS, SRCCOPY);
finally
freemem(SourceBuf);
freemem(DestBufffer);
end;
end else //图像扩大
begin
W := (W + 3) div 4 * 4;
Bmp := TBitmap.Create;
bmp.PixelFormat := pf24bit;
bmp.Width:=W;
bmp.Height:=H;
bmp.Canvas.StretchDraw(Rect(0,0,W,H),SourceBmp);
C := (W * 3+3) div 4 * 4* H;
try
Getmem(SourceBuf, C * 2);
except
exit;
end;
try
GetBitmapBits(Bmp.Handle, C, SourceBuf);
DestBufffer :=Pointer( DWORD(SourceBuf)+C);
Copymemory(DestBufffer, SourceBuf, C);
W3 := (W * 3+3)div 4*4;
for j:=1 to H - 2 do
begin
for i:=1 to W - 2 do
begin
for k := 0 to 2 do //Blue, Green, Red
begin
Y := PByte(DWORD(DestBufffer)+ j * W3 + i * 3 + K);
B := DWORD(SourceBuf)+ j * W3 + i * 3 + K;
X1 := PByte(B - W3 - 3);
X2 := PByte(B - W3);
X3 := PByte(B - W3 + 3);
X4 := PByte(B - 3);
X5 := PByte(B);
X6 := PByte(B + 3);
X7 := PByte(B + W3 - 3);
X8 := PByte(B + W3);
X9 := PByte(B + W3 + 3);
Y^ := (X1^ + X2^ + X3^ + X4^ + X5^ * 2 + X6^ + X7^ + X8^ + X9^) div 10;
end;
end;
end;
SetBitmapBits(Bmp.Handle, C, DestBufffer);
Canvas.Draw(0,0,Bmp);
Bmp.Free;
finally
freemem(SourceBuf);
end;
end;
end;
procedure ChangeImageSize(SourceImage:TImage;NewWidth,NewHeight:integer;DestBmp:TBitmap );
var SourceBmp:TBitmap ;
begin
SourceBmp:=TBitmap.Create;
if DestBmp=nil then
DestBmp:=TBitmap.Create;
try
SourceBmp.Width := SourceImage.Picture.Width;
SourceBmp.height := SourceImage.Picture.height;
DestBmp.Width := NewWidth;
DestBmp.Height := NewHeight;
SourceBmp.Canvas.Draw(0,0,SourceImage.Picture.Graphic);
RHStretchDraw(SourceImage.ClientRect,DestBmp.Canvas, SourceBmp);
finally
SourceBmp.Free;
end;
end;
procedure TForm1.Button1Click(Sender:TObject);
var jpg:TJpegImage;
DestBmp:TBitmap;
begin
DestBmp := TBitmap.Create;
jpg:=TJpegImage.Create;
try
ChangeImageSize(Image1,310,234,DestBmp);
jpg.Assign(DestBmp);
jpg.SaveToFile('a.jpg');
finally
jpg.free;
DestBmp.Free;
end;
end;