10.03.2014 Views

API - Chapitre 03.pdf - IUT d'Arles

API - Chapitre 03.pdf - IUT d'Arles

API - Chapitre 03.pdf - IUT d'Arles

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

3. Affichage graphique<br />

3.1 Graphics Device Interface (GDI)<br />

Le GDI (Graphics Device Interface) est un ensemble de fonctions de<br />

l’<strong>API</strong> Windows permettant de dessiner à l’écran, en mémoire ou sur<br />

imprimante.<br />

Ces fonctions permettent le tracé de primitives graphiques (points,<br />

lignes, rectangles, cercles, …), d’images bitmap ou encore de texte.<br />

Le GDI fonctionne autour du principe de « Device Context » (DC),<br />

représenté par le type HDC (« Handle to Device Context »).<br />

1


Un HDC désigne un endroit sur lequel on peut dessiner : l’écran<br />

tout entier, une fenêtre toute entière, la zone client d’une fenêtre, une<br />

image stockée en mémoire ou une imprimante.<br />

Pour afficher sur un périphérique à sortie graphique, il faut toujours<br />

avoir un DC lié à celui-ci.<br />

En donnant un handle sur ce DC à une fonction GDI on indique à<br />

Windows sur quel périphérique de sortie on souhaite travailler.<br />

indépendance vis à vis du matériel. On utilise le même code pour<br />

dessiner à l’écran ou sur une imprimante.<br />

2


Le cas le plus courant d’affichage se fait dans la zone client de la<br />

fenêtre.<br />

Y<br />

mini<br />

X<br />

mini<br />

Y maxi<br />

= zone<br />

client<br />

X maxi<br />

3


Système de coordonnées<br />

GDI trace les primitives graphiques (points, lignes,<br />

rectangles, etc.), les images, le texte, dans un<br />

système de coordonnées.<br />

Un moniteur réalise l’affichage sur une matrice<br />

rectangulaire de points appelés pixels .<br />

Les algorithmes de tracés de figure de GDI<br />

permettent de donner une couleur à certains de ces<br />

pixels (ici pour tracer une ligne).<br />

4


3.2 Evolution de GDI : GDI+<br />

Nombreuses innovations :<br />

Chargement d’images (BMP, JPG, TIFF, PNG, GIF, ICO, …)<br />

Nouvelles primitives graphiques (courbes, …)<br />

Nouveaux types de tracés (flèche, …)<br />

Transformations (rotations, symétries, …)<br />

Ajustements (contraste, luminosité, netteté, …)<br />

…<br />

La plupart des méthodes de GDI+ sont surchargées : nombreuses<br />

syntaxes différentes.<br />

Plus d’infos sur le MSDN (MicroSoft Developper Network) :<br />

msdn.microsoft.com/<br />

5


3.2.1 Configuration<br />

Fichiers nécessaires :<br />

gdiplus.dll : La DLL<br />

gdiplus.lib : La librairie<br />

gdiplus*.h : Les fichiers d’en-tête<br />

Le VC++ doit être configuré de manière à connaître le chemin des<br />

fichiers d’include et de librairies de GDI+ :<br />

6


Paramètres :<br />

Dans le menu Projet, sélectionnez Propriétés. Dans la boîte qui<br />

apparaît, ajoutez gdiplus.lib dans le champ Dépendances<br />

supplémentaires de l’onglet Éditeur de liens / Entrée.<br />

7


Initialisation :<br />

Au début de votre programme, rajoutez les lignes suivantes :<br />

#include <br />

using namespace Gdiplus;<br />

ULONG_PTR m_gdiplusToken;<br />

8


Au début de votre programme, on initialise GDI+ avec les instructions<br />

suivantes :<br />

GdiplusStartupInput gdiplusStartupInput;<br />

GdiplusStartup(&m_gdiplusToken,&gdiplusStartupInput,NULL);<br />

A la fin de votre programme, on quitte proprement GDI+ avec<br />

l’instruction suivante :<br />

GdiplusShutdown(m_gdiplusToken);<br />

9


3.2.2 La classe Graphics<br />

Toutes les fonctionnalités graphiques de GDI+ sont des méthodes de la<br />

classe Graphics.<br />

Un objet de classe Graphics s’obtient en fournissant au constructeur<br />

le handle de contexte de périphérique.<br />

Ex: dans WindowsProc() :<br />

case WM_PAINT:<br />

HDC hdc;<br />

hdc = BeginPaint(handle_fenetre, &PaintST);<br />

Graphics graphics(hdc);<br />

Pen crayon(Color(255, 255, 0, 0));<br />

graphics.DrawLine(&crayon, 0, 0, 200, 100);<br />

EndPaint(handle_fenetre, &PaintST);<br />

return 0;<br />

10


Obtenir un contexte de périphérique sur une fenêtre<br />

Deux possibilités :<br />

1. Dans WindowProc(), lors de l’interception du message WM_PAINT,<br />

on peut obtenir un DC avec BeginPaint() .<br />

case WM_PAINT :<br />

HDC hdc = BeginPaint(handle_fenetre,&PaintSt);<br />

2. Ailleurs, pour obtenir un DC il faut utiliser la fonction GetDC().<br />

HDC hdc = GetDC (handle_fenetre);<br />

11


Suppression de contexte de périphérique<br />

Lorsqu’on n’a plus besoin d’un DC, il faut le supprimer. La fonction à<br />

utiliser dépend de comment on a obtenu le DC :<br />

1. Si on a obtenu le DC avec BeginPaint() :<br />

HDC hdc = BeginPaint(handle_fenetre,&PaintSt);<br />

alors il faut le supprimer avec EndPaint() :<br />

EndPaint(handle_fenetre,&PaintSt);<br />

2. Si on a obtenu le DC avec GetDC() :<br />

HDC hdc = GetDC (handle_fenetre);<br />

alors il faut le supprimer avec ReleaseDC() :<br />

ReleaseDC(handle_fenetre, hdc);<br />

12


3.2.3 La classe Color<br />

En informatique, on représente n’importe quelle couleur par un mélange<br />

de 3 couleurs de base : le rouge, le vert, le bleu (système RVB).<br />

C’est le principe de la synthèse additive (vu en cours de 2ème année).<br />

Si on mélange du rouge, du vert et du bleu avec 256 nuances chacun,<br />

alors on peut obtenir 16,7 millions de couleurs (256x256x256).<br />

R V B<br />

Noir 0 0 0<br />

Bleu 0 0 255<br />

Vert 0 255 0<br />

Cyan 0 255 255<br />

Rouge 255 0 0<br />

Magenta 255 0 255<br />

Jaune 255 255 0<br />

Blanc 255 255 255<br />

13


GDI+ définit une couleur ARVB avec la classe Color.<br />

Nb bits<br />

=<br />

8 8 8 Nb bits 8 8 8 8<br />

=<br />

Un pixel RVB<br />

(24 bits)<br />

Un pixel ARVB<br />

(32 bits)<br />

Alpha = 0 : pixel complètement transparent<br />

Alpha = 255 : pixel complètement opaque<br />

0 < Alpha < 255 : pixel plus ou moins translucide<br />

A R V B<br />

Color c1(255, 255, 0, 0); // Rouge opaque<br />

Color c2(128, 0, 255, 0); // Vert à moitié transparent<br />

14


3.2.4 La classe Pen<br />

Classe de « crayon » définissant le style de tracé. On peut définir la<br />

couleur, l’épaisseur, les extrémités (flèche, rond, etc.), l’apparence<br />

(solide, pointillés, etc.).<br />

Constructeurs de la classe Pen :<br />

Pen::Pen(Color couleur); // Epaisseur = 1 pixel<br />

Pen::Pen(Color couleur, int epaisseur);<br />

Exemple :<br />

Pen crayon(Color(255, 255, 0, 0));<br />

// Crayon Rouge<br />

15


3.2.5 Tracé de lignes<br />

Pen crayon(Color(255, 255, 0, 0)); // Rouge<br />

graphics.DrawLine(&crayon, 10, 20, 200, 100);<br />

On définit d’abord un pointeur sur le crayon à utiliser, puis les<br />

coordonnées des deux extrémités.<br />

16


Définition des extrémités de lignes<br />

Pen crayon(Color(255, 0, 0, 255),20);<br />

crayon.SetLineCap(LineCapRound,<br />

LineCapArrowAnchor,<br />

DashCapRound);<br />

graphics.DrawLine(&crayon, 20, 20,200, 80);<br />

17


Effet de l’alpha blending<br />

Alpha faible (max=255) couleur<br />

transparente<br />

Pen crayon(Color(80, 0, 0, 255),40);<br />

graphics.DrawLine(&crayon, 10, 20,280, 150);<br />

18


3.2.6 Tracé de rectangles<br />

Graphics::DrawRectangle(Pen *crayon, int x, int y,<br />

int largeur, int hauteur);<br />

Exemple:<br />

graphics.DrawRectangle(&crayon, 100, 50, 80, 40);<br />

100<br />

50<br />

40<br />

80<br />

19


3.2.7 Tracé d’ellipses<br />

Graphics::DrawEllipse(Pen *crayon, int x, int y,<br />

int largeur, int hauteur);<br />

Exemple:<br />

graphics.DrawEllipse(&crayon, 100, 50, 80, 40);<br />

100<br />

50<br />

40<br />

80<br />

20


3.2.8 Tracé de polygones<br />

Point liste_points[] = {Point(60, 180), Point(30, 60)};<br />

Point(120, 80), Point(170, 20),<br />

Point(220, 100)};<br />

graphics.DrawPolygon(&crayon, liste_points, 5);<br />

(170, 20)<br />

(30, 60)<br />

(120, 80)<br />

(60, 180)<br />

(220, 100)<br />

class Point<br />

{<br />

int X,<br />

Y;<br />

}<br />

(définie par<br />

GDI+)<br />

21


3.2.9 Tracé de courbes splines<br />

Courbe passant par des points de contrôle.<br />

Point liste_points[] = {Point(60, 180), Point(30, 60)};<br />

Point(120, 80), Point(170, 20),<br />

Point(220, 100)};<br />

graphics.DrawCurve(&crayon, liste_points, 5, 1.0f);<br />

22


Dernier paramètre = « tension »<br />

graphics.DrawCurve(&crayon, liste_points, 5, 1.0f );<br />

Tension = 0.0f Tension = 1.0f Tension = 2.0f<br />

23


3.2.10 Tracé de courbes de Bézier<br />

Courbe influencée par des points de contrôle. La courbe passe par le<br />

premier point et par le dernier, mais pas par les autres.<br />

graphics.DrawBezier(&crayon, 60,180, 30,60,<br />

170,20, 220,100);<br />

(30, 60)<br />

(170, 20)<br />

(220, 100)<br />

(60, 180)<br />

24


3.2.11 Remplissage de formes avec des brosses<br />

On a vu comment afficher des contours de formes (rectangles,<br />

ellipses, polygones). Il existe l’équivalent de ces fonctions pour<br />

l’affichage de formes remplies.<br />

DrawRectan<br />

gle<br />

DrawEllip<br />

se<br />

DrawPolyg<br />

on<br />

FillRectan<br />

gle<br />

FillEllips<br />

e<br />

FillPolygo<br />

n<br />

Alors que les fonctions de tracé de contour de formes attendent en 1 er<br />

paramètre l’adresse d’un crayon, les fonctions de tracé de formes remplies<br />

attendent en 1 er paramètre l’adresse d’une brosse.<br />

25


Il existe différents types de brosses (« brush ») permettant de remplir<br />

des formes :<br />

La classe SolidBrush<br />

SolidBrush brosse(Color(255, 255, 0, 0));<br />

graphics.FillEllipse(&brosse, 100, 50, 160, 80);<br />

26


La classe HatchBrush<br />

HatchBrush brosse(HatchStyleVertical,<br />

Color(255, 0, 0, 255),<br />

Color(255, 0, 255, 0));<br />

graphics.FillEllipse(&brosse, 100, 50, 160, 80);<br />

GDI+ offre plus de 50 types de<br />

hachures.<br />

27


La classe TextureBrush<br />

Image image(L"rosace.bmp");<br />

TextureBrush brosse(&image);<br />

graphics.FillEllipse(&brosse, 100, 50, 160, 80);<br />

rosace.bmp<br />

Note: le constructeur<br />

de la classe Image<br />

(vue plus loin dans le<br />

cours) attend en<br />

paramètre un nom de<br />

fichier.<br />

La chaîne de<br />

caractères doit être<br />

codée en Unicode (2<br />

octets par caractère).<br />

28


3.2.12 Clipping<br />

Le « clipping » ou « découpage » permet de restreindre l’affichage à<br />

une région donnée.<br />

Region region(Rect(20, 30, 100, 50));<br />

graphics.DrawRectangle(&crayon, 20, 30, 100, 50);<br />

graphics.SetClip(&region, CombineModeReplace);<br />

graphics.DrawLine(&crayon, 0, 0, 200, 200);<br />

Sans<br />

Avec<br />

Clipping d’une série<br />

d’ellipses par les<br />

contours d’un texte<br />

29


3.2.13 Antialiasing<br />

L’affichage se fait sur une matrice de pixels nombre limité de points,<br />

plus ou moins important en fonction de la résolution.<br />

Apparition de phénomènes « d’aliassage » (« aliasing » en anglais)<br />

comme des effets de « marches d’escalier »<br />

Affichage<br />

normal<br />

Affichage avec<br />

antialiassage<br />

Solution : utiliser des algorithmes « d’antialiassage » (« antialiasing ») qui<br />

vont calculer des pixels supplémentaires, affichés avec transparence, pour<br />

atténuer les effets de pixelisation.<br />

30


Une fonction GDI+ permet d’utiliser de l’antialiasing lors du tracé de<br />

lignes, courbes, rectangles, ellipses, etc. :<br />

Prototype :<br />

Graphics::SetSmoothingMode(SmoothingMode mode);<br />

Exemple :<br />

graphics.SetSmoothingMode(SmoothingModeAntiAlias);<br />

graphics.DrawEllipse(&crayon, 20, 20, 80, 40);<br />

graphics.SetSmoothingMode(SmoothingModeAntiAlias);<br />

graphics.DrawEllipse(&crayon, 20, 70, 80, 40);<br />

Remarque : L’antialiassage<br />

permet une meilleure qualité<br />

d’affichage mais est plus lent<br />

en raison des calculs<br />

supplémentaires.<br />

31


3.2.14 Affichage de texte<br />

FontFamily fontFamily(L"Times New Roman");<br />

Font font(&fontFamily, 24, FontStyleRegular, UnitPixel);<br />

PointF pointF(30.0f, 10.0f);<br />

SolidBrush solidBrush(Color(255, 0, 0, 255));<br />

graphics.DrawString(L"Hello",-1,&font,pointF,&solidBrush);<br />

32


Affichage de texte dans une zone rectangulaire<br />

FontFamily fontFamily(L"Arial");<br />

Font font(&fontFamily, 12, FontStyleBold, UnitPoint);<br />

RectF rectF(30.0f, 10.0f, 150.0f, 100.0f);<br />

SolidBrush solidBrush(Color(255, 0, 0, 255));<br />

graphics.DrawString(L"Affichage d'un texte dans un<br />

rectangle de 150x100 pixels", -1, &font, rectF, NULL,<br />

&solidBrush);<br />

33


Affichage de texte avec antialiasing<br />

Prototype :<br />

Graphics::SetTextRenderingHint(TextRenderingHint mode);<br />

Exemple :<br />

graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);<br />

graphics.DrawString(L"Hello",-1,&font,PointF(30.0f, 60.0f),<br />

&solidBrush);<br />

mode =<br />

TextRenderingHintSingleBit<br />

PerPixel<br />

TextRenderingHintSystem<br />

Default<br />

TextRenderingHintAnt<br />

iAlias<br />

34


3.2.15 Affichage d’images<br />

Image : « bitmap » = matrice de pixels<br />

Pixel = « PICture ELement »<br />

Largeur (nb pixels)<br />

Un pixel<br />

Hauteur<br />

(nb<br />

pixels)<br />

Agrandissement d’une<br />

partie de l’image (œil)<br />

35


Pour afficher une image à l’écran avec le GDI :<br />

1. Charger l’image du disque vers la mémoire<br />

2. Copier l’image de la mémoire vers la fenêtre<br />

1 2<br />

Mémoire<br />

Disque<br />

Fenêtre<br />

36


Classe Image<br />

Pour afficher une image, il faut un objet de classe Graphics et un<br />

objet de classe Image. La classe Image permet de charger des images<br />

aux formats BMP, GIF, JPEG, PNG, TIFF, WMF, EMF, ICO.<br />

Image img(L"bird.jpg");<br />

Graphics graphics(hDC);<br />

img.GetWidth()<br />

img.GetHeight()<br />

37


Affichage<br />

La méthode DrawImage() de la classe Graphics a de nombreuses<br />

variantes (surcharges). En voici 3 :<br />

Image img(L"bird.jpg");<br />

Graphics graphics(hDC);<br />

1<br />

graphics.DrawImage(&img, 20, 10);<br />

38


2<br />

Graphics::DrawImage(Image* image,<br />

int xDestination, int yDestination,<br />

int xSource, int ySource,<br />

int largeurSource, int hauteurSource)<br />

xSource<br />

ySource<br />

xDestination<br />

yDestination<br />

hauteurSource<br />

largeurSource<br />

DrawImag<br />

e()<br />

Source<br />

Destination<br />

39


3<br />

Graphics::DrawImage(Image* image,<br />

Rect Dest,<br />

int xSource, int ySource,<br />

int largeurSource, int hauteurSource)<br />

xSource<br />

ySource<br />

hauteurSource<br />

Dest.top<br />

Dest.left<br />

largeurSource<br />

Dest.bottom<br />

Source<br />

DrawImag<br />

e()<br />

Dest.right<br />

Destination<br />

40


Gestion de la transparence<br />

Certains formats de fichiers d’image gèrent la transparence. Soit avec<br />

une seule couleur considérée comme transparente (ex: GIF), soit avec<br />

un canal alpha par pixel (ex: BMP, PNG, TGA).<br />

Quand on affiche une telle image, on peut voir ce qui avait déjà été<br />

affiché au travers des pixels transparents.<br />

Utile pour les « sprites » d’un jeu 2D, pour l’affichage de couches<br />

transparentes à la manière d’un dessin animé, etc.<br />

+<br />

Couleur<br />

41

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!