Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

CMSWindowsClipboardBitmapConverter.cpp

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

Generated on Fri Nov 6 00:21:14 2009 for synergy-plus by  doxygen 1.3.9.1