Question

I am working on a program in Delphi XE2 which needs to be able to convert Windows enhanced metafiles to bitmaps. The following code is used to perform the conversion:

procedure TForm1.Button8Click(Sender: TObject);
var
  Bitmap : TBitmap;
  Metafile : TMetafile;
begin
  Metafile := TMetafile.Create();
  Bitmap := TBitmap.Create;
  try
    Metafile.LoadFromFile(Edit1.Text);
    Bitmap.Width := Metafile.Width;
    Bitmap.height:= Metafile.Height;
    Bitmap.Canvas.Draw(0,0,Metafile);
    Bitmap.SaveToFile(ChangeFileExt(Edit1.Text, '.bmp'));
  finally
    Bitmap.Free();
    Metafile.Free();
  end;
end;

With certain image files the text, which was quite clear in the original metafile, appears somewhat blurry in the final bitmap. Unfortunately I cannot post an example image here because I don't have sufficient reputation points, however you can see the sort of thing I am talking about if you compare the two images in the following question:

when rendering metafile, the texts are too large

I have tested this on two machines (both Windows 7; one 32-bit, the other 64-bit). The problem only occurs on the 64-bit machine; converting exactly the same image file on the 32-bit machine results in a bitmap with normal-looking text.

Things I have tried so far:

  • Installed all fonts that were present on the 32-bit machine but not on the 64-bit machine onto the 64-bit machine. The text in the generated bitmap was still blurry.

  • Tried performing the conversion using the SynGdiPlus library instead of the above code. The text in the generated bitmap was still blurry.

  • Tried opening the original image file in EMF Explorer. Regardless of whether GDI+ is enabled or not, the text displayed there is non-blurry.

Does anybody have any suggestions as to how I could solve this problem?

Here are the two images:

The version made on the 64 bit machine:

enter image description here

The version made on the 32 bit machine:

enter image description here

For the scenario I am dealing with, I prefer the second image, that made on the 32 bit machine.

Was it helpful?

Solution

{1} Edit: Since we've established that you're not the one creating the original meta after this answer has been posted, please refer to section Retrieving records from an existing MetaFile.

{2} Edit: Per your second problem with identifying font settings, please refer to second update section Retrieving font structure record.

ClearType is quite a pickle. Anyone can change the intensity of the blending color as they wish, thanks to the integrated ClearType tuner. With Images in mind you therefor cannot rely on the ClearType settings of each individual system.

AFAIK the only real solution is to ignore the custom ClearType rendering and use a pre-configured one.


Edit 1 : Retrieving records from an existing MetaFile

You can modify an existing Metafile through Enhanced Metafile Operations more specifically through EnumEnhMetaFile function which has a callback function EnhMetaFileProc that you can use to process the records.

Use the PlayEnhMetaFileRecord function to parse through and examine each record at a time. More on how to edit & modify a specific record, see here.

At some point down the line you will have to use the code below to modify the existing font rendering.


Edit 2 : Retrieving font structure record

Just like you can retrieve the position and text via EMREXTTEXTOUTA structure, you can also retrieve the Font settings used via the EMREXTCREATEFONTINDIRECTW structure. This structure will allow you to get the font record of LOGFONT defined type which contains most info regarding the font, except for the brush used.

If you look at my original answer code you can see that the color of the font is defined by the brush used. so equally you have to use a different structure to obtain that info, the EMRCREATEBRUSHINDIRECT structure. The LOGBRUSH32 typed member contains info about the color and style of the brush used.


Original Answer

In order to accomplish this you have to resort to using GDI+ since the delphi encapsulation of the Win32 Enhanced metafile is not complete. Use the Delphi GDI+ library.

uses 
 GDIPlus,GDIPlusHelpers

const
  Deftext = 'Lorem ipsum dolor sit amet,'
  +sLineBreak+'consectetur adipisicing elit, sed do eiusmod tempor incididunt'
  +sLineBreak+'ut labore et dolore magna aliqua.';

procedure CreateEmF(const EmfFileName : TFileName);
var
  Graphics : IGPGraphics;
  xBrush: IGPBrush;
  xFontFamily: IGPFontFamily;
  xFont: IGPFont;
  DC: HDC;
  Metafile: IGPMetafile;

begin

  xBrush := TGPSolidBrush.Create(TGPColor.Create(0, 0, 0));
  xFontFamily := TGPFontFamily.Create('Segoe UI');
  xFont := TGPFont.Create(xFontFamily, 12, FontStyleRegular, UnitPoint{UnitPixel});

  DC := GetDC(0);

  try

    Metafile := TGPMetafile.Create(EmfFileName, DC);
    Graphics := TGPGraphics.Create(Metafile);

    {
      Use Presets instead of the DefaultSystemRendering 

      TextRenderingHintAntiAliasGridFit - Preset ClearType Rendering
      TextRenderingHintSingleBitPerPixelGridFit - Preset Normal Rendering
    }

    Graphics.TextRenderingHint := TextRenderingHintAntiAliasGridFit;
    Graphics.DrawString(Deftext, xFont, TGPPointF.Create(50, 50), xBrush);

    Graphics := nil;

  finally
    ReleaseDC(0, DC);
  end;

end;

procedure ConvertEmf2Bmp(const EMFFileName, BMPFileName: TFileName) ;
var
  MetaFile : TMetafile;
  Bitmap : TBitmap;
begin
  Metafile := TMetaFile.Create;
  Bitmap := TBitmap.Create;
  try
    MetaFile.LoadFromFile(EMFFileName);
    with Bitmap do
    begin
      SetSize(MetaFile.Width,MetaFile.Height);
      Canvas.Draw(0, 0, MetaFile) ;
      SaveToFile(BMPFileName) ;
    end;
  finally
    Bitmap.Free;
    MetaFile.Free;
  end;
end;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top