#1 2012-06-07 18:59:30

emarc
Member
Registered: 2012-06-07
Posts: 3

Size problems using GDI+ antialiasing function

Regards,

We are using your great library in order to apply antialiasing to several vectorial shapes drawed at runtime. But when it must be shown at screen, it doesn't fit on the designed size.

I attach a simple sample to show this behaviour (you only need to add an Image1 TImage into a new form to run it)

It should show an ellipsis at 50 pixels from every screen border, but it doesn't.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
  TfrmMain = class(TForm)
    Image1: TImage;
    procedure FormResize(Sender: TObject);
  private
  public
    procedure DrawTest;
  end;

var
  frmMain: TfrmMain;

implementation 

{$R *.dfm}

Uses Math, SynGdiPlus;

procedure TfrmMain.FormResize(Sender: TObject);
begin
  DrawTest;
end;

procedure TfrmMain.DrawTest;
var Bmp: TBitmap;
    MF: TMetaFile;
    MetafileCanvas: TMetafileCanvas;
    DC: HDC;
    ScreenLogPixels: Integer;
begin
  Gdip := TGDIPlusFull.Create('gdiplus.dll');       // Dibujamos sobre un TMetafile sobre el cual podemos hacer una llamada GDI+ a aplicar Antialiasing
  MF := TMetaFile.Create;
  DC := GetDC(0);
  ScreenLogPixels := GetDeviceCaps(DC, LOGPIXELSY);
  MF.Inch := ScreenLogPixels;
  MF.Width := frmMain.Width;
  MF.Height := frmMain.Height;

  MetafileCanvas := TMetafileCanvas.Create(MF, DC);

  MetafileCanvas.Brush.Color := clRed;
  MetafileCanvas.Brush.Style := bsDiagCross;
  MetafileCanvas.Ellipse(50, 50, Image1.Width - 50, Image1.Height - 50);

  ReleaseDC(0, DC);
  MetafileCanvas.Free;
  MF.Enhanced := FALSE;

  Bmp := Gdip.DrawAntiAliased(MF,100,100);

  Image1.Picture.Assign(Bmp);
  MF.Destroy;
  Self.BringToFront;
end;

end.

Can you tell us what we are doing wrong ?

Thank you.

Offline

#2 2012-06-08 06:40:31

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,183
Website

Re: Size problems using GDI+ antialiasing function

If you disable GDI+ rendering (by letting GdiP to be nil), the drawing is the same.
Therefore, issue is not in SynGDIPlus unit.

The problem comes from the fact that you scale your picture from the main window size, then use the Image1 Width/Height for the ellipsis size.

By the way, your code creates several memory leaks:
- Is reallocating Gdip several times (at each resize);
- The Bmp shall be freed after Assign;
- Do not call MF.Destroy but MF.Free;
- Protect your resources with try..finally blocks.
Of course, this is because it's only a demo code, but ensure that production code won't suffer from these issues! wink

Offline

#3 2012-06-08 09:19:48

emarc
Member
Registered: 2012-06-07
Posts: 3

Re: Size problems using GDI+ antialiasing function

Hello.

ab wrote:

The problem comes from the fact that you scale your picture from the main window size, then use the Image1 Width/Height for the ellipsis size.

Thanks, but I can't understand where the problem is. I have changed the code, following your advice, but I get exactly the same result. I expect an ellipsis centered on the screen, but I get an image moved to the right, with the ellipsis cutted on the right edge.

I try to set exactly the same size for the Metafile, Image and Form. I suspect that the Metafile doesn't adjust to the indicated size, so drawing into MetafileCanvas and exporting it results creates a bitmap slightly larger than Image1 bitmap.

  MF.Width := frmMain.Width;
  MF.Height := frmMain.Height;
  Image1.Width := frmMain.Width;
  Image1.Height := frmMain.Height;
  Image1.Top := 0;
  Image1.Left := 0;

  MetafileCanvas := TMetafileCanvas.Create(MF, DC);

  MetafileCanvas.Brush.Color := clRed;
  MetafileCanvas.Brush.Style := bsDiagCross;
  MetafileCanvas.Ellipse(50, 50, frmMain.Width - 50, frmMain.Height - 50);

I only get the expected result at a form resolution of 1209 x 907, but I don't know what is especial about that resolution. It seems that the Metafile Canvas always draws at 1209 x 907 and cuts to the desired result, but I don't understand how or why it does that.

Thanks for your kind help.

Last edited by emarc (2012-06-08 09:28:32)

Offline

#4 2012-06-08 09:43:18

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,183
Website

Re: Size problems using GDI+ antialiasing function

This will depend on the position of Image1.
In fact, you should set MF.Width/MF.Height to the Image1.Width/Height.

This code works as expected:

procedure TForm1.FormResize(Sender: TObject);
var Bmp: TBitmap;
    MF: TMetaFile;
    MetafileCanvas: TMetafileCanvas;
begin
  Gdip := TGDIPlusFull.Create('gdiplus.dll');
  MF := TMetaFile.Create;
  MF.Width := 300;
  MF.Height := 200;

  MetafileCanvas := TMetafileCanvas.Create(MF, 0);
  MetafileCanvas.Brush.Color := clRed;
  MetafileCanvas.Brush.Style := bsDiagCross;
  MetafileCanvas.Ellipse(50, 50, 300 - 50, 200 - 50);
  MetafileCanvas.Free;

  Bmp := Gdip.DrawAntiAliased(MF);
  Image1.Picture.Assign(Bmp);
  Bmp.Free;
  //Image1.Picture.Assign(MF);

  MF.Free;
  FreeAndNil(GdiP);
end;

The error is when you call MF.Height and MF.Width in MetafileCanvas.Ellipse() parameters: it does not return the expected dimensions.
You'll have to use your own variables here.

This is an issue (a feature?) with the Windows MetaFile implementation.
You'd never rely on MF.HEight/Width, but use your own variables to compute the coordinates.

Offline

#5 2012-06-08 17:48:34

emarc
Member
Registered: 2012-06-07
Posts: 3

Re: Size problems using GDI+ antialiasing function

Thank you very much.

It works like a charm. smile

Offline

Board footer

Powered by FluxBB