diff options
Diffstat (limited to 'Wrapper/FreeImagePlus/src/fipWinImage.cpp')
-rw-r--r-- | Wrapper/FreeImagePlus/src/fipWinImage.cpp | 481 |
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 |