Declaration
function GetImageRectWithinArea(ImageWidth, ImgHeight : Integer;
DestWidth, DestHeight : Integer;
HorzOffset : Integer = 0;
VertOffset : integer = 0;
bAllowStretching : boolean = true;
bAllowShrinking : boolean = true;
bCenterHorz : boolean = true;
bCenterVert : boolean = true;
iAutoCropPercent : Integer = 0;
FitMethod: TFitMethod = _fmFitWithinRect) : TRect; overload;
function GetImageRectWithinArea(ImgWidth, ImgHeight: Integer;
ADestRect : TRect;
bAllowStretching : boolean = true;
bAllowShrinking : boolean = true;
bCenterHorz : boolean = true;
bCenterVert : boolean = true;
iAutoCropPercent : Integer = 0;
FitMethod: TFitMethod = _fmFitWithinRect) : TRect; overload;
Description
Return the new size and position of an image within an area assuming that we maintain the aspect ratio of the image.
Parameter | Description |
ImgWidth/ImgHeight | The dimensions of the image |
DestWidth/DestHeight or ADestRect | The space available for the image (e.g. the client area of a display control, such as a TImageEnView) |
HorzOffset/VertOffset | Added to the left/top of the image position, e.g. to add a margin |
bAllowStretching | If image is smaller than DestWidth/DestHeight its dimensions will be enlarged |
bAllowShrinking | If image is larger than DestWidth/DestHeight its dimensions will be reduced |
bCenterHorz | Image is positioned in the horizontal center (Otherwise result.Left will be zero) |
bCenterVert | Image is positioned in the vertical center (Otherwise result.Top will be zero) |
iAutoCropPercent | An advanced parameter that allows the image to be positioned outside of the display area to that it appears larger (i.e. part of the image is cropped). For example, if a portrait image is shown on screen generally there are wide side borders. An autocrop value of 10% would see (up to) 5% of the image not shown at the top and bottom so the border areas are reduced |
FitMethod | Generally _fmFitWithinRect, but _fmFillRect_WithOverlap will return an image that makes the image as large as possible without any border area (but with part of the image offscreen). This is the same as using an iAutoCropPercent of 100 |
// Stretch Draw an image centered within a TIEBitmap
aRect := GetImageRectWithinArea( SrcBMP.Width, SrcBMP.Height, DestBMP.Width, DestBMP.Height );
SrcBMP.DrawToTIEBitmap( DestBMP, IERectangle( aRect ), IERectangle( 0, 0, SrcBMP.Width, SrcBMP.Height ));
// Col 1 of a TStringGrid displays a thumbnail drawn from a TImageEnMView
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Longint;
Rect: TRect; State: TGridDrawState);
var
aIEBitmap: IEBitmap;
aCanvas: TCanvas;
idx: Integer;
begin
// Col 1 contains thumbnail. Row 0 is fixed header row
if (ACol <> 1) or (ARow = 0) then
Exit;
idx := ARow;
aCanvas := (Sender as TStringGrid).Canvas;
// Clear current cell rect
aCanvas.FillRect( Rect );
// Get our image
// Note: don't need to create or free the TIEBitmap
aIEBitmap := ImageEnMView1.GetIEBitmap( idx );
// Adjust our rect to maintain the image aspect ratio
Rect := GetImageRectWithinArea( Rect, aIEBitmap.Width, aIEBitmap.Height );
// Draw the image
aIEBitmap := RenderToCanvas( aCanvas, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top, rfFastLinear, 0 );
// Release our image
ImageEnMView1.ReleaseBitmap( idx, False );
end;
// Overlay entire image with watermark at 30% opacity (maintaining aspect ratio)
bmpImg := TIEBitmap.create;
bmpWM := TIEBitmap.create;
bmpImg.Read('D:\image.jpeg');
bmpWM.Read('D:\Watermark.png');
aRect := GetImageRectWithinArea( wmBMP.Width, wmBMP.Height, bmpImg.Width, bmpImg.Height);
wmOpacity := 0.30;
bmpWM.RenderToTIEBitmapEx( bmpImg,
aRect.Left, aRect.Top, aRect.Right - aRect.Left, aRect.Bottom - aRect.Top,
0, 0, bmpWM.Width, bmpWM.Height,
True, 255, rfFastLinear, ielNormal,
wmOpacity );
bmpImg.Write('D:\image-marked.jpeg');
bmpImg.Free;
bmWM.Free;
// Draw two images onto a bitmap above
// Image 1 is centered within the top 30% of the bitmap. Image 2 is centered within the bottom 70% of the bitmap
const
// Size to draw image 1
Image_1_Max_Width = 900;
Image_1_Max_Height = 300; // 30% of output image height
// Size to draw image 2
Image_2_Max_Width = Image_1_Max_Width;
Image_2_Max_Height = 700; // 70% of output image height
// Size of output image
Image_Out_Width = Image_1_Max_Width;
Image_Out_Height = Image_1_Max_Height + Image_2_Max_Height;
BG_Color = clWhite;
var
bmpOut, bmp1, bmp2 : TIEBitmap;
rct1, rct2: TRect;
begin
bmp1 := TIEBitmap.Create();
bmp2 := TIEBitmap.Create();
bmpOut := TIEBitmap.Create( Image_Out_Width, Image_Out_Height, BG_Color );
try
bmp1.Read( 'D:\image1.jpg' );
bmp2.Read( 'D:\image2.jpg' );
// Draw bmp1 at top of image within allowed space (while maintaing AR)
rct1 := GetImageRectWithinArea( bmp1.Width, bmp1.Height,
Image_1_Max_Width, Image_1_Max_Height );
bmp1.StretchRectTo( bmpOut,
rct1.Left, rct1.Top, rct1.Right - rct1.Left, rct1.Bottom - rct1.Top,
0, 0, bmp1.Width, bmp1.Height,
rfLanczos3 );
// Draw bmp2 below bmp1 within allowed space (while maintaing AR)
rct2 := GetImageRectWithinArea( bmp2.Width, bmp2.Height,
Image_2_Max_Width, Image_2_Max_Height );
bmp2.StretchRectTo( bmpOut,
rct2.Left, Image_1_Max_Height + rct2.Top, rct2.Right - rct2.Left, rct2.Bottom - rct2.Top,
0, 0, bmp2.Width, bmp2.Height,
rfLanczos3 );
// Show in our TImageEnView
ImageEnView1.Assign( bmpOut );
finally
bmp1 .Free;
bmp2 .Free;
bmpOut.Free;
end;
end;
// CREATE BITMAP WITH BLURRED IMAGE FILLING NON-IMAGE AREA
// DestBmp: Output image for result
// BackgroundBmp: Image to use as background (must be valid)
// ImageBmp: Image to draw centered (can be same as BackgroundBmp, or can be NIL)
// Width, Height: Size to make DestBmp
// BlurRadius: How much to blur image (Default is 8, 0 for no blur)
// BackgroundOpacity: If less than 1.0, the background is drawn semi-opaque (with BackgroundColor visible)
procedure StretchDrawWithBlur(DestBmp, BackgroundBmp, ImageBmp: TIEBitmap; Width, Height: Integer; BlurRadius: Integer = 8; BackgroundOpacity: Double = 0.75; BackgroundColor: TColor = clBlack);
var
aRect: TRect;
DestRect : TIERectangle;
begin
// Allocate and size
if not assigned( DestBmp ) then
DestBmp := TIEBitmap.create;
DestBmp.Allocate( Width, Height );
// Fill background color if needed
if BackgroundOpacity < 1.0 then
DestBmp.Fill( BackgroundColor );
// Scale draw the background to fill entire image area
aRect := GetImageRectWithinArea( BackgroundBmp.Width, BackgroundBmp.Height, DestBmp.Width, DestBmp.Height,
0, 0, True, True, True, True, 0,
_fmFillRect_WithOverlap );
DestRect := IERectangle( aRect );
BackgroundBmp.RenderToTIEBitmapEx( DestBmp, DestRect.X, DestRect.Y, DestRect.Width, DestRect.Height,
0, 0, BackgroundBmp.Width, BackgroundBmp.Height,
True, 255, rfNone, ielNormal, BackgroundOpacity );
// Blur the background
if BlurRadius > 0 then
with TImageEnProc.CreateFromBitmap( DestBmp ) do
begin
Blur( BlurRadius );
Free();
end;
// Draw our image
if ImageBmp <> nil then
begin
aRect := GetImageRectWithinArea( ImageBmp.Width, ImageBmp.Height, DestBmp.Width, DestBmp.Height );
DestRect := IERectangle( aRect );
ImageBmp.RenderToTIEBitmapEx( DestBmp, DestRect.X, DestRect.Y, DestRect.Width, DestRect.Height,
0, 0, ImageBmp.Width, ImageBmp.Height,
True, 255, rfNone, ielNormal, 1.0 );
end;
end;
// TEST METHOD
procedure TImageEnViewForm.Button1Click(Sender: TObject);
var
bmpIn, bmpOut: TIEBitmap;
begin
bmpIn := TIEBitmap.Create;
bmpOut := TIEBitmap.Create();
try
bmpIn.Read( 'D:\image.jpeg' );
StretchDrawWithBlur( bmpOut, bmpIn, bmpIn, 900, 400, 8, 0.75, clGray );
ImageEnView1.Assign( bmpOut );
finally
bmpIn.Free;
bmpOut.Free;
end;
end;
See Also
◼GetImageSizeWithinArea
◼IEAdjustRectToAspectRatio