Rotation bitmap

Description

Code permettant d'effectuer une rotation sur un HBITMAP de 0°, 90°, 180° ou 270°.

Source / Exemple :


//*****************************************************************************
// GetBmpSize : récupère la taille d'un bitmap.
// entrée : hBmp : bitmap dont on souhaite récupérer la taille.
// retour : taille du bitmap spécifié.
//*****************************************************************************
SIZE GetBmpSize(HBITMAP hBmp)
{
	// récupération des informations sur le bitmap
	BITMAP bmpInfo;
	GetObject(hBmp, sizeof(bmpInfo), &bmpInfo);

	// taille
	SIZE size;
	size.cx = bmpInfo.bmWidth;
	size.cy = bmpInfo.bmHeight;
	return size;
}

//*****************************************************************************
// GetBmpData : récupère les données (pixels) d'un bitmap.
// entrée : hdc  : DC à utiliser pour les appels aux fonctions API.
//          hBmp : bitmap source.
// retour : données du bitmap (à libérer par VirtualFree) ou NULL en cas
//          d'erreur.
//-----------------------------------------------------------------------------
// Remarques : - les données sont récupéres en 32 bits par pixels (4octets)
//               afin d'éviter d'avoir à rajouter du padding pour aligner les
//               lignes sur 4 octets.
//             - les bitmaps top-down ne sont pas gérés.
//             - les pixels sont stockées par ligne à partir du bas du bitmap
//               (bottum-up).
//*****************************************************************************
LPVOID GetBmpData(HDC hdc, HBITMAP hBmp)
{
	// taille du bitmap, si bitmap top-down on renvoi NULL
	SIZE sizeBmp = GetBmpSize(hBmp);
	if(sizeBmp.cy < 0)
		return NULL;

	// allocation mémoire (on va récupérer en 32 bits par pixel)
	DWORD dwSize = 4*sizeBmp.cx*sizeBmp.cy;
	LPVOID lpMem = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
	if(lpMem == NULL)
		return NULL;

	// initialisation structure BITMAPINFO
	BITMAPINFO bi;
	ZeroMemory(&bi, sizeof(BITMAPINFO));
	bi.bmiHeader.biSize			= sizeof(BITMAPINFOHEADER);
	bi.bmiHeader.biPlanes		= 1;
	bi.bmiHeader.biBitCount		= 32;
	bi.bmiHeader.biWidth		= sizeBmp.cx;
	bi.bmiHeader.biHeight		= sizeBmp.cy;
	bi.bmiHeader.biCompression	= BI_RGB;

	// récupération bits
	int nResult = GetDIBits(hdc, hBmp, 0, sizeBmp.cy, lpMem, &bi, DIB_RGB_COLORS);

	// si tout c'est bien passé
	if(nResult != 0)
		return lpMem;

	// erreur, libération de la mémoire
	VirtualFree(lpMem, 0, MEM_RELEASE);
	return NULL;
}

//*****************************************************************************
// RotateBmp : effectue une rotation d'un bitmap.
// entrée : hdc     : DC à utiliser pour les appels aux fonctions API.
//          hBmpSrc : bitmap source.
//          nAngle  : angle de rotation, en degré, dans le sens trigo (inverse
//                    horaire. Seules les valeurs 0, 90, 180 et 270 sont
//                    valides.
// retour : bitmap avec la rotation demandée ou NULL en cas d'erreur.
//*****************************************************************************
HBITMAP	RotateBmp(HDC hdc, HBITMAP hBmpSrc, int nAngle)
{
	// nAngle doit être 0, 90, 180 ou 270
	if(nAngle != 0 && nAngle != 90 && nAngle != 180 && nAngle != 270)
		return NULL;

	// taille et données du bitmap source
	SIZE sizeSrc = GetBmpSize(hBmpSrc);
	LPVOID lpDataSrc = GetBmpData(hdc, hBmpSrc);
	if(lpDataSrc == NULL)
		return NULL;

	// taille du bitmap de destination
	SIZE sizeDst = sizeSrc;
	if(nAngle == 90 || nAngle == 270)
	{
		sizeDst.cx = sizeSrc.cy;
		sizeDst.cy = sizeSrc.cx;
	}

	// allocation mémoire pour le bitmap de destination (32 bits par pixel)
	DWORD dwSize = 4*sizeDst.cx*sizeDst.cy;
	LPVOID lpDataDst = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
	if(lpDataDst == NULL)
	{
		VirtualFree(lpDataSrc, 0, MEM_RELEASE);
		return NULL;
	}

	// affectation des bits
	for(int xSrc = 0; xSrc < sizeSrc.cx; xSrc++)
	{
		for(int ySrc = 0; ySrc < sizeSrc.cy; ySrc++)
		{
			// pixel de destination :
			int xDst, yDst;
			switch(nAngle)
			{
			case 0	: xDst = xSrc;				yDst = ySrc;				break;
			case 90	: xDst = sizeSrc.cy-ySrc-1;	yDst = xSrc;				break;
			case 180: xDst = sizeSrc.cx-xSrc-1; yDst = sizeSrc.cy-ySrc-1;	break;
			case 270: xDst = ySrc;				yDst = sizeSrc.cx-xSrc-1;	break;
			}

			// affectation du pixels (32 bits = 4 octets = 1 DWORD)
			LPDWORD lpSrc = (LPDWORD)lpDataSrc+sizeSrc.cx*ySrc+xSrc;
			LPDWORD lpDst = (LPDWORD)lpDataDst+sizeDst.cx*yDst+xDst;

  • lpDst = *lpSrc;
} } // initialisation structure BITMAPINFO pour le bitmap de destination BITMAPINFO bi; ZeroMemory(&bi, sizeof(BITMAPINFO)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biWidth = sizeDst.cx; bi.bmiHeader.biHeight = sizeDst.cy; bi.bmiHeader.biCompression = BI_RGB; // création du bitmap de destination HBITMAP hBmpDst = CreateDIBitmap(hdc, &bi.bmiHeader, CBM_INIT, lpDataDst, &bi, DIB_RGB_COLORS); // libération mémoire VirtualFree(lpDataSrc, 0, MEM_RELEASE); VirtualFree(lpDataDst, 0, MEM_RELEASE); // retour return hBmpDst; }

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.