Créer et utiliser une classe image en C++


La présente page vient à la suite des pages suivantes qu'elle complète :
1) Structure d'un fichier TIFF non compressé
2) Modifier une image transparente en C++.
Elle montre comment créer et utiliser une classe image en C++ afin de modifier facilement une image tiff transparente non compressée créée avec Gimp (Cette classe a été testée avec les versions 2.4 et 2.8 de Gimp) . Cette technique peut servir à divers usages, notamment à la création d'une infinité de cadres photos originaux.

1) Créer la classe mytif

1.1) Composition de la classe mytif

La classe mytif est associée à une image créée avec Gimp, dotée d'un canal de transparence, et enregistrée dans un fichier tif sans compression. Cette classe comprend les données et méthodes suivantes :

Données

  • int W : Largeur de l'image en pixels ;
  • int H : Hauteur de l'image en pixels ;
  • char src_file [18+1] : chemin et nom du fichier image de départ, créé avec Gimp ("C:/ modele_gimp.tif" par exemple);
  • char dst_file [18+1] : chemin et nom du fichier image modifié par le programme ("C:/ modele_sauv.tif" par exemple);
  • int nbytes : taille du fichier image en octets;
  • FILE *pf : pointeur vers le fichier image une fois celui-ci chargé en mémoire ;
  • unsigned char * t : tableau (dynamique) à 1 dimension contenant les nbytes du fichier une fois celui ci chargé en mémoire.

Méthodes

  • mytif() : constructeur de la classe. Le constructeur de mytif ouvre et charge en mémoire, dans le tableau t (créé en dynamqiue avec l'instruction malloc) , un fichier tif créé puis enregistré sans compression avec Gimp ("C:/modele_gimp.tif" par exemple). Le constructeur calcule et mémorise dans la donnée membre nbytes le nombre d'octets de ce fichier. Il effectue un contrôle de la présence du fichier et un contrôle de la cohérence entre la taille de ce fichier d'une part et la hauteur et la largeur de l'image associée d'autre part. En cas d'absence du fichier ou d'incohérence détectée, le programme se termine aussitôt avec un message d'erreur. Remarque : la création du tableau t de façon dynamique est obligatoire car une création statique, à l'aide d'une déclaration du type "unsigned char t [nbytes]", fonctionne correctement avec des tableaux de petites ou de moyennes tailles mais ne fonctionne pas avec des tableaux de très grandes tailles comme c'est le cas ici.
  • ~mytif() : destructeur de la classe; Le destructeur de la classe libère, à la fin de l'exécution du programme, la mémoire occupée par le tableau t.
  • void setpixel_rgba (int i, int j, unsigned char r, unsigned char g, unsigned char b, unsigned char a) : cette méthode permet de modifier dans t [ ] la couleur du pixel i,j (ligne,colonne) de l'image, avec 0 <= i < H et 0 <= j < W
  • void setbox_rgba (int x0, int y0, int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a) : cette méthode permet de remplir, avec la couleur rgba, le rectangle situé entre les points de coordonnées (x0, y0) et (x1, y1)
  • void setrect_rgba (int x0, int y0, int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a); cette méthode permet de tracer, avec la couleur rgba, le rectangle situé entre les points de coordonnées (x0, y0) et (x1, y1)
  • void savetofile() : cette méthode permet d'enregistrer dans un fichier tif ("C:/modele_sauv.tif" par exemple) le contenu du tableau t [ ] une fois celui ci modifié par un traitement quelconque.

1

Utilisation de la classe mytif

Pour utiliser la classe mytif, il faut :

  • 1) Créer avec Gimp un fichier image tif de taille quelconque et doté d'un canal alpha de transparence. Enregistrer ce fichier sans compression, avec conservation des données de transparence et avec le chemin et le nom "C:/modele_gimp.tif" (par exemple);
  • 2) Vérifier que les dimensions WIDTH et HEIGHT de l'image sont correctement indiquées dans les instructions #define WIDTH et #define HEIGHT en début de programme. Vérifier également que le chemin et le nom du fichier de départ sont correctement indiqués dans l'instruction strcpy(src_file, "C:/ modele_gimp.tif"); située dans le constructeur mytif::mytif(). Vérifier enfin que le chemin et le nom du fichier modifié sont correctement indiqués dans l'instruction strcpy (dst_file, "C:/ modele_sauv.tif" ); située dans la méthode savetofile.;
  • 3) Déclarer, dans le corps du programme, un objet mytif img;
  • 4) Utiliser autant que de besoin les méthodes associées à cet objet. Par exemple : img.setpixel_rgba(0,0,0,0,0,0); img.setbox_rgba(0,0,WIDTH-1,HEIGHT-1, 0, 0, 0, 0); red=255; green= 255; blue= 255, alpha=255; img.setrect_rgba(20,20, WIDTH-1-20,HEIGHT-1-20, red, green, blue,alpha); img.savetofile(); ...

2) Ecrire un programme

/*
Classe mytif
Auteur C.Turrier - Juillet 2016
------
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------
*/
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
#define WIDTH 1200
#define HEIGHT 800
class mytif
{
public:
int W ;
int H ;
char src_file [18+1];
char dst_file [18+1];
int nbytes;
FILE *pf;
unsigned char * t;
mytif();
~mytif();
void setpixel_rgba (int i, int j, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
void setbox_rgba (int x0, int y0, int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
void setrect_rgba (int x0, int y0, int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
void savetofile();
};
mytif::mytif()
{
W=WIDTH;
H=HEIGHT;
strcpy(src_file, "C:/modele_gimp.tif");
//ouverture du fichier et calcul de sa taille
pf = fopen(src_file, "rb");
if( pf == NULL ){cout << "Erreur ! Fichier C:/modele_gimp.tif inexistant..." << endl; system ("pause");exit(0);}
fseek(pf, 0, SEEK_END);//positionnement à la fin du fichier
nbytes = ftell(pf);
cout << "Nombre d'octets du fichier : " << nbytes << endl;
rewind(pf); //positionnement au début du fichier
//écriture des octets du fichier dans t
t = (unsigned char *)malloc((nbytes+1)*sizeof(unsigned char));
fread(t, nbytes, 1, pf);
//controle taille
int p = W * H * 4 + 30; int q = W * H * 4 + 42;
if( p > nbytes ){cout << "Erreur ! dimensions image (#define WIDTH et HEIGHT) " << endl; system ("pause");exit(0);}
if( q > nbytes ){cout << "Erreur ! dimensions image (#define WIDTH et HEIGHT) " << endl; system ("pause");exit(0);}
int largeur = t[p] + 256 * t[p+1] + 256 * 256 * t[p+2] + 256 * 256* 256 * t[p+3];
int hauteur = t[q] + 256 * t[q+1] + 256 * 256 * t[q+2] + 256 * 256* 256 * t[q+3];
cout << "largeur image = " << largeur << " : Ok" << endl;
cout << "hauteur image = " << hauteur << " : Ok" << endl;
if( largeur != W ){cout << "Erreur ! dimensions image (#define WIDTH et HEIGHT) " << endl; system ("pause");exit(0);}
if( hauteur != H ){cout << "Erreur ! dimensions image (#define WIDTH et HEIGHT) " << endl; system ("pause");exit(0);}
fclose(pf);
}
mytif::~mytif()
{
free(t);
}
void mytif::savetofile ()
{
strcpy (dst_file, "C:/modele_sauv.tif" );
pf = fopen(dst_file,"w+b");
if( pf == NULL ){cout << "Erreur ! Fichier C:/modele_sauv.tif non enregistre..." << endl; system ("pause"); exit(0);}
for (int i=0;i < nbytes;i++){ fprintf (pf,"%c", t[i]);}
fclose(pf);
}
void mytif::setpixel_rgba (int i, int j, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
int k;
//r pixel ij
k = 8 + i*W*4 + j*4; t[k]=r;
//g pixel ij
k = 8 + i*W*4 + j*4 + 1; t[k]= g;
//b pixel ij
k = 8 + i*W*4 + j*4 + 2; t[k]= b;
//a pixel ij
k = 8 + i*W*4 + j*4 + 3; t[k]= a;
}
void mytif::setbox_rgba (int x0, int y0, int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
int k;
for( int i = y0; i <= y1; i++){
for( int j = x0; j <= x1; j++){
//r pixel ij
k = 8 + i*W*4 + j*4; t[k]=r;
//g pixel ij
k = 8 + i*W*4 + j*4 + 1; t[k]= g;
//b pixel ij
k = 8 + i*W*4 + j*4 + 2; t[k]= b;
//a pixel ij
k = 8 + i*W*4 + j*4 + 3; t[k]= a;
}}
}
void mytif::setrect_rgba (int x0, int y0, int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
int k;
//i=y0
for( int j = x0; j <= x1; j++){
k = 8 + y0*W*4 + j*4; t[k]=r; //r pixel ij
k = 8 + y0*W*4 + j*4 + 1; t[k]= g; //g pixel ij
k = 8 + y0*W*4 + j*4 + 2; t[k]= b; //b pixel ij
k = 8 + y0*W*4 + j*4 + 3; t[k]= a; //a pixel ij
}
//i=y1
for( int j = x0; j <= x1; j++){
k = 8 + y1*W*4 + j*4; t[k]=r; //r pixel ij
k = 8 + y1*W*4 + j*4 + 1; t[k]= g; //g pixel ij
k = 8 + y1*W*4 + j*4 + 2; t[k]= b; //b pixel ij
k = 8 + y1*W*4 + j*4 + 3; t[k]= a; //a pixel ij
}
//j=x0
for( int i = y0+1; i < y1; i++){
k = 8 + i*W*4 + x0*4; t[k]=r; //r pixel ij
k = 8 + i*W*4 + x0*4 + 1; t[k]= g; //g pixel ij
k = 8 + i*W*4 + x0*4 + 2; t[k]= b; //b pixel ij
k = 8 + i*W*4 + x0*4 + 3; t[k]= a; //a pixel ij
}
//j=x1
for( int i = y0+1; i < y1; i++){
k = 8 + i*W*4 + x1*4; t[k]=r; //r pixel ij
k = 8 + i*W*4 + x1*4 + 1; t[k]= g; //g pixel ij
k = 8 + i*W*4 + x1*4 + 2; t[k]= b; //b pixel ij
k = 8 + i*W*4 + x1*4 + 3; t[k]= a; //a pixel ij
}
}
int main ()
{
int u;
unsigned char red, green, blue, alpha;
mytif img;
//img.setpixel_rgba(0,0,0,0,0,0);
img.setbox_rgba(0,0,WIDTH-1,HEIGHT-1, 0, 0, 0, 0);
red=255; green= 255; blue= 255, alpha=255;
img.setrect_rgba(20,20, WIDTH-1-20,HEIGHT-1-20, red, green, blue,alpha);
for (u=0;u <20; u++)
{
alpha = alpha-10 ;
img.setrect_rgba(u,u, WIDTH-1-u , HEIGHT-1-u, red, green, blue, alpha);
}
img.savetofile();
cout << "fin traitement :" << img.nbytes << " octets : Ok"<< endl;
system("pause");
return (0);
}

2

Télécharger le code source main.cpp

3) Exécuter le programme

En l'absence d'erreur, sur les dimensions de l'image et sur le chemin et le nom du fichier utilisé, le programme retourne le contenu de fenêtre console suivant. Le fichier modifié peut alors être récupéré à l'emplacement indiqué dans la méthode savetofile.

3

Ouvrir ce fichier avec Gimp afin de vérifier le travail effectué par le programme.

4

4) Utiliser le fichier image créé

L'image créée par le programme peut être facilement superposée à une photo, à l'aide de Gimp par exemple. Conseil : avant d'exécuter le programme, utiliser l'outil pipette de GImp pour identifier une couleur de cadre adaptée à la photo à encadrer.

photo