Un meilleur job mieux payé ?

Deviens chef de projet, développeur, ingénieur, informaticien

Mets à jour ton profil pro

ça m'intéresse

Developpez.com - Delphi
X

Choisissez d'abord la catégorieensuite la rubrique :


Transformation de metafile Windows (rotation, miroir, inversion)

Date de publication : 26/02/2005

Par Pierre Castelain (Contributions)
 

Routine Delphi de transformation d'un metafile Windows (image au format vectoriel)



Voici une unité contenant une procédure de transformation d'un metafichier Windows. Les metafichiers (wmf ou emf) sont des fichiers images contenant la description vectorielle d'un dessin. Ils ont l'avantage de pouvoir être redimensionnés sans perte de qualité. Par contre, leur modification en mémoire est assez fastidieuse.

Le source suivant vous permet d'appliquer plusieurs transformations à un de ces fichiers en mémoire : rotation (dans le sens inverse des aiguilles d'une montre, inversion (haut-bas) et miroir (droite-gauche).

Pour l'utiliser, passez le handle d'un TMetafile à la procédure en indiquant les transformations désirées.

Ce code source n'est pas parfait car la transformation de certains ordres GDI n'est pas supportée. Par exemple, si le metafile contient du texte, celui-ci ne subira pas les transformations.

GDI+ vous permet d'appliquer des transformations beaucoup plus évoluées lors du tracé. Vous êtes encouragés à l'utiliser, mais si pour une raison quelconque cela n'est pas possible, vous pouvez utiliser cette unité.

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.
Vous pouvez directement télécharger cette unité ici : EMFTransform.pas


Articles
Delphi 2005 : Découvrez le futur Delphi 2005
DirectX : Introduction à DirectX 9 en Delphi
Variables d'environnement : Présentation, description et utilisation des variables d'environnement sous Windows
Mailslots : Présentation des mailslots et de leur utilisation en Delphi pour la communication inter-processus
Projets complets avec sources
NumericalParser : Parser numérique en Delphi afin de transformer une chaîne de caractères en valeur flottante ou entière.
RegSearch : Composant de recherche dans la base de registre
CDAReader : Lecture des informations contenues dans les fichier CDA de Windows
ScreenSaverPreview : Composant d'affichage de l'aperçu des économiseurs d'écran de Windows
ScanResources : Programme d'exploration des ressources des programmes ou des dll d'un répertoire
ClipboardViewer : Démonstration de la détection des modifications et de l'affichage du contenu du presse-papier
Matrix : Tentative de reproduction en Delphi de l'animation bien connue du film Matrix
Sources et exemples
EMFTransform : Transformation (rotation, inversion, miroir) d'un metafile Windows en mémoire
DeleteKeyTree : Suppression récursive d'un clé de la base de registre
MultiStrings : Routines de gestion de tableaux de chaînes C
GetDllFilename : Pour récupérer le chemin d'une dll par son handle
Extension du shell : Exemple d'extension du menu contextuel du shell de Windows
TriStringGrid : Exemple de tri par colonne d'un composant TStringGrid à l'aide d'un algorithme de tri rapide (quick sort)
XPManifestCPL : Utilisation des contrôles XP dans une application du panneau de configuration (cpl)
Bouboules : Modélisation à l'aide du design pattern Observer
Divers
Diagramme ternaire : Un logiciel gratuit de tracé de diagramme ternaire


Copyright © Pierre Castelain. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Responsables bénévoles de la rubrique Delphi : Gilles Vasseur - Alcatîz -