begin process at 2012 02 08 22:35:05
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Graphique

 > ETIRER/RÉTRÉCIR UNE IMAGE BMP SANS STRETCHBLT

ETIRER/RÉTRÉCIR UNE IMAGE BMP SANS STRETCHBLT


 Information sur la source

Note :
10 / 10 - par 3 personnes
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Graphique Niveau :Débutant Date de création :29/07/2004 Vu / téléchargé :8 517 / 556

Auteur : Maegis

Ecrire un message privé
Commentaire sur cette source (0)
Ajouter un commentaire et/ou une note

 Description

C'est un code qui permet de changer la résolution d'une image avec deux méthodes pour l'agrandissement (avec ou sans moyenne)
Le principe est expliqué dans un fichier txt joint dans le zip
3 fonctions : lire un bmp24 bits, le scaler, et l'enregistrer

Lancez le prog, il ouvrira image.bmp et créera une image de double taille avec ou sans la moyenne et une image de taille la moitié.
On peut aussi stretcher l'image comme l'on veut : agrandir un coté et rétrecir l'autre, ou toute autre configuration

Source

  • /*-----------------------------------------------------------------------------------------------*
  • //
  • // ScaleImage
  • //
  • //Fait par : MaegisInstinct (maegisinstinct@free.fr)
  • //
  • //le : 29/07/2004 à 20:27:37
  • //
  • //Description : Permet d'etirer/étrecir une image
  • Lire le .txt pour avoir des explications sur la méthode de Scale
  • //
  • /*----------------------------------------------------------------------------------------------*/
  • #include <windows.h>
  • #define PARTDEC(a) (a-(double)(int)a) //retourne la partie décimale d'un double
  • struct PIXEL
  • {
  • BYTE b;
  • BYTE g;
  • BYTE r;
  • };
  • /*--------------------------------*/
  • //Change la resolution d'une image
  • /*--------------------------------*/
  • void Scale(const PIXEL* src,DWORD srcwidth,DWORD srcheight,PIXEL* data,DWORD datawidth,DWORD dataheight,BOOL moyenne_etirement)
  • {
  • DWORD i,j,k,l;
  • PIXEL* save_data;
  • double xratio,yratio;
  • double precx = 0.0,precy = 0.0;
  • double currentx,currenty;
  • double coeff; //somme des coeffs pour la moyenne
  • double temp;
  • double somme_r,somme_g,somme_b;
  • xratio = (double)srcwidth/(double)datawidth;
  • yratio = (double)srcheight/(double)dataheight;
  • save_data = data;
  • currenty = 0.0;
  • for(j=0;j<dataheight;j++) //Pour chaque pixel du but
  • {
  • currentx = 0.0;
  • currenty += yratio;
  • for(i=0;i<datawidth;i++)
  • {
  • currentx += xratio;
  • coeff = 0.0;
  • somme_r = 0.0;
  • somme_g = 0.0;
  • somme_b = 0.0;
  • //Calcul de la moyenne
  • for(l=0;l<(unsigned int)yratio+1;l++) //Pour chaque pixel de la source contenu dans le pixel du but
  • {
  • for(k=0;k<(unsigned int)xratio+1;k++)
  • {
  • //Coeff en x
  • if (k==0)
  • temp = 1.0-PARTDEC(precx);
  • else if (k==(unsigned int)xratio)
  • temp = xratio-(double)((int)xratio-1)-(1.0-PARTDEC(precx));
  • else
  • temp = 1;
  • //Coeff en y
  • if (l==0)
  • temp = temp*(1.0-PARTDEC(precy));
  • else if (l==(unsigned int)yratio)
  • temp = temp*(yratio-(double)((int)yratio-1)-(1.0-PARTDEC(precy)));
  • if ((int)precx+k<srcwidth && (int)precy+l<srcheight) //si on est dans les limites
  • {
  • somme_r += src[(int)precx+k+((int)precy+l)*srcwidth].r*temp;
  • somme_g += src[(int)precx+k+((int)precy+l)*srcwidth].g*temp;
  • somme_b += src[(int)precx+k+((int)precy+l)*srcwidth].b*temp;
  • coeff += temp;
  • }
  • if (moyenne_etirement) //Moyenne lors de l'etirement si souhaité
  • {
  • if (xratio<1. && (int)currentx-(int)precx==1 && PARTDEC(currentx) != 0.)
  • {
  • temp = PARTDEC(currentx);
  • somme_r += src[(int)precx+1 + (int)precy*srcwidth].r*temp;
  • somme_g += src[(int)precx+1 + (int)precy*srcwidth].g*temp;
  • somme_b += src[(int)precx+1 + (int)precy*srcwidth].b*temp;
  • coeff += temp;
  • temp = -1.0;
  • }
  • if (yratio<1. && (int)currenty-(int)precy==1 && PARTDEC(currenty) != 0.)
  • {
  • if (temp == -1.0) //on compte le quatrieme carré
  • {
  • temp = PARTDEC(currenty)*PARTDEC(currentx);
  • somme_r += src[(int)precx+1 + ((int)(precy)+1)*srcwidth].r*temp;
  • somme_g += src[(int)precx+1 + ((int)(precy)+1)*srcwidth].g*temp;
  • somme_b += src[(int)precx+1 + ((int)(precy)+1)*srcwidth].b*temp;
  • coeff += temp;
  • }
  • temp = PARTDEC(currenty);
  • somme_r += src[(int)precx + ((int)(precy)+1)*srcwidth].r*temp;
  • somme_g += src[(int)precx + ((int)(precy)+1)*srcwidth].g*temp;
  • somme_b += src[(int)precx + ((int)(precy)+1)*srcwidth].b*temp;
  • coeff += temp;
  • }
  • }
  • }
  • }
  • data->r = (BYTE)(somme_r/coeff);
  • data->g = (BYTE)(somme_g/coeff);
  • data->b = (BYTE)(somme_b/coeff);
  • data++;
  • precx = currentx;
  • }
  • precy = currenty;
  • precx = 0.0;
  • }
  • data = save_data;
  • }
  • /*---------------------------------*/
  • //Enregistre un fichier bmp24 bits
  • /*---------------------------------*/
  • BOOL SaveBmp24(char *path,PIXEL *data,int width,int height)
  • {
  • BITMAPFILEHEADER fileheader;
  • BITMAPINFOHEADER infoheader;
  • HANDLE fichier;
  • DWORD dummy;
  • int size;
  • int bourrage = 0;
  • int i,j,k;
  • char *image = NULL;
  • fichier = CreateFile(path,
  • GENERIC_WRITE,
  • FILE_SHARE_READ,
  • NULL,
  • CREATE_ALWAYS,
  • FILE_ATTRIBUTE_NORMAL,
  • NULL);
  • if (fichier == INVALID_HANDLE_VALUE)
  • return FALSE;
  • fileheader.bfType = 0x4D42; //"bm"
  • fileheader.bfSize = 54 + width*height*3;
  • fileheader.bfReserved2 = 0;
  • fileheader.bfReserved1 = 0;
  • fileheader.bfOffBits = 54;
  • infoheader.biSize = sizeof(BITMAPINFOHEADER);
  • infoheader.biWidth = width;
  • infoheader.biHeight = height;
  • infoheader.biPlanes = 1;
  • infoheader.biBitCount = 24;
  • infoheader.biCompression = 0;
  • infoheader.biSizeImage = width*height;
  • infoheader.biXPelsPerMeter = 0;
  • infoheader.biYPelsPerMeter = 0;
  • infoheader.biClrImportant = 0;
  • infoheader.biClrUsed = 0;
  • while ((3*width+bourrage) % 4 != 0) //calcul du nb de bits de bourrage (3 car 24bits = 3octs)
  • bourrage++;
  • size = width*height;
  • image = new char[size*3+bourrage*height];
  • if (image == NULL)
  • {
  • CloseHandle(fichier);
  • return FALSE;
  • }
  • for(i=0;i<height;i++)
  • {
  • for(j=0;j<width;j++)
  • {
  • image[i*(3*width+bourrage)+3*j] = data[(height-i-1)*width+j].b;
  • image[i*(3*width+bourrage)+3*j+1] = data[(height-i-1)*width+j].g;
  • image[i*(3*width+bourrage)+3*j+2] = data[(height-i-1)*width+j].r;
  • }
  • for(k=1;k<bourrage;k++)
  • image[i*(3*width+bourrage)+3*j+k] = 0;
  • }
  • WriteFile(fichier,&fileheader,14,&dummy,NULL);
  • WriteFile(fichier,&infoheader,40,&dummy,NULL);
  • WriteFile(fichier,image,size*3+bourrage*height,&dummy,NULL);
  • CloseHandle(fichier);
  • return TRUE;
  • }
  • /*---------------------*/
  • //Ouvre un bmp 24 bits
  • /*---------------------*/
  • BOOL GetBmp24(char* chemin,PIXEL **data,DWORD& width,DWORD& height)
  • {
  • BITMAPFILEHEADER fileheader;
  • BITMAPINFOHEADER infoheader;
  • HANDLE fichier;
  • DWORD dummy,i,j;
  • DWORD size;
  • DWORD bourrage = 0;
  • PIXEL temp;
  • BYTE *buffer = NULL;
  • fichier = CreateFile(chemin,
  • GENERIC_READ,
  • FILE_SHARE_READ,
  • NULL,
  • OPEN_EXISTING,
  • FILE_ATTRIBUTE_NORMAL,
  • NULL);
  • if (fichier == INVALID_HANDLE_VALUE)
  • return FALSE;
  • ReadFile(fichier,&fileheader,14,&dummy,NULL);
  • ReadFile(fichier,&infoheader,40,&dummy,NULL);
  • width = infoheader.biWidth;
  • height = infoheader.biHeight;
  • while ((3*width+bourrage) % 4 != 0) //gestion du bourrage
  • bourrage++;
  • if (fileheader.bfType != 0x4D42 || infoheader.biBitCount != 24
  • || infoheader.biCompression != 0)
  • {
  • CloseHandle(fichier);
  • return FALSE;
  • }
  • size = width*height;
  • buffer = new BYTE[size*3+bourrage*height];
  • if (buffer == NULL)
  • return FALSE;
  • SetFilePointer(fichier,fileheader.bfOffBits,NULL,FILE_BEGIN);
  • ReadFile(fichier,buffer,size*3+bourrage*height,&dummy,NULL);
  • (*data) = new PIXEL[size];
  • if ((*data) == NULL)
  • {
  • delete[] buffer;
  • return FALSE;
  • }
  • for(i=0;i<height;i++)
  • {
  • memcpy((*data)+(i*width),buffer+i*(3*width+bourrage),width*3);
  • }
  • //remet dans le bon sens
  • for(i=0;i<(height/2);i++)
  • {
  • for(j=0;j<width;j++)
  • {
  • temp = (*data)[i*width+j];
  • (*data)[i*width+j] = (*data)[(height-1-i)*width+j];
  • (*data)[(height-1-i)*width+j] = temp;
  • }
  • }
  • CloseHandle(fichier);
  • delete[] buffer;
  • return TRUE;
  • }
  • /*--------------*/
  • //Fonction Main
  • /*--------------*/
  • int APIENTRY WinMain(HINSTANCE hInstance,
  • HINSTANCE hPrevInstance,
  • LPSTR lpCmdLine,
  • int nShowCmd)
  • {
  • PIXEL *data,*scaleddata;
  • DWORD width,height;
  • if (GetBmp24("image.bmp",&data,width,height))
  • {
  • scaleddata = new PIXEL[width*height*4];
  • Scale(data,width,height,scaleddata,width/2,height/2,FALSE);
  • SaveBmp24("Halfimage.bmp",scaleddata,width/2,height/2);
  • Scale(data,width,height,scaleddata,width*2,height*2,FALSE);
  • SaveBmp24("Doubleimage.bmp",scaleddata,width*2,height*2);
  • Scale(data,width,height,scaleddata,width*2,height*2,TRUE);
  • SaveBmp24("Doubleimagemoyenne.bmp",scaleddata,width*2,height*2);
  • delete[] data;
  • delete[] scaleddata;
  • return 0;
  • }
  • return -1;
  • }
/*-----------------------------------------------------------------------------------------------*
//
//                                      ScaleImage
//
//Fait par         : MaegisInstinct (maegisinstinct@free.fr)
//
//le               : 29/07/2004 à 20:27:37
//
//Description      : Permet d'etirer/étrecir une image
					 Lire le .txt pour avoir des explications sur la méthode de Scale
//
/*----------------------------------------------------------------------------------------------*/

#include <windows.h>

#define PARTDEC(a) (a-(double)(int)a)		//retourne la partie décimale d'un double

struct PIXEL
{
	BYTE b;
	BYTE g;
	BYTE r;
};


/*--------------------------------*/
//Change la resolution d'une image
/*--------------------------------*/
void Scale(const PIXEL* src,DWORD srcwidth,DWORD srcheight,PIXEL* data,DWORD datawidth,DWORD dataheight,BOOL moyenne_etirement)
{
	DWORD	i,j,k,l;
	PIXEL*	save_data; 
	double	xratio,yratio;
	double	precx = 0.0,precy = 0.0;
	double	currentx,currenty;
	double	coeff;						//somme des coeffs pour la moyenne
	double	temp;
	double	somme_r,somme_g,somme_b;

	xratio = (double)srcwidth/(double)datawidth;
	yratio = (double)srcheight/(double)dataheight;
	save_data = data;
	currenty = 0.0;

	for(j=0;j<dataheight;j++)			//Pour chaque pixel du but
	{
		currentx = 0.0;
		currenty += yratio;
		for(i=0;i<datawidth;i++)
		{
			currentx += xratio;
			coeff = 0.0;
			somme_r = 0.0;
			somme_g = 0.0;
			somme_b = 0.0;
		
			//Calcul de la moyenne
			for(l=0;l<(unsigned int)yratio+1;l++)		//Pour chaque pixel de la source contenu dans le pixel du but
			{
				for(k=0;k<(unsigned int)xratio+1;k++)
				{
				//Coeff en x
					if (k==0)
						temp = 1.0-PARTDEC(precx);
					else if (k==(unsigned int)xratio)
						temp = xratio-(double)((int)xratio-1)-(1.0-PARTDEC(precx));
					else
						temp = 1;
				//Coeff en y
					if (l==0)
						temp = temp*(1.0-PARTDEC(precy));
					else if (l==(unsigned int)yratio)
						temp = temp*(yratio-(double)((int)yratio-1)-(1.0-PARTDEC(precy)));

					if ((int)precx+k<srcwidth && (int)precy+l<srcheight)		//si on est dans les limites
					{
						somme_r += src[(int)precx+k+((int)precy+l)*srcwidth].r*temp;
						somme_g += src[(int)precx+k+((int)precy+l)*srcwidth].g*temp;
						somme_b += src[(int)precx+k+((int)precy+l)*srcwidth].b*temp;
						coeff += temp;
					}

					if (moyenne_etirement)  //Moyenne lors de l'etirement si souhaité
					{
						if (xratio<1. && (int)currentx-(int)precx==1 && PARTDEC(currentx) != 0.)
						{
							temp = PARTDEC(currentx);
							somme_r += src[(int)precx+1 + (int)precy*srcwidth].r*temp;
							somme_g += src[(int)precx+1 + (int)precy*srcwidth].g*temp;
							somme_b += src[(int)precx+1 + (int)precy*srcwidth].b*temp;
							coeff += temp;
							temp = -1.0;
						}
						if (yratio<1. && (int)currenty-(int)precy==1 && PARTDEC(currenty) != 0.)
						{
							if (temp == -1.0)		//on compte le quatrieme carré
							{
								temp = PARTDEC(currenty)*PARTDEC(currentx);
								somme_r += src[(int)precx+1 + ((int)(precy)+1)*srcwidth].r*temp;
								somme_g += src[(int)precx+1 + ((int)(precy)+1)*srcwidth].g*temp;
								somme_b += src[(int)precx+1 + ((int)(precy)+1)*srcwidth].b*temp;
								coeff += temp;
							}
							temp = PARTDEC(currenty);
							somme_r += src[(int)precx + ((int)(precy)+1)*srcwidth].r*temp;
							somme_g += src[(int)precx + ((int)(precy)+1)*srcwidth].g*temp;
							somme_b += src[(int)precx + ((int)(precy)+1)*srcwidth].b*temp;
							coeff += temp;
						}
					}
				}
			}
			data->r = (BYTE)(somme_r/coeff);
			data->g = (BYTE)(somme_g/coeff);
			data->b = (BYTE)(somme_b/coeff);
			data++;
			precx = currentx;
		}
		precy = currenty;
		precx = 0.0;
	}
	data = save_data;
}

/*---------------------------------*/
//Enregistre un fichier bmp24 bits
/*---------------------------------*/
BOOL SaveBmp24(char *path,PIXEL *data,int width,int height)
{
	BITMAPFILEHEADER	fileheader;
	BITMAPINFOHEADER	infoheader;
	HANDLE				fichier;
	DWORD				dummy;
	int					size;
	int					bourrage = 0;
	int					i,j,k;
	char				*image = NULL;

	fichier = CreateFile(path,
						 GENERIC_WRITE,
						 FILE_SHARE_READ,
						 NULL,
						 CREATE_ALWAYS,
						 FILE_ATTRIBUTE_NORMAL,
						 NULL);
	if (fichier == INVALID_HANDLE_VALUE)
		return FALSE;

	fileheader.bfType = 0x4D42;	//"bm"
	fileheader.bfSize = 54 + width*height*3;
	fileheader.bfReserved2 = 0;
	fileheader.bfReserved1 = 0;
	fileheader.bfOffBits = 54;

	infoheader.biSize = sizeof(BITMAPINFOHEADER);
	infoheader.biWidth = width;
	infoheader.biHeight = height;
	infoheader.biPlanes = 1;
	infoheader.biBitCount = 24;
	infoheader.biCompression = 0;
	infoheader.biSizeImage = width*height;
	infoheader.biXPelsPerMeter = 0;
	infoheader.biYPelsPerMeter = 0;
	infoheader.biClrImportant = 0;
	infoheader.biClrUsed = 0;

	while ((3*width+bourrage) % 4 != 0)	//calcul du nb de bits de bourrage (3 car 24bits = 3octs)
		bourrage++;

	size = width*height;

	image = new char[size*3+bourrage*height];
	if (image == NULL)
	{
		CloseHandle(fichier);
		return FALSE;
	}
	
	for(i=0;i<height;i++)
	{
		for(j=0;j<width;j++)
		{
			image[i*(3*width+bourrage)+3*j]		= data[(height-i-1)*width+j].b;
			image[i*(3*width+bourrage)+3*j+1]	= data[(height-i-1)*width+j].g;
			image[i*(3*width+bourrage)+3*j+2]	= data[(height-i-1)*width+j].r;
		}
		for(k=1;k<bourrage;k++)
			image[i*(3*width+bourrage)+3*j+k] = 0;
	}

	WriteFile(fichier,&fileheader,14,&dummy,NULL);
	WriteFile(fichier,&infoheader,40,&dummy,NULL);
	WriteFile(fichier,image,size*3+bourrage*height,&dummy,NULL);

	CloseHandle(fichier);
	return TRUE;
}

/*---------------------*/
//Ouvre un bmp 24 bits
/*---------------------*/
BOOL GetBmp24(char* chemin,PIXEL **data,DWORD& width,DWORD& height)
{
	BITMAPFILEHEADER	fileheader;
	BITMAPINFOHEADER	infoheader;
	HANDLE				fichier;
	DWORD				dummy,i,j;
	DWORD				size;
	DWORD				bourrage	= 0;
	PIXEL				temp;
	BYTE				*buffer		= NULL;

	fichier = CreateFile(chemin,
						 GENERIC_READ,
						 FILE_SHARE_READ,
						 NULL,
						 OPEN_EXISTING,
						 FILE_ATTRIBUTE_NORMAL,
						 NULL);
	if (fichier == INVALID_HANDLE_VALUE)
		return FALSE;

	ReadFile(fichier,&fileheader,14,&dummy,NULL);
	ReadFile(fichier,&infoheader,40,&dummy,NULL);
	width = infoheader.biWidth;
	height = infoheader.biHeight;

	while ((3*width+bourrage) % 4 != 0)		//gestion du bourrage
		bourrage++;

	if (fileheader.bfType != 0x4D42 || infoheader.biBitCount != 24 
		|| infoheader.biCompression != 0)
	{
		CloseHandle(fichier);
		return FALSE;
	}
	size = width*height;

	buffer = new BYTE[size*3+bourrage*height];
	if (buffer == NULL)
		return FALSE;

	SetFilePointer(fichier,fileheader.bfOffBits,NULL,FILE_BEGIN);

	ReadFile(fichier,buffer,size*3+bourrage*height,&dummy,NULL);

	(*data) = new PIXEL[size];
	if ((*data) == NULL)
	{
		delete[] buffer;
		return FALSE;
	}

	for(i=0;i<height;i++)
	{
		memcpy((*data)+(i*width),buffer+i*(3*width+bourrage),width*3);
	}

	//remet dans le bon sens
	for(i=0;i<(height/2);i++)
	{
		for(j=0;j<width;j++)
		{
			temp  = (*data)[i*width+j];
			(*data)[i*width+j] = (*data)[(height-1-i)*width+j];
			(*data)[(height-1-i)*width+j] = temp;
		}
	}
	

	CloseHandle(fichier);
	delete[] buffer;
	return TRUE;
}

/*--------------*/
//Fonction Main
/*--------------*/
int APIENTRY WinMain(HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	PIXEL *data,*scaleddata;
	DWORD width,height;

	if (GetBmp24("image.bmp",&data,width,height))
	{
		scaleddata = new PIXEL[width*height*4];
		Scale(data,width,height,scaleddata,width/2,height/2,FALSE);
		SaveBmp24("Halfimage.bmp",scaleddata,width/2,height/2);
		Scale(data,width,height,scaleddata,width*2,height*2,FALSE);
		SaveBmp24("Doubleimage.bmp",scaleddata,width*2,height*2);
		Scale(data,width,height,scaleddata,width*2,height*2,TRUE);
		SaveBmp24("Doubleimagemoyenne.bmp",scaleddata,width*2,height*2);
		
		delete[] data;
		delete[] scaleddata;
		return 0;
	}
	return -1;
}

 Conclusion

La difference en l'agrandissement avec ou sans la moyenne se voit sur des petites images
(Essayez sur des 8*8 ou 16*16 ou sur des icones à agrandir fortement)

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Sources du même auteur

Source avec Zip Source avec une capture DETECTION DE CONTOURS
Source avec Zip Source avec une capture ASCII ART : BMP TO HTM - TRANSFORME UNE IMAGE EN FICHIER HT...
Source avec Zip Source avec une capture BITMAP24 TO TEXT - TRANSFORME UNE IMAGE EN TEXTE VC++
Source avec Zip RESOLUTION D'EQUATIONS DE DEGRÉ 4 OU INFERIEUR
Source avec Zip Source avec une capture DEBUT DE MOTEUR D'AFFICHAGE OPENGL AVEC RENDU DE SKYBOX

 Sources de la même categorie

Source avec Zip APPLICATION DE DESSIN DE QUELQUES FIGURES par laguchori
Source avec Zip Source avec une capture HDR EXPOSURE FUSION par mecrosoft
Source avec Zip Source avec une capture IRC CLIENT MULTISERVEUR EN MFC (TXIRC) par TeniX
Source avec Zip ENTETE DU FICHIER BMP (BIPMAP) par k.Lutchi
Source avec Zip Source avec une capture XCOUPE : COUPE 2D par pop70

Commentaires et avis

Aucun commentaire pour le moment.

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,591 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales