summaryrefslogtreecommitdiff
path: root/Wrapper/FreeImagePlus/src/fipWinImage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Wrapper/FreeImagePlus/src/fipWinImage.cpp')
-rw-r--r--Wrapper/FreeImagePlus/src/fipWinImage.cpp481
1 files changed, 481 insertions, 0 deletions
diff --git a/Wrapper/FreeImagePlus/src/fipWinImage.cpp b/Wrapper/FreeImagePlus/src/fipWinImage.cpp
new file mode 100644
index 0000000..9139152
--- /dev/null
+++ b/Wrapper/FreeImagePlus/src/fipWinImage.cpp
@@ -0,0 +1,481 @@
+// ==========================================================
+// fipWinImage class implementation
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImagePlus.h"
+
+#ifdef _WIN32
+
+// marker used for clipboard copy / paste
+
+static inline void
+SET_FREEIMAGE_MARKER(BITMAPINFOHEADER *bmih, FIBITMAP *dib) {
+ // Windows constants goes from 0L to 5L
+ // Add 0xFF to avoid conflicts
+ bmih->biCompression = 0xFF + FreeImage_GetImageType(dib);
+}
+
+static inline FREE_IMAGE_TYPE
+GET_FREEIMAGE_MARKER(BITMAPINFOHEADER *bmih) {
+ return (FREE_IMAGE_TYPE)(bmih->biCompression - 0xFF);
+}
+
+///////////////////////////////////////////////////////////////////
+// Construction / Destruction
+
+fipWinImage::fipWinImage(FREE_IMAGE_TYPE image_type, WORD width, WORD height, WORD bpp) : fipImage(image_type, width, height, bpp) {
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ // default tone mapping operator
+ _tmo = FITMO_DRAGO03;
+ _tmo_param_1 = 0;
+ _tmo_param_2 = 0;
+ _tmo_param_3 = 1;
+ _tmo_param_4 = 0;
+}
+
+fipWinImage::~fipWinImage() {
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ }
+}
+
+void fipWinImage::clear() {
+ // delete _display_dib
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ }
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ // delete base class data
+ fipImage::clear();
+}
+
+BOOL fipWinImage::isValid() const {
+ return fipImage::isValid();
+}
+
+///////////////////////////////////////////////////////////////////
+// Copying
+
+fipWinImage& fipWinImage::operator=(const fipImage& Image) {
+ // delete _display_dib
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ }
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ // clone the base class
+ fipImage::operator=(Image);
+
+ return *this;
+}
+
+fipWinImage& fipWinImage::operator=(const fipWinImage& Image) {
+ if(this != &Image) {
+ // delete _display_dib
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ }
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ // copy tmo data
+ _tmo = Image._tmo;
+ _tmo_param_1 = Image._tmo_param_1;
+ _tmo_param_2 = Image._tmo_param_2;
+ _tmo_param_3 = Image._tmo_param_3;
+ _tmo_param_4 = Image._tmo_param_4;
+
+ // clone the base class
+ fipImage::operator=(Image);
+ }
+ return *this;
+}
+
+HANDLE fipWinImage::copyToHandle() const {
+ HANDLE hMem = NULL;
+
+ if(_dib) {
+
+ // Get equivalent DIB size
+ long dib_size = sizeof(BITMAPINFOHEADER);
+ dib_size += FreeImage_GetColorsUsed(_dib) * sizeof(RGBQUAD);
+ dib_size += FreeImage_GetPitch(_dib) * FreeImage_GetHeight(_dib);
+
+ // Allocate a DIB
+ hMem = GlobalAlloc(GHND, dib_size);
+ BYTE *dib = (BYTE*)GlobalLock(hMem);
+
+ memset(dib, 0, dib_size);
+
+ BYTE *p_dib = (BYTE*)dib;
+
+ // Copy the BITMAPINFOHEADER
+
+ BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(_dib);
+ memcpy(p_dib, bih, sizeof(BITMAPINFOHEADER));
+ if(FreeImage_GetImageType(_dib) != FIT_BITMAP) {
+ // this hack is used to store the bitmap type in the biCompression member of the BITMAPINFOHEADER
+ SET_FREEIMAGE_MARKER((BITMAPINFOHEADER*)p_dib, _dib);
+ }
+ p_dib += sizeof(BITMAPINFOHEADER);
+
+ // Copy the palette
+
+ RGBQUAD *pal = FreeImage_GetPalette(_dib);
+ memcpy(p_dib, pal, FreeImage_GetColorsUsed(_dib) * sizeof(RGBQUAD));
+ p_dib += FreeImage_GetColorsUsed(_dib) * sizeof(RGBQUAD);
+
+ // Copy the bitmap
+
+ BYTE *bits = FreeImage_GetBits(_dib);
+ memcpy(p_dib, bits, FreeImage_GetPitch(_dib) * FreeImage_GetHeight(_dib));
+
+ GlobalUnlock(hMem);
+ }
+
+ return hMem;
+}
+
+BOOL fipWinImage::copyFromHandle(HANDLE hMem) {
+ BYTE *lpVoid = NULL;
+ BITMAPINFOHEADER *pHead = NULL;
+ RGBQUAD *pPalette = NULL;
+ BYTE *bits = NULL;
+ DWORD bitfields[3] = {0, 0, 0};
+
+ // Get a pointer to the bitmap
+ lpVoid = (BYTE *)GlobalLock(hMem);
+
+ // Get a pointer to the bitmap header
+ pHead = (BITMAPINFOHEADER *)lpVoid;
+
+ // Get a pointer to the palette
+ if(pHead->biBitCount < 16)
+ pPalette = (RGBQUAD *)(((BYTE *)pHead) + sizeof(BITMAPINFOHEADER));
+
+ // Get a pointer to the pixels
+ bits = ((BYTE*)pHead + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pHead->biClrUsed);
+
+ if(pHead->biCompression == BI_BITFIELDS) {
+ // Take into account the color masks that specify the red, green, and blue components (16- and 32-bit)
+ unsigned mask_size = 3 * sizeof(DWORD);
+ memcpy(&bitfields[0], bits, mask_size);
+ bits += mask_size;
+ }
+
+ if(lpVoid) {
+
+ // Allocate a new FIBITMAP
+
+ FREE_IMAGE_TYPE image_type = FIT_BITMAP;
+ // Use a hack to decide if the clipboard contains non standard bitmaps ...
+ switch(GET_FREEIMAGE_MARKER(pHead)) {
+ case FIT_UINT16:
+ case FIT_INT16:
+ case FIT_UINT32:
+ case FIT_INT32:
+ case FIT_FLOAT:
+ case FIT_DOUBLE:
+ case FIT_COMPLEX:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ image_type = GET_FREEIMAGE_MARKER(pHead);
+ break;
+ }
+ if(!setSize(image_type, (WORD)pHead->biWidth, (WORD)pHead->biHeight, pHead->biBitCount, bitfields[2], bitfields[1], bitfields[0])) {
+ GlobalUnlock(lpVoid);
+ return FALSE;
+ }
+
+ // Copy the bitmap header
+ memcpy(FreeImage_GetInfoHeader(_dib), pHead, sizeof(BITMAPINFOHEADER));
+
+
+ // Copy the palette
+ memcpy(FreeImage_GetPalette(_dib), pPalette, pHead->biClrUsed * sizeof(RGBQUAD));
+
+ // Copy the bitmap
+ memcpy(FreeImage_GetBits(_dib), bits, FreeImage_GetPitch(_dib) * FreeImage_GetHeight(_dib));
+
+ GlobalUnlock(lpVoid);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL fipWinImage::copyFromBitmap(HBITMAP hbmp) {
+ if(hbmp) {
+ int Success;
+ BITMAP bm;
+ // Get informations about the bitmap
+ GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm);
+ // Create the image
+ setSize(FIT_BITMAP, (WORD)bm.bmWidth, (WORD)bm.bmHeight, (WORD)bm.bmBitsPixel);
+
+ // The GetDIBits function clears the biClrUsed and biClrImportant BITMAPINFO members (dont't know why)
+ // So we save these infos below. This is needed for palettized images only.
+ int nColors = FreeImage_GetColorsUsed(_dib);
+
+ // Create a device context for the bitmap
+ HDC dc = GetDC(NULL);
+ // Copy the pixels
+ Success = GetDIBits(dc, // handle to DC
+ hbmp, // handle to bitmap
+ 0, // first scan line to set
+ FreeImage_GetHeight(_dib), // number of scan lines to copy
+ FreeImage_GetBits(_dib), // array for bitmap bits
+ FreeImage_GetInfo(_dib), // bitmap data buffer
+ DIB_RGB_COLORS // RGB
+ );
+ if(Success == 0) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Error : GetDIBits failed");
+ ReleaseDC(NULL, dc);
+ return FALSE;
+ }
+ ReleaseDC(NULL, dc);
+
+ // restore BITMAPINFO members
+
+ FreeImage_GetInfoHeader(_dib)->biClrUsed = nColors;
+ FreeImage_GetInfoHeader(_dib)->biClrImportant = nColors;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL fipWinImage::copyToClipboard(HWND hWndNewOwner) const {
+ HANDLE hDIB = copyToHandle();
+
+ if(OpenClipboard(hWndNewOwner)) {
+ if(EmptyClipboard()) {
+ if(SetClipboardData(CF_DIB, hDIB) == NULL) {
+ MessageBox(hWndNewOwner, "Unable to set Clipboard data", "FreeImage", MB_ICONERROR);
+ CloseClipboard();
+ return FALSE;
+ }
+ }
+ }
+ CloseClipboard();
+
+ return TRUE;
+}
+
+BOOL fipWinImage::pasteFromClipboard() {
+ if(!IsClipboardFormatAvailable(CF_DIB))
+ return FALSE;
+
+ if(OpenClipboard(NULL)) {
+ HANDLE hDIB = GetClipboardData(CF_DIB);
+ copyFromHandle(hDIB);
+ CloseClipboard();
+ return TRUE;
+ }
+ CloseClipboard();
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////
+// Screen capture
+
+BOOL fipWinImage::captureWindow(HWND hWndApplicationWindow, HWND hWndSelectedWindow) {
+ int xScreen, yScreen, xshift, yshift;
+ RECT r;
+
+ // Get window size
+ GetWindowRect(hWndSelectedWindow, &r);
+
+ // Check if the window is out of the screen or maximixed
+ xshift = 0;
+ yshift = 0;
+ xScreen = GetSystemMetrics(SM_CXSCREEN);
+ yScreen = GetSystemMetrics(SM_CYSCREEN);
+ if(r.right > xScreen)
+ r.right = xScreen;
+ if(r.bottom > yScreen)
+ r.bottom = yScreen;
+ if(r.left < 0) {
+ xshift = -r.left;
+ r.left = 0;
+ }
+ if(r.top < 0){
+ yshift = -r.top;
+ r.top = 0;
+ }
+
+ int width = r.right - r.left;
+ int height = r.bottom - r.top;
+
+ if(width <= 0 || height <= 0)
+ return FALSE;
+
+ // Hide the application window.
+ ShowWindow(hWndApplicationWindow, SW_HIDE);
+ // Bring the window at the top most level
+ SetWindowPos(hWndSelectedWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+ // Give enough time to refresh the window
+ Sleep(500);
+
+ // Prepare the DCs
+ HDC dstDC = GetDC(NULL);
+ HDC srcDC = GetWindowDC(hWndSelectedWindow); // full window (GetDC(hWndSelectedWindow) = clientarea)
+ HDC memDC = CreateCompatibleDC(dstDC);
+
+ // Copy the screen to the bitmap
+ HBITMAP bm = CreateCompatibleBitmap(dstDC, width, height);
+ HBITMAP oldbm = (HBITMAP)SelectObject(memDC, bm);
+ BitBlt(memDC, 0, 0, width, height, srcDC, xshift, yshift, SRCCOPY);
+
+ // Redraw the application window.
+ ShowWindow(hWndApplicationWindow, SW_SHOW);
+
+ // Restore the position
+ SetWindowPos(hWndSelectedWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+ SetWindowPos(hWndApplicationWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+
+ // Convert the HBITMAP to a FIBITMAP
+ copyFromBitmap(bm);
+
+ // Free objects
+ DeleteObject(SelectObject(memDC, oldbm));
+ DeleteDC(memDC);
+
+ // Convert 32-bit images to 24-bit
+ if(getBitsPerPixel() == 32) {
+ convertTo24Bits();
+ }
+
+ return TRUE;
+}
+
+
+///////////////////////////////////////////////////////////////////
+// Painting operations
+
+void fipWinImage::drawEx(HDC hDC, RECT& rcDest, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) const {
+ // Convert to a standard bitmap if needed
+ if(_bHasChanged) {
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ }
+
+ FREE_IMAGE_TYPE image_type = getImageType();
+ if(image_type == FIT_BITMAP) {
+ BOOL bHasBackground = FreeImage_HasBackgroundColor(_dib);
+ BOOL bIsTransparent = FreeImage_IsTransparent(_dib);
+
+ if(!bIsTransparent && (!bHasBackground || !useFileBkg)) {
+ // Copy pointer
+ _display_dib = _dib;
+ }
+ else {
+ // Create the transparent / alpha blended image
+ _display_dib = FreeImage_Composite(_dib, useFileBkg, appBkColor, bg);
+ if(_display_dib) {
+ // Remember to delete _display_dib
+ _bDeleteMe = TRUE;
+ } else {
+ // Something failed: copy pointers
+ _display_dib = _dib;
+ }
+ }
+ } else {
+ // Convert to a standard dib for display
+
+ if(image_type == FIT_COMPLEX) {
+ // Convert to type FIT_DOUBLE
+ FIBITMAP *dib_double = FreeImage_GetComplexChannel(_dib, FICC_MAG);
+ // Convert to a standard bitmap (linear scaling)
+ _display_dib = FreeImage_ConvertToStandardType(dib_double, TRUE);
+ // Free image of type FIT_DOUBLE
+ FreeImage_Unload(dib_double);
+ } else if((image_type == FIT_RGBF) || (image_type == FIT_RGBAF) || (image_type == FIT_RGB16)) {
+ // Apply a tone mapping algorithm and convert to 24-bit
+ switch(_tmo) {
+ case FITMO_REINHARD05:
+ _display_dib = FreeImage_TmoReinhard05Ex(_dib, _tmo_param_1, _tmo_param_2, _tmo_param_3, _tmo_param_4);
+ break;
+ default:
+ _display_dib = FreeImage_ToneMapping(_dib, _tmo, _tmo_param_1, _tmo_param_2);
+ break;
+ }
+ } else if(image_type == FIT_RGBA16) {
+ // Convert to 32-bit
+ FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(_dib);
+ if(dib32) {
+ // Create the transparent / alpha blended image
+ _display_dib = FreeImage_Composite(dib32, useFileBkg, appBkColor, bg);
+ FreeImage_Unload(dib32);
+ }
+ } else {
+ // Other cases: convert to a standard bitmap (linear scaling)
+ _display_dib = FreeImage_ConvertToStandardType(_dib, TRUE);
+ }
+ // Remember to delete _display_dib
+ _bDeleteMe = TRUE;
+ }
+
+ _bHasChanged = FALSE;
+ }
+
+ // Draw the dib
+ SetStretchBltMode(hDC, COLORONCOLOR);
+ StretchDIBits(hDC, rcDest.left, rcDest.top,
+ rcDest.right-rcDest.left, rcDest.bottom-rcDest.top,
+ 0, 0, FreeImage_GetWidth(_display_dib), FreeImage_GetHeight(_display_dib),
+ FreeImage_GetBits(_display_dib), FreeImage_GetInfo(_display_dib), DIB_RGB_COLORS, SRCCOPY);
+
+}
+
+void fipWinImage::setToneMappingOperator(FREE_IMAGE_TMO tmo, double first_param, double second_param, double third_param, double fourth_param) {
+ // avoid costly operations if possible ...
+ if((_tmo != tmo) || (_tmo_param_1 != first_param) || (_tmo_param_2 != second_param) || (_tmo_param_3 != third_param) || (_tmo_param_4 != fourth_param)) {
+ _tmo = tmo;
+ _tmo_param_1 = first_param;
+ _tmo_param_2 = second_param;
+ _tmo_param_3 = third_param;
+ _tmo_param_4 = fourth_param;
+
+ FREE_IMAGE_TYPE image_type = getImageType();
+ if((image_type == FIT_RGBF) || (image_type == FIT_RGB16)) {
+ _bHasChanged = TRUE;
+ }
+ }
+}
+
+void fipWinImage::getToneMappingOperator(FREE_IMAGE_TMO *tmo, double *first_param, double *second_param, double *third_param, double *fourth_param) const {
+ *tmo = _tmo;
+ *first_param = _tmo_param_1;
+ *second_param = _tmo_param_2;
+ *third_param = _tmo_param_3;
+ *fourth_param = _tmo_param_4;
+}
+
+
+#endif // _WIN32