• Main Page
  • Classes
  • Files
  • File List

CMSWindowsClipboardBitmapConverter.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2004 Chris Schoeneman
00005  * 
00006  * This package is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * found in the file COPYING that should have accompanied this file.
00009  * 
00010  * This package is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include "CMSWindowsClipboardBitmapConverter.h"
00020 #include "CLog.h"
00021 
00022 //
00023 // CMSWindowsClipboardBitmapConverter
00024 //
00025 
00026 CMSWindowsClipboardBitmapConverter::CMSWindowsClipboardBitmapConverter()
00027 {
00028     // do nothing
00029 }
00030 
00031 CMSWindowsClipboardBitmapConverter::~CMSWindowsClipboardBitmapConverter()
00032 {
00033     // do nothing
00034 }
00035 
00036 IClipboard::EFormat
00037 CMSWindowsClipboardBitmapConverter::getFormat() const
00038 {
00039     return IClipboard::kBitmap;
00040 }
00041 
00042 UINT
00043 CMSWindowsClipboardBitmapConverter::getWin32Format() const
00044 {
00045     return CF_DIB;
00046 }
00047 
00048 HANDLE
00049 CMSWindowsClipboardBitmapConverter::fromIClipboard(const CString& data) const
00050 {
00051     // copy to memory handle
00052     HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, data.size());
00053     if (gData != NULL) {
00054         // get a pointer to the allocated memory
00055         char* dst = (char*)GlobalLock(gData);
00056         if (dst != NULL) {
00057             memcpy(dst, data.data(), data.size());
00058             GlobalUnlock(gData);
00059         }
00060         else {
00061             GlobalFree(gData);
00062             gData = NULL;
00063         }
00064     }
00065 
00066     return gData;
00067 }
00068 
00069 CString
00070 CMSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const
00071 {
00072     // get datator
00073     const char* src = (const char*)GlobalLock(data);
00074     if (src == NULL) {
00075         return CString();
00076     }
00077     UInt32 srcSize = (UInt32)GlobalSize(data);
00078 
00079     // check image type
00080     const BITMAPINFO* bitmap = reinterpret_cast<const BITMAPINFO*>(src);
00081     LOG((CLOG_INFO "bitmap: %dx%d %d", bitmap->bmiHeader.biWidth, bitmap->bmiHeader.biHeight, (int)bitmap->bmiHeader.biBitCount));
00082     if (bitmap->bmiHeader.biPlanes == 1 &&
00083         (bitmap->bmiHeader.biBitCount == 24 ||
00084         bitmap->bmiHeader.biBitCount == 32) &&
00085         bitmap->bmiHeader.biCompression == BI_RGB) {
00086         // already in canonical form
00087         CString image(src, srcSize);
00088         GlobalUnlock(data);
00089         return image;
00090     }
00091 
00092     // create a destination DIB section
00093     LOG((CLOG_INFO "convert image from: depth=%d comp=%d", bitmap->bmiHeader.biBitCount, bitmap->bmiHeader.biCompression));
00094     void* raw;
00095     BITMAPINFOHEADER info;
00096     LONG w               = bitmap->bmiHeader.biWidth;
00097     LONG h               = bitmap->bmiHeader.biHeight;
00098     info.biSize          = sizeof(BITMAPINFOHEADER);
00099     info.biWidth         = w;
00100     info.biHeight        = h;
00101     info.biPlanes        = 1;
00102     info.biBitCount      = 32;
00103     info.biCompression   = BI_RGB;
00104     info.biSizeImage     = 0;
00105     info.biXPelsPerMeter = 1000;
00106     info.biYPelsPerMeter = 1000;
00107     info.biClrUsed       = 0;
00108     info.biClrImportant  = 0;
00109     HDC dc      = GetDC(NULL);
00110     HBITMAP dst = CreateDIBSection(dc, (BITMAPINFO*)&info,
00111                             DIB_RGB_COLORS, &raw, NULL, 0);
00112 
00113     // find the start of the pixel data
00114     const char* srcBits = (const char*)bitmap + bitmap->bmiHeader.biSize;
00115     if (bitmap->bmiHeader.biBitCount >= 16) {
00116         if (bitmap->bmiHeader.biCompression == BI_BITFIELDS &&
00117             (bitmap->bmiHeader.biBitCount == 16 ||
00118             bitmap->bmiHeader.biBitCount == 32)) {
00119             srcBits += 3 * sizeof(DWORD);
00120         }
00121     }
00122     else if (bitmap->bmiHeader.biClrUsed != 0) {
00123         srcBits += bitmap->bmiHeader.biClrUsed * sizeof(RGBQUAD);
00124     }
00125     else {
00126         //http://msdn.microsoft.com/en-us/library/ke55d167(VS.80).aspx
00127         srcBits += (1i64 << bitmap->bmiHeader.biBitCount) * sizeof(RGBQUAD);
00128     }
00129 
00130     // copy source image to destination image
00131     HDC dstDC         = CreateCompatibleDC(dc);
00132     HGDIOBJ oldBitmap = SelectObject(dstDC, dst);
00133     SetDIBitsToDevice(dstDC, 0, 0, w, h, 0, 0, 0, h,
00134                             srcBits, bitmap, DIB_RGB_COLORS);
00135     SelectObject(dstDC, oldBitmap);
00136     DeleteDC(dstDC);
00137     GdiFlush();
00138 
00139     // extract data
00140     CString image((const char*)&info, info.biSize);
00141     image.append((const char*)raw, 4 * w * h);
00142 
00143     // clean up GDI
00144     DeleteObject(dst);
00145     ReleaseDC(NULL, dc);
00146 
00147     // release handle
00148     GlobalUnlock(data);
00149 
00150     return image;
00151 }

Generated on Sat May 25 2013 00:00:04 for Synergy by  doxygen 1.7.1