Otra vez con el GDIpus a cuestas...
En ocasiones interesa rotar una imagen en incrementos de 90º, otras veces queremos invertirla (180º) o conseguir una imagen especular.
El código que presento realiza ésto de forma muy simple y con GDI plus. Podremos rotar fácil y eficientemente una imagen en múltiplos de 90 grados y combinar esa rotación con un flp especular.
Como siempre voy a escribir el ejemplo en C/C++ y delphi:
#pragma link "Gdiplus.lib" // poner la ruta dentro de las libreriras extern "C" { DWORD WINAPI GdiplusStartup(ULONG_PTR *hToken, void *input, void *Output); void WINAPI GdiplusShutdown(ULONG_PTR token); DWORD WINAPI GdipCreateBitmapFromHBITMAP(HBITMAP hBmp, HPALETTE hPal, HANDLE* GBitmap); DWORD WINAPI GdipCreateHBITMAPFromBitmap(HANDLE Bmp, HBITMAP* hBmp, DWORD BKColor); DWORD WINAPI GdipDisposeImage(HANDLE hImage); DWORD WINAPI GdipImageRotateFlip(HANDLE hImage, DWORD rfType); } typedef enum { RotateNoneFlipNone = 0, Rotate90FlipNone = 1, Rotate180FlipNone = 2, Rotate270FlipNone = 3, RotateNoneFlipX = 4, Rotate90FlipX = 5, Rotate180FlipX = 6, Rotate270FlipX = 7, RotateNoneFlipY = Rotate180FlipX, Rotate90FlipY = Rotate270FlipX, Rotate180FlipY = RotateNoneFlipX, Rotate270FlipY = Rotate90FlipX, RotateNoneFlipXY = Rotate180FlipNone, Rotate90FlipXY = Rotate270FlipNone, Rotate180FlipXY = RotateNoneFlipNone, Rotate270FlipXY = Rotate90FlipNone } RotateFlipType; HBITMAP FlipBitmap(HBITMAP hBitmap, int Type = Rotate90FlipNone) { // Initialize GDI+. __int64 gdiplusStartupInput[3]; ULONG_PTR gdiplusToken; gdiplusStartupInput[0] = 1; gdiplusStartupInput[1] = 0; if(GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL)) return 0; HBITMAP Result; HANDLE GBitmap; GdipCreateBitmapFromHBITMAP(hBitmap, 0, &GBitmap); GdipImageRotateFlip(GBitmap, Type); GdipCreateHBITMAPFromBitmap(GBitmap, &Result, 0); GdipDisposeImage(GBitmap); //shutdown GDI+ GdiplusShutdown(gdiplusToken); return Result; }
Ejemplo de uso:
Image1->Picture->Bitmap->Handle = FlipBitmap(Image1->Picture->Bitmap->Handle); Image1->Invalidate();
Por no hacer un mensaje muy extenso en código, la versión delphi la pongo en el siguiente.
PD: Un detalle que me gustaría añadir para las dos versiones. Si os fijáis, la inicialización y cierre de GDI+ se realiza en la función. Lo he puesto así para compactar el código. No es necesario hacerlo de esta forma. Si se va a hacer uso intensivo del GDI+ es pejor una inicialización global y cierre al terminar su uso, de esa forma evitamos la redundancia.
Saludos.