마음의 안정을 찾기 위하여 - [Delphi] EMF Meta File Rotation
1987043
407
569
관리자새글쓰기
태그위치로그방명록
별일없다의 생각
dawnsea's me2day/2010
색상(RGB)코드 추출기(Color...
Connection Generator/2010
최승호PD, '4대강 거짓말 검...
Green Monkey**/2010
Syng의 생각
syng's me2DAY/2010
천재 작곡가 윤일상이 기획,...
엘븐킹's Digital Factory/2010
[Delphi] EMF Meta File Rotation
Delphi/Image Processing | 2019/06/07 15:13
http://www.efg2.com/Lab/Library/Delphi/Graphics/FreddyDarsonvilleMetafileRotation.TXT

unit libmeta;

interface
{$R-}
uses
    Windows, Classes,math, Graphics, FlipReverseRotateLibrary,SysUtils;

type
    PDWORD = ^DWORD;

  {the callback function for enumerating enhanced metafile records}
function RotateLeftRecords(DisplaySurface: HDC;    var MetafileTable:
THandleTable;    var MetafileRecord: TEnhMetaRecord; ObjectCount:
Integer;    var Data: Longint): Integer; stdcall;

  {the metafile records I've done}
procedure RotateLeftLINETO(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
procedure RotateLeftMOVETOEX(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
procedure RotateLeftEXTTEXTOUTW(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
procedure RotateLeftEXTCREATEFONTINDIRECTW(var rec: TEnhMetaRecord; dc:
HDC; width: integer); stdcall;
procedure RotateLeftRECTANGLE(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
procedure RotateLeftPOLYLINE(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
procedure RotateLeftPOLYGON(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
procedure RotateLeftPOLYLINE16(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
procedure RotateLeftPOLYGON16(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
procedure RotateLeftBITBLT(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
procedure RotateLeftEXTSELECTCLIPRGN(var rec: TEnhMetaRecord; dc: HDC;
width: integer); stdcall;

  {the other !!!!}
procedure ToDo(var rec: TEnhMetaRecord; dc: HDC; width: integer);
stdcall;


function RotateMetafile(TheMeta : HENHMETAFILE; w,h:integer) :
TMetafile;
function NTRotateMetafile(TheMeta : HENHMETAFILE; w,h:integer) :
TMetafile;



implementation

uses dialogs;

var
    fdc: HFONT; //local but necessary


function RotateLeftRecords(DisplaySurface: HDC;
    var MetafileTable: THandleTable;
    var MetafileRecord: TEnhMetaRecord;
    ObjectCount: Integer;
    var Data: Longint): Integer;
begin
    case MetafileRecord.iType of
        EMR_LINETO: RotateLeftLINETO(MetafileRecord, displaySurface,
data);
        EMR_MOVETOEX: RotateLeftMOVETOEX(MetafileRecord, displaySurface,
data);
        EMR_EXTTEXTOUTW: RotateLeftEXTTEXTOUTW(MetafileRecord,
displaySurface, data);
        EMR_EXTCREATEFONTINDIRECTW:
RotateLeftEXTCREATEFONTINDIRECTW(MetafileRecord, displaySurface, data);
        EMR_RECTANGLE: RotateLeftRECTANGLE(MetafileRecord,
displaySurface, data);
        EMR_POLYLINE: RotateLeftPOLYLINE(MetafileRecord, displaySurface,
data);
        EMR_POLYGON: RotateLeftPOLYGON(MetafileRecord, displaySurface,
data);
        EMR_POLYLINE16: RotateLeftPOLYLINE16(MetafileRecord,
displaySurface, data);
        EMR_POLYGON16: RotateLeftPOLYGON16(MetafileRecord,
displaySurface, data);
        EMR_EXTSELECTCLIPRGN: RotateLeftEXTSELECTCLIPRGN(MetafileRecord,
displaySurface, data);
        EMR_FILLRGN:Todo(MetafileRecord, displaySurface, data);
        EMR_FRAMERGN:Todo(MetafileRecord, displaySurface, data);
        EMR_INVERTRGN:Todo(MetafileRecord, displaySurface, data);
        EMR_PAINTRGN:Todo(MetafileRecord, displaySurface, data);
        EMR_STRETCHBLT:Todo(MetafileRecord, displaySurface, data);
        EMR_MASKBLT:Todo(MetafileRecord, displaySurface, data);
        EMR_PLGBLT:Todo(MetafileRecord, displaySurface, data);
        EMR_SETDIBITSTODEVICE:Todo(MetafileRecord, displaySurface,
data);
        EMR_STRETCHDIBITS : Todo(MetafileRecord, displaySurface, data);

//        EMR_BITBLT:Todo(MetafileRecord, displaySurface, data);
//        EMR_SETMETARGN: Todo(MetafileRecord, displaySurface, data);
    else
        PlayEnhMetaFileRecord(DisplaySurface, MetafileTable,
MetafileRecord, ObjectCount);
    end;

    Result := 1; // continue enumeration
end;

procedure RotateLeftLINETO(var rec: TEnhMetaRecord; dc: HDC; width:
longint);
var
    p: PEMRLineTo;
begin
    p := PEMRLineTo(@rec);
    lineto(dc, width - p.ptl.y, p.ptl.x);
end;

procedure RotateLeftMOVETOEX(var rec: TEnhMetaRecord; dc: HDC; width:
longint);
var
    p: PEMRMoveToEx;
begin
    p := PEMRMoveToEx(@rec);
    movetoex(dc, width - p.ptl.y, p.ptl.x, nil);
end;

procedure RotateLeftEXTTEXTOUTW(var rec: TEnhMetaRecord; dc: HDC; width:
longint);
var
    p: PEMRExtTextOut;
    ptext: PEMRText;
    R: TRect;
    text: PWideChar;


    LogRec: TLOGFONT; {* Storage area for font information *}
    hf: HFONT;
begin
    p := PEMRExtTextOut(@rec);
    ptext := PEMRText(@p.emrtext);


    text := PWideChar(DWORD(ptext) + ptext.offstring div 2 + 2);

    R := Rect(width - p.rclBounds.bottom, p.rclBounds.left, width -
p.rclBounds.top, p.rclBounds.right);

     SelectObject(dc, fdc);

    TextOutW(DC, width - p.emrtext.ptlReference.y,
p.emrtext.ptlReference.x, PWideCHAR(text), ptext.nChars);

end;

procedure RotateLeftEXTCREATEFONTINDIRECTW(var rec: TEnhMetaRecord; dc:
HDC; width: longint);
var
    p: PEMRExtCreateFontIndirect;
    logf: TLOGFONTW;
    res : boolean;
begin
    p := PEMRExtCreateFontIndirect(@rec);
    logf := p.elfw.elfLogFont;
    logf.lfEscapement := logf.lfEscapement + 2700;
    logf.lfOrientation := logf.lfEscapement;

    fdc := CreateFontIndirectW(logf);
    SelectObject(DC,fdc);
end;

procedure RotateLeftRECTANGLE(var rec: TEnhMetaRecord; dc: HDC; width:
integer);
var
    p: PEMRRectangle;
begin
    p := PEMRRectangle(@rec);
    rectangle(dc, width - p.rclBox.top, p.rclBox.left, width -
p.rclBox.bottom, p.rclBox.right);
end;

procedure RotateLeftPOLYLINE(var rec: TEnhMetaRecord; dc: HDC; width:
integer);
var
    p: PEMRPolyline;
    i: integer;
    ar: array[0..200] of TPoint;
    nb: integer;
begin
    p := PEMRPolyline(@rec);
    nb := p.cptl;

    for i := 0 to nb - 1 do
        ar[i] := Point(width - p.aptl[i].y, p.aptl[i].x);
    polyline(dc, ar, nb);
end;



procedure RotateLeftPOLYGON(var rec: TEnhMetaRecord; dc: HDC; width:
integer);
var
    p: PEMRPolygon;
    i: integer;
    ar: array[0..200] of TPoint;
    nb: integer;
begin
    p := PEMRPolygon(@rec);
    nb := p.cptl;

    for i := 0 to nb - 1 do
        ar[i] := Point(width - p.aptl[i].y, p.aptl[i].x);
    polygon(dc, ar, nb);
end;

procedure RotateLeftPOLYLINE16(var rec: TEnhMetaRecord; dc: HDC; width:
integer);
var
    p: PEMRPolyline16;
    i: integer;
    ar: array[0..200] of TPoint;
    nb: integer;
begin
    p := PEMRPolyline16(@rec);
    nb := p.cpts;

    for i := 0 to nb - 1 do
        ar[i] := Point(width - p.apts[i].y, p.apts[i].x);
    polyline(dc, ar, nb);
end;



procedure RotateLeftPOLYGON16(var rec: TEnhMetaRecord; dc: HDC; width:
integer);
var
    p: PEMRPolygon16;
    i: integer;
    ar: array[0..200] of TPoint;
    nb: integer;
begin
    p := PEMRPolygon16(@rec);
    nb := p.cpts;

    for i := 0 to nb - 1 do
        ar[i] := Point(width - p.apts[i].y, p.apts[i].x);
    polygon(dc, ar, nb);
end;

procedure RotateLeftBITBLT(var rec: TEnhMetaRecord; dc: HDC; width:
integer); stdcall;
const
    MaxPixelCount = 65536; // or some other arbitrarily large value
type
    TRGBArray = array[0..MaxPixelCount - 1] of TRGBTriple;
    pRGBArray = ^TRGBArray;
var
    p: PEMRBitBlt;
    bmp, rotbmp: TBitmap;
    i, j: integer;
    RowIn, RowOut: pRGBArray;
    DWordWidth: integer;
begin
    p := PEMRBitBlt(@rec);
    bmp := TBitmap.Create;
    bmp.PixelFormat := pf24bit;
    bmp.Width := p.cxDest;
    bmp.Height := p.cyDest;

    DWordWidth := 4*bmp.Width;
    for j := 0 to bmp.Height - 1 do
    begin
        rowIn := Pointer(DWORD(@p) + p.offBitsSrc + j * DWordWidth);
        rowOut := bmp.ScanLine[j];

        // Could optimize the following by using a function like
CopyMemory
        // from the Windows unit.
        for i := 0 to bmp.Width - 1 do
        begin
          // Why does this crash with RowOut[i] := RowIn[i]?  Alignment?

          // Use this longer form as workaround.
            with rowOut[i] do
            begin
                rgbtRed := rowIn[i].rgbtRed;
                rgbtGreen := rowIn[i].rgbtGreen;
                rgbtBlue := rowIn[i].rgbtBlue;
            end
        end
    end {SimpleCopy};

    rotbmp := RotateScanLine90(90, bmp);
    bitblt(dc, width - p.yDest, p.xDest, p.cyDest, p.cxDest,
rotbmp.Canvas.Handle, 0, 0, p.dwRop);
end;



procedure RotateLeftEXTSELECTCLIPRGN(var rec: TEnhMetaRecord; dc: HDC;
width: integer); stdcall;
var
    p: PEMRExtSelectClipRgn;
    rdh : TRgnDataHeader;
    prdh : pRgnDataHeader;
    rect : TRect;
    hrgn : integer;
begin
try
    p := PEMRExtSelectClipRgn(@rec);

    pRdh := pRgnDataHeader(@p.RgnData);
    rdh := tRgnDataHeader(prdh^);
    rect := rdh.rcBound ;
    hrgn := CreateRectRgn(Width - rect.Top , rect.Left , Width -
rect.Bottom , rect.Right );
    ExtSelectClipRgn(dc,hrgn,rdh.iType );
except
     ShowMessage('RotateLeftEXTSELECTCLIPRGN failed');
end;
end;

procedure ToDo(var rec: TEnhMetaRecord; dc: HDC; width: integer);
stdcall;
begin
     assert(False,'This type of metafile record is not supported :
'+IntToStr(rec.iType ));
end;



function RotateMetafile(TheMeta : HENHMETAFILE; w,h:integer) :
TMetafile;
var
    buf: TEnhMetaHeader;
    thewidth: longint;
    meta, meta2: TMetafile;
    metaCanvas, metacanvas2: TMetafileCanvas;
    R: TRect;
    hregion:    HRGN;
begin


    GetEnhMetaFileHeader(TheMeta, sizeof(TEnhMetaHeader), @buf);


   {enumerate the records in the metafile}
    meta := TMetafile.Create;
    meta.Enhanced := True;
    meta2 := TMetafile.Create;
    meta2.Enhanced := True;
    meta2.Height :=(buf.rclBounds.Right - buf.rclBounds.left) ;
    meta2.Width :=(buf.rclBounds.Bottom  - buf.rclBounds.Top);

  //  GetClipRgn (theMeta, hregion);
  //  GetrgnBox(hregion, R);


    thewidth :=  buf.rclBounds.Bottom  - buf.rclBounds.top; //0

    metaCanvas := TMetafileCanvas.Create(meta, 0);
    metaCanvas2 := TMetafileCanvas.Create(meta2, 0);


    EnumEnhMetaFile(metaCanvas.Handle, TheMeta, @RotateLeftRecords,
        @thewidth, buf.rclBounds);
    metaCanvas.free;

    GetEnhMetaFileHeader(meta.Handle, sizeof(TEnhMetaHeader), @buf);
    metacanvas2.Draw(-buf.rclBounds.Left, -buf.rclBounds.top, meta);
    metaCanvas2.free;


    meta.free;
    result := meta2;
end;

function NTRotateMetafile(TheMeta : HENHMETAFILE; w,h:integer) :
TMetafile;
var
    buf: TEnhMetaHeader;
    meta: TMetafile;
    metaCanvas: TMetafileCanvas;
    R: TRect;
    hregion:    HRGN;
       mat : XForm;
begin
    GetEnhMetaFileHeader(TheMeta, sizeof(TEnhMetaHeader), @buf);

   {enumerate the records in the metafile}
    meta := TMetafile.Create;
    metaCanvas := TMetafileCanvas.Create(meta, 0);
    meta.Enhanced := True;
    meta.Height :=w;
    meta.Width :=h;

    SetGraphicsMode(metaCanvas.Handle,GM_ADVANCED);

    mat.eM11 := 0;
    mat.eM12 := 1;
    mat.eM21 := -1;
    mat.eM22 := 0;
    mat.eDx := (buf.rclBounds.Bottom  - buf.rclBounds.Top);
    mat.eDy :=0;

    SetWorldTransform(metaCanvas.Handle,mat);
    PlayEnhMetaFile (metaCanvas.Handle,TheMeta  , rect(0,0,w,h) );

    metaCanvas.free;
    result := meta;
end;

end.



https://castelain.developpez.com/sources/EMFTransform/

unit EMFTransform;

interface
uses
  Classes, Windows;

procedure TransformEMF(emf: HENHMETAFILE; DoRotate, DoFlip, DoMirror: boolean);

implementation
uses
  SysUtils, Dialogs;

var
  centerl: TPoint;
  Rotate, Flip, Mirror: boolean;


{------------------------------------------------------------------------------}
function SmallPoint(x, y: SHORT): TSmallPoint;
begin
  Result.x:= x;
  Result.y:= y;
end;

{------------------------------------------------------------------------------}
function RectCenter(rec: TRect): TPoint;
begin
  result:= Point((rec.Left + rec.Right) div 2, (rec.Top + rec.Bottom) div 2);
end;

{------------------------------------------------------------------------------}
procedure InvertHVRect(var rec: TRect);
var
  tmp: LongInt;
begin
  tmp:= rec.Left;
  rec.Left:= rec.Top;
  rec.Top:= tmp;
  tmp:= rec.Right;
  rec.Right:= rec.Bottom;
  rec.Bottom:= tmp;
end;

{------------------------------------------------------------------------------}
procedure InvertHVPoint(var pt: TPoint);
var
  tmp: LongInt;
begin
  tmp:= pt.X;
  pt.X:= pt.Y;
  pt.Y:= tmp;
end;

{------------------------------------------------------------------------------}
procedure RotatePoint(var pt: TPoint; center: TPoint);
begin
  pt:= Point(pt.Y, 2*center.X - pt.X);
end;

{------------------------------------------------------------------------------}
procedure FlipPoint(var pt: TPoint; center: TPoint);
// Le haut deviens le bas et inversement
begin
  pt:= Point(pt.X, 2*center.Y - pt.Y);
end;

{------------------------------------------------------------------------------}
procedure MirrorPoint(var pt: TPoint; center: TPoint);
// La gauche devient la droite et inversement
begin
  pt:= Point(2*center.X - pt.X, pt.Y);
end;

{------------------------------------------------------------------------------}
procedure RotateSmallPoint(var pt: TSmallPoint; center: TPoint);
begin
  pt:= SmallPoint(pt.Y, 2*center.X - pt.X);
end;

{------------------------------------------------------------------------------}
procedure FlipSmallPoint(var pt: TSmallPoint; center: TPoint);
// Le haut deviens le bas et inversement
begin
  pt:= SmallPoint(pt.X, 2*center.Y - pt.Y);
end;

{------------------------------------------------------------------------------}
procedure MirrorSmallPoint(var pt: TSmallPoint; center: TPoint);
// La gauche devient la droite et inversement
begin
  pt:= SmallPoint(2*center.X - pt.X, pt.Y);
end;

{------------------------------------------------------------------------------}
procedure RotateRect(var r: TRect; center: TPoint);
var
  p2, p4: TPoint;
begin
  p2:= Point(r.Right, r.Top);
  p4:= Point(r.Left, r.Bottom);
  RotatePoint(p2, Center);
  RotatePoint(p4, Center);
  r:= Rect(p2.X, p2.Y, p4.X, p4.Y);
end;

{------------------------------------------------------------------------------}
procedure FlipRect(var r: TRect; center: TPoint);
var
  p1, p2: TPoint;
begin
  p1:= r.TopLeft;
  p2:= r.BottomRight;
  FlipPoint(p1, center);
  FlipPoint(p2, center);
  r.Top:= p2.Y;
  r.Bottom:= p1.Y;
end;

{------------------------------------------------------------------------------}
procedure MirrorRect(var r: TRect; center: TPoint);
var
  p1, p2: TPoint;
begin
  p1:= r.TopLeft;
  p2:= r.BottomRight;
  MirrorPoint(p1, center);
  MirrorPoint(p2, center);
  r.Left:= p2.X;
  r.Right:= p1.X;
end;

{------------------------------------------------------------------------------}
procedure RotateSize(var sz: TSize);
var
  tmpl: LongInt;
begin
  tmpl  := sz.cx;
  sz.cx := sz.cy;
  sz.cy := tmpl;
end;

{------------------------------------------------------------------------------}
function EnhMetaFileProc_Manipulate(DC: HDC; lpHTable: PHandleTable; lpEMFR: PENHMetaRecord; nObj: integer; lpData: LPARAM): integer; stdcall;
var
  i: integer;
begin
  Result:= 1;

  case lpEMFR^.iType of
    EMR_HEADER:
    with PEnhMetaHeader(lpEMFR)^ do
    begin
      if Rotate then
      begin
        InvertHVRect(PEnhMetaHeader(lpEMFR)^.rclBounds);
        InvertHVRect(PEnhMetaHeader(lpEMFR)^.rclFrame);

        RotateSize(PEnhMetaHeader(lpEMFR)^.szlDevice);
        RotateSize(PEnhMetaHeader(lpEMFR)^.szlMillimeters);
      end;
    end;

    EMR_LINETO, EMR_MOVETOEX:
    begin
      if Rotate then
        RotatePoint(PEMRLineTo(lpEMFR)^.ptl, centerl);
      if Flip then
        FlipPoint(PEMRLineTo(lpEMFR)^.ptl, centerl);
      if Mirror then
        MirrorPoint(PEMRLineTo(lpEMFR)^.ptl, centerl);
    end;

    EMR_OFFSETCLIPRGN:
    begin
      if Rotate then
        RotatePoint(PEMROffsetClipRgn(lpEMFR)^.ptlOffset, centerl);
      if Flip then
        FlipPoint(PEMROffsetClipRgn(lpEMFR)^.ptlOffset, centerl);
      if Mirror then
        MirrorPoint(PEMROffsetClipRgn(lpEMFR)^.ptlOffset, centerl);
    end;

    EMR_FILLPATH, EMR_STROKEANDFILLPATH, EMR_STROKEPATH:
    begin
      if Rotate then
        RotateRect(PEMRFillPath(lpEMFR)^.rclBounds, centerl);
      if Flip then
        FlipRect(PEMRFillPath(lpEMFR)^.rclBounds, centerl);
      if Mirror then
        MirrorRect(PEMRFillPath(lpEMFR)^.rclBounds, centerl);
    end;

    EMR_EXCLUDECLIPRECT, EMR_INTERSECTCLIPRECT:
    begin
      if Rotate then
        RotateRect(PEMRExcludeClipRect(lpEMFR)^.rclClip, centerl);
      if Flip then
        FlipRect(PEMRExcludeClipRect(lpEMFR)^.rclClip, centerl);
      if Mirror then
        MirrorRect(PEMRExcludeClipRect(lpEMFR)^.rclClip, centerl);
    end;

    EMR_SETWINDOWORGEX:
      with PEMRSetViewportOrgEx(lpEMFR)^ do
      begin
        // Nothing
      end;


    EMR_SETVIEWPORTORGEX, EMR_SETBRUSHORGEX:
    with PEMRSetViewportOrgEx(lpEMFR)^ do
    begin
        // Nothing
    end;

    EMR_SETVIEWPORTEXTEX, EMR_SETWINDOWEXTEX:
    begin
        // Nothing
    end;

    EMR_SETPIXELV:
    begin
      if Rotate then
        RotatePoint(PEMRSetPixelV(lpEMFR)^.ptlPixel, centerl);
      if Flip then
        FlipPoint(PEMRSetPixelV(lpEMFR)^.ptlPixel, centerl);
      if Mirror then
        MirrorPoint(PEMRSetPixelV(lpEMFR)^.ptlPixel, centerl);
    end;

    EMR_EXTFLOODFILL:
    begin
      if Rotate then
        RotatePoint(PEMRExtFloodFill(lpEMFR)^.ptlStart, centerl);
      if Flip then
        FlipPoint(PEMRExtFloodFill(lpEMFR)^.ptlStart, centerl);
      if Mirror then
        MirrorPoint(PEMRExtFloodFill(lpEMFR)^.ptlStart, centerl);
    end;

    EMR_ELLIPSE, EMR_RECTANGLE:
    begin
      if Rotate then
        RotateRect(PEMREllipse(lpEMFR)^.rclBox, centerl);
      if Flip then
        FlipRect(PEMREllipse(lpEMFR)^.rclBox, centerl);
      if Mirror then
        MirrorRect(PEMREllipse(lpEMFR)^.rclBox, centerl);
    end;

    EMR_ROUNDRECT:
    begin
      if Rotate then
      begin
        RotateRect(PEMRRoundRect(lpEMFR)^.rclBox, centerl);
        RotateSize(PEMRRoundRect(lpEMFR)^.szlCorner);
      end;
      if Flip then
        FlipRect(PEMRRoundRect(lpEMFR)^.rclBox, centerl);
      if Mirror then
        MirrorRect(PEMRRoundRect(lpEMFR)^.rclBox, centerl);
    end;

    EMR_ARC, EMR_ARCTO, EMR_CHORD, EMR_PIE:
    begin
      if Rotate then
      begin
        RotateRect(PEMRArc(lpEMFR)^.rclBox, centerl);
        RotatePoint(PEMRArc(lpEMFR)^.ptlStart, centerl);
        RotatePoint(PEMRArc(lpEMFR)^.ptlEnd, centerl);
      end;
      if Flip then
      begin
        FlipRect(PEMRArc(lpEMFR)^.rclBox, centerl);
        FlipPoint(PEMRArc(lpEMFR)^.ptlStart, centerl);
        FlipPoint(PEMRArc(lpEMFR)^.ptlEnd, centerl);
      end;
      if Mirror then
      begin
        MirrorRect(PEMRArc(lpEMFR)^.rclBox, centerl);
        MirrorPoint(PEMRArc(lpEMFR)^.ptlStart, centerl);
        MirrorPoint(PEMRArc(lpEMFR)^.ptlEnd, centerl);
      end;
    end;

    EMR_ANGLEARC:
    begin
      if Rotate then
        RotatePoint(PEMRAngleArc(lpEMFR)^.ptlcenter, centerl);
      if Flip then
        FlipPoint(PEMRAngleArc(lpEMFR)^.ptlcenter, centerl);
      if Mirror then
        MirrorPoint(PEMRAngleArc(lpEMFR)^.ptlcenter, centerl);
    end;

    EMR_POLYLINE, EMR_POLYBEZIER, EMR_POLYGON, EMR_POLYBEZIERTO, EMR_POLYLINETO:
    begin
      if Rotate then
        RotateRect(PEMRPolyline(lpEMFR)^.rclBounds, centerl);
      if Flip then
        FlipRect(PEMRPolyline(lpEMFR)^.rclBounds, centerl);
      if Mirror then
        MirrorRect(PEMRPolyline(lpEMFR)^.rclBounds, centerl);
      for i:=0 to PEMRPolyline(lpEMFR)^.cptl-1 do
      begin
        if Rotate then
          RotatePoint(PEMRPolyline(lpEMFR)^.aptl[i], Centerl);
        if Flip then
          FlipPoint(PEMRPolyline(lpEMFR)^.aptl[i], Centerl);
        if Mirror then
          MirrorPoint(PEMRPolyline(lpEMFR)^.aptl[i], Centerl);
      end;
    end;

    EMR_POLYLINE16, EMR_POLYBEZIER16, EMR_POLYGON16, EMR_POLYBEZIERTO16, EMR_POLYLINETO16:
    begin
      if Rotate then
        RotateRect(PEMRPolyline16(lpEMFR)^.rclBounds, centerl);
      if Flip then
        FlipRect(PEMRPolyline16(lpEMFR)^.rclBounds, centerl);
      if Mirror then
        MirrorRect(PEMRPolyline16(lpEMFR)^.rclBounds, centerl);
      for i:=0 to PEMRPolyline16(lpEMFR)^.cpts-1 do
      begin
        if Rotate then
          RotateSmallPoint(PEMRPolyline16(lpEMFR)^.apts[i], Centerl);
        if Flip then
          FlipSmallPoint(PEMRPolyline16(lpEMFR)^.apts[i], Centerl);
        if Mirror then
          MirrorSmallPoint(PEMRPolyline16(lpEMFR)^.apts[i], Centerl);
      end;
    end;

    EMR_POLYDRAW:
    begin
      if Rotate then
        RotateRect(PEMRPolyDraw(lpEMFR)^.rclBounds, centerl);
      if Flip then
        FlipRect(PEMRPolyDraw(lpEMFR)^.rclBounds, centerl);
      if Mirror then
        MirrorRect(PEMRPolyDraw(lpEMFR)^.rclBounds, centerl);
      for i:=0 to PEMRPolyDraw(lpEMFR)^.cptl-1 do
      begin
        if Rotate then
          RotatePoint(PEMRPolyDraw(lpEMFR)^.aptl[i], Centerl);
        if Flip then
          FlipPoint(PEMRPolyDraw(lpEMFR)^.aptl[i], Centerl);
        if Mirror then
          MirrorPoint(PEMRPolyDraw(lpEMFR)^.aptl[i], Centerl);
      end;
    end;

    EMR_POLYDRAW16:
    begin
      if Rotate then
        RotateRect(PEMRPolyDraw16(lpEMFR)^.rclBounds, centerl);
      if Flip then
        FlipRect(PEMRPolyDraw16(lpEMFR)^.rclBounds, centerl);
      if Mirror then
        MirrorRect(PEMRPolyDraw16(lpEMFR)^.rclBounds, centerl);
      for i:=0 to PEMRPolyDraw16(lpEMFR)^.cpts-1 do
      begin
        if Rotate then
          RotateSmallPoint(PEMRPolyDraw16(lpEMFR)^.apts[i], Centerl);
        if Flip then
          FlipSmallPoint(PEMRPolyDraw16(lpEMFR)^.apts[i], Centerl);
        if Mirror then
          MirrorSmallPoint(PEMRPolyDraw16(lpEMFR)^.apts[i], Centerl);
      end;
    end;

    EMR_POLYPOLYLINE, EMR_POLYPOLYGON:
    begin
      if Rotate then
        RotateRect(PEMRPolyPolyLine(lpEMFR)^.rclBounds, centerl);
      if Flip then
        FlipRect(PEMRPolyPolyLine(lpEMFR)^.rclBounds, centerl);
      if Mirror then
        MirrorRect(PEMRPolyPolyLine(lpEMFR)^.rclBounds, centerl);
      for i:=0 to PEMRPolyPolyLine(lpEMFR)^.cptl-1 do
      begin
        if Rotate then
          RotatePoint(PEMRPolyPolyLine(lpEMFR)^.aptl[i], Centerl);
        if Flip then
          FlipPoint(PEMRPolyPolyLine(lpEMFR)^.aptl[i], Centerl);
        if Mirror then
          MirrorPoint(PEMRPolyPolyLine(lpEMFR)^.aptl[i], Centerl);
      end;
    end;

    EMR_POLYPOLYLINE16, EMR_POLYPOLYGON16:
    begin
      if Rotate then
        RotateRect(PEMRPolyPolyLine16(lpEMFR)^.rclBounds, centerl);
      if Flip then
        FlipRect(PEMRPolyPolyLine16(lpEMFR)^.rclBounds, centerl);
      if Mirror then
        MirrorRect(PEMRPolyPolyLine16(lpEMFR)^.rclBounds, centerl);
      for i:=0 to PEMRPolyPolyLine16(lpEMFR)^.cpts-1 do
      begin
        if Rotate then
          RotateSmallPoint(PEMRPolyPolyLine16(lpEMFR)^.apts[i], Centerl);
        if Flip then
          FlipSmallPoint(PEMRPolyPolyLine16(lpEMFR)^.apts[i], Centerl);
        if Mirror then
          MirrorSmallPoint(PEMRPolyPolyLine16(lpEMFR)^.apts[i], Centerl);
      end;
    end;

    EMR_EXTSELECTCLIPRGN:
    begin
     //Nothing
    end;

    EMR_SCALEVIEWPORTEXTEX, EMR_SCALEWINDOWEXTEX, EMR_SETWORLDTRANSFORM,
    EMR_MODIFYWORLDTRANSFORM, EMR_INVERTRGN, EMR_PAINTRGN, EMR_FILLRGN,
    EMR_FRAMERGN, EMR_EXTTEXTOUTA, EMR_EXTTEXTOUTW,
    EMR_POLYTEXTOUTA, EMR_POLYTEXTOUTW :
    begin
        // Nothing
    end;
  end;
end;

procedure TransformEMF(emf: HENHMETAFILE; DoRotate, DoFlip, DoMirror: boolean);
var
  metaHeader: TEnhMetaHeader;
begin
  Rotate:= DoRotate;
  Flip:= DoFlip;
  Mirror:= DoMirror;
  GetEnhMetaFileHeader(emf, SizeOf(TEnhMetaHeader), @metaHeader);
  with metaHeader do
    centerl:= Point((rclBounds.Left + rclBounds.Right) div 2,
                   (rclBounds.Top + rclBounds.Bottom) div 2);
  EnumEnhMetaFile(0, emf, @EnhMetaFileProc_Manipulate, nil, Rect(0, 0, 0, 0));
end;

end.




https://stackoverflow.com/questions/20135498/is-it-possible-to-rotate-the-metafile-image-without-converting-it-to-the-bitmap

unit UEmfRotate;
{

  Use:
  var
    FRotationPos : TRotationPosition;

    FRotationPos := GetNewPosition(Clockwise, FRotationPos);
    UEmfRotate.RotateMetafile(Filename, image1, FRotationPos);

}

interface

uses
  Types, ExtCtrls;

type
  TRotationPosition = -3 .. 3;

procedure RotateMetafile(const Path: string; image: TImage; Position: TRotationPosition);
function GetNewPosition(Clockwise: boolean; OldPosition: TRotationPosition): TRotationPosition;

implementation

uses
  Windows, Graphics, Forms, Math;
{
  // Resolved: Fast increasing rotation time after about 15 rotations.
  // Resolved: Control panel Display Change (dimension of all elements)
  // Resolved: Loose of CreatedBy and Description after rotation
}

{

  All destination positions from -3 to 3 (-270.. 270)
  0     1      2     3
  WWW   AW    AAA    WA
  AAA   AW    WWW    WA
        AW           WA

  0     -1    -2     -3
  WWW   WA    AAA     AW
  AAA   WA    WWW     AW
        WA            AW

}

type
  TDestinationArray = array [boolean, TRotationPosition] of TRotationPosition;
  TDegrees = array [TRotationPosition] of cardinal;

const                     // OldPosition  -3  -2  -1   0  -1  -2  -3    Clockwise
  DestinationArray: TDestinationArray = (( 0, -3, -2, -1,  0,  1,  2),  // False
                                         (-2, -1,  0,  1,  2,  3,  0)); // True
          // Position  -3,  -2,  -1, 0,  1,   2,   3
  Degrees: TDegrees = (90, 180, 270, 0, 90, 180, 270);

function GetNewPosition(Clockwise: boolean;
  OldPosition: TRotationPosition): TRotationPosition;
begin
  Result := DestinationArray[Clockwise, OldPosition];
end;

function GetDegrees(Position: Integer): cardinal;
begin
  Result := Degrees[Position];
end;

function GetScreenSize(out Size: TSize): boolean;
// Used to correct for a change in windows global display settings.
const
  ENUM_CURRENT_SETTINGS: DWORD = $FFFFFFFF;
var
  DevMode: TDevMode;
begin
  Size.cx := 0;
  Size.cy := 0;
  DevMode.dmSize := SizeOf(TDevMode);
  Result := EnumDisplaySettings(nil, ENUM_CURRENT_SETTINGS, DevMode);
  if Result then
  begin
    Size.cx := DevMode.dmPelsWidth;
    Size.cy := DevMode.dmPelsHeight;
  end;
end;

procedure RotateMetafile90(image: TImage);
var
  DestMetafile: TMetafile;
  DestCanvas: TMetafileCanvas;
  TransformMatrix: XFORM;
  w, h: Integer;
  w1, h1: Integer;
  ScreenSize: TSize;
begin

  w := image.Picture.Width;
  h := image.Picture.Height;
  // Get screen dimension independent of the control panel display settings.
  if GetScreenSize(ScreenSize) then
  begin
    w1 := MulDiv(w, Screen.Width, ScreenSize.cx);
    h1 := MulDiv(h, Screen.Height, ScreenSize.cy);
  end
  else
  begin
    // Can not do anything
    w1 := w;
    h1 := h;
  end;
  DestMetafile := TMetafile.Create;
  DestMetafile.Enhanced := True;
  DestMetafile.SetSize(h1, w1);
  try
    DestCanvas := TMetafileCanvas.CreateWithComment(DestMetafile, 0,
      image.Picture.Metafile.CreatedBy, image.Picture.Metafile.Description);
    DestCanvas.Lock;
    Try

      SetGraphicsMode(DestCanvas.Handle, GM_ADVANCED);
      SetMapMode(DestCanvas.Handle, MM_TEXT);

      Fillchar(TransformMatrix, SizeOf(TransformMatrix), 0);
      TransformMatrix.eM11 := 0;  // Cos(Angle);
      TransformMatrix.eM12 := 1;  // Sin(Angle);
      TransformMatrix.eM21 := -1; // -Sin(Angle);
      TransformMatrix.eM22 := 0;  // Cos(Angle);
      TransformMatrix.eDx := h;
      TransformMatrix.eDy := 0;

      SetWorldTransform(DestCanvas.Handle, TransformMatrix);

      DestCanvas.Draw(0, 0, image.Picture.Graphic); // Same as Play

    Finally
      DestCanvas.Unlock;
      DestCanvas.Free();
    End;

    image.Picture := nil;
    image.Picture.Metafile.Assign(DestMetafile);

  finally
    DestMetafile.Free;
  end;
end;

procedure RotateMetafile180(image: TImage);
var
  DestMetafile: TMetafile;
  DestCanvas: TMetafileCanvas;
  TransformMatrix: XFORM;
  w, h: Integer;
  w1, h1: Integer;
  ScreenSize: TSize;
begin

  w := image.Picture.Width;
  h := image.Picture.Height;
  // Get screen dimension independent of the control panel display settings.
  if GetScreenSize(ScreenSize) then
  begin
    w1 := MulDiv(w, Screen.Width, ScreenSize.cx);
    h1 := MulDiv(h, Screen.Height, ScreenSize.cy);
  end
  else
  begin
    // Can not do anything
    w1 := w;
    h1 := h;
  end;
  DestMetafile := TMetafile.Create;
  DestMetafile.Enhanced := True;
  DestMetafile.SetSize(w1, h1);
  try
    DestCanvas := TMetafileCanvas.CreateWithComment(DestMetafile, 0,
      image.Picture.Metafile.CreatedBy, image.Picture.Metafile.Description);
    DestCanvas.Lock;
    Try

      SetGraphicsMode(DestCanvas.Handle, GM_ADVANCED);
      SetMapMode(DestCanvas.Handle, MM_TEXT);

      Fillchar(TransformMatrix, SizeOf(TransformMatrix), 0);
      TransformMatrix.eM11 := -1; // Cos(Angle);
      TransformMatrix.eM12 := 0;  // Sin(Angle);
      TransformMatrix.eM21 := 0;  // -Sin(Angle);
      TransformMatrix.eM22 := -1; // Cos(Angle);
      TransformMatrix.eDx := w;
      TransformMatrix.eDy := h;

      SetWorldTransform(DestCanvas.Handle, TransformMatrix);

      DestCanvas.Draw(0, 0, image.Picture.Graphic); // Same as Play

    Finally
      DestCanvas.Unlock;
      DestCanvas.Free();
    End;

    image.Picture := nil;
    image.Picture.Metafile.Assign(DestMetafile);

  finally
    DestMetafile.Free;
  end;
end;

procedure RotateMetafile270(image: TImage);
var
  DestMetafile: TMetafile;
  DestCanvas: TMetafileCanvas;
  TransformMatrix: XFORM;
  w, h: Integer;
  w1, h1: Integer;
  ScreenSize: TSize;
begin

  w := image.Picture.Width;
  h := image.Picture.Height;
  // Get screen dimension independent of the control panel display settings.
  if GetScreenSize(ScreenSize) then
  begin
    w1 := MulDiv(w, Screen.Width, ScreenSize.cx);
    h1 := MulDiv(h, Screen.Height, ScreenSize.cy);
  end
  else
  begin
    // Can not do anything
    w1 := w;
    h1 := h;
  end;
  DestMetafile := TMetafile.Create;
  DestMetafile.Enhanced := True;
  DestMetafile.SetSize(h1, w1);
  try
    DestCanvas := TMetafileCanvas.CreateWithComment(DestMetafile, 0,
      image.Picture.Metafile.CreatedBy, image.Picture.Metafile.Description);
    DestCanvas.Lock;
    Try

      SetGraphicsMode(DestCanvas.Handle, GM_ADVANCED);
      SetMapMode(DestCanvas.Handle, MM_TEXT);

      Fillchar(TransformMatrix, SizeOf(TransformMatrix), 0);
      TransformMatrix.eM11 := 0;  // Cos(Angle);
      TransformMatrix.eM12 := -1; // Sin(Angle);
      TransformMatrix.eM21 := 1;  // -Sin(Angle);
      TransformMatrix.eM22 := 0;  // Cos(Angle);
      TransformMatrix.eDx := 0;
      TransformMatrix.eDy := w;

      SetWorldTransform(DestCanvas.Handle, TransformMatrix);

      DestCanvas.Draw(0, 0, image.Picture.Graphic); // Same as Play

    Finally
      DestCanvas.Unlock;
      DestCanvas.Free();
    End;

    image.Picture := nil;
    image.Picture.Metafile.Assign(DestMetafile);

  finally
    DestMetafile.Free;
  end;
end;

procedure RotateMetafile(const Path: string; image: TImage;
  Position: TRotationPosition);
{
  Cumulative rotating causes increasing execution time
  With cumulative rotating i mean rotate an image already rotated
         ENHMETAHEADER         Size
  Angle  nHandles nRecords   (Bytes)
  0           4       173      4192
  90          7       214      5372
  180        10       273      6998
  270        13       354      9352
  360        16       479     13212
  450        19       692     20064
  540        22      1081     36864

  To avoid this never rotate an already rotated image, but rotate the
  original image.

}
begin
  image.Picture.Metafile.LoadFromFile(Path);
  Assert(image.Picture.Graphic is TMetafile);
  case GetDegrees(Position) of
    90:
      RotateMetafile90(image);
    180:
      RotateMetafile180(image);
    270:
      RotateMetafile270(image);
  end;
  // image.Picture.SaveToFile('emf.emf');
end;

end.







2019/06/07 15:13 2019/06/07 15:13
Article tag list Go to top
View Comment 0
Trackback URL :: 이 글에는 트랙백을 보낼 수 없습니다
 
 
 
 
PREV : [1][2][3][4][5] ... [1404] :
«   2019/06   »
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            
전체 (1404)
출판 준비 (0)
My-Pro... (41)
여행 (42)
사는 ... (954)
블로그... (25)
My Lib... (32)
게임 ... (23)
개발관... (3)
Smart ... (1)
C Builder (0)
Object... (0)
VC, MF... (9)
Window... (1)
Open API (3)
Visual... (0)
Java, JSP (2)
ASP.NET (0)
PHP (4)
리눅스 (28)
Windows (27)
Device... (1)
Embedded (1)
게임 ... (0)
Web Se... (2)
Web, S... (19)
잡다한... (4)
프로젝트 (0)
대통령... (9)
Link (2)
Delphi (96)
Reference (1)
OpenSo... (5)
Apache (2)
Database (21)
프로그램 (0)