CXWindowsClipboardAnyBitmapConverter.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 "CXWindowsClipboardAnyBitmapConverter.h"
00016 
00017 // BMP info header structure
00018 struct CBMPInfoHeader {
00019 public:
00020     UInt32              biSize;
00021     SInt32              biWidth;
00022     SInt32              biHeight;
00023     UInt16              biPlanes;
00024     UInt16              biBitCount;
00025     UInt32              biCompression;
00026     UInt32              biSizeImage;
00027     SInt32              biXPelsPerMeter;
00028     SInt32              biYPelsPerMeter;
00029     UInt32              biClrUsed;
00030     UInt32              biClrImportant;
00031 };
00032 
00033 // BMP is little-endian
00034 
00035 static
00036 void
00037 toLE(UInt8*& dst, UInt16 src)
00038 {
00039     dst[0] = static_cast<UInt8>(src & 0xffu);
00040     dst[1] = static_cast<UInt8>((src >> 8) & 0xffu);
00041     dst += 2;
00042 }
00043 
00044 static
00045 void
00046 toLE(UInt8*& dst, SInt32 src)
00047 {
00048     dst[0] = static_cast<UInt8>(src & 0xffu);
00049     dst[1] = static_cast<UInt8>((src >>  8) & 0xffu);
00050     dst[2] = static_cast<UInt8>((src >> 16) & 0xffu);
00051     dst[3] = static_cast<UInt8>((src >> 24) & 0xffu);
00052     dst += 4;
00053 }
00054 
00055 static
00056 void
00057 toLE(UInt8*& dst, UInt32 src)
00058 {
00059     dst[0] = static_cast<UInt8>(src & 0xffu);
00060     dst[1] = static_cast<UInt8>((src >>  8) & 0xffu);
00061     dst[2] = static_cast<UInt8>((src >> 16) & 0xffu);
00062     dst[3] = static_cast<UInt8>((src >> 24) & 0xffu);
00063     dst += 4;
00064 }
00065 
00066 static inline
00067 UInt16
00068 fromLEU16(const UInt8* data)
00069 {
00070     return static_cast<UInt16>(data[0]) |
00071             (static_cast<UInt16>(data[1]) << 8);
00072 }
00073 
00074 static inline
00075 SInt32
00076 fromLES32(const UInt8* data)
00077 {
00078     return static_cast<SInt32>(static_cast<UInt32>(data[0]) |
00079             (static_cast<UInt32>(data[1]) <<  8) |
00080             (static_cast<UInt32>(data[2]) << 16) |
00081             (static_cast<UInt32>(data[3]) << 24));
00082 }
00083 
00084 static inline
00085 UInt32
00086 fromLEU32(const UInt8* data)
00087 {
00088     return static_cast<UInt32>(data[0]) |
00089             (static_cast<UInt32>(data[1]) <<  8) |
00090             (static_cast<UInt32>(data[2]) << 16) |
00091             (static_cast<UInt32>(data[3]) << 24);
00092 }
00093 
00094 
00095 //
00096 // CXWindowsClipboardAnyBitmapConverter
00097 //
00098 
00099 CXWindowsClipboardAnyBitmapConverter::CXWindowsClipboardAnyBitmapConverter()
00100 {
00101     // do nothing
00102 }
00103 
00104 CXWindowsClipboardAnyBitmapConverter::~CXWindowsClipboardAnyBitmapConverter()
00105 {
00106     // do nothing
00107 }
00108 
00109 IClipboard::EFormat
00110 CXWindowsClipboardAnyBitmapConverter::getFormat() const
00111 {
00112     return IClipboard::kBitmap;
00113 }
00114 
00115 int
00116 CXWindowsClipboardAnyBitmapConverter::getDataSize() const
00117 {
00118     return 8;
00119 }
00120 
00121 CString
00122 CXWindowsClipboardAnyBitmapConverter::fromIClipboard(const CString& bmp) const
00123 {
00124     // fill BMP info header with native-endian data
00125     CBMPInfoHeader infoHeader;
00126     const UInt8* rawBMPInfoHeader = reinterpret_cast<const UInt8*>(bmp.data());
00127     infoHeader.biSize             = fromLEU32(rawBMPInfoHeader +  0);
00128     infoHeader.biWidth            = fromLES32(rawBMPInfoHeader +  4);
00129     infoHeader.biHeight           = fromLES32(rawBMPInfoHeader +  8);
00130     infoHeader.biPlanes           = fromLEU16(rawBMPInfoHeader + 12);
00131     infoHeader.biBitCount         = fromLEU16(rawBMPInfoHeader + 14);
00132     infoHeader.biCompression      = fromLEU32(rawBMPInfoHeader + 16);
00133     infoHeader.biSizeImage        = fromLEU32(rawBMPInfoHeader + 20);
00134     infoHeader.biXPelsPerMeter    = fromLES32(rawBMPInfoHeader + 24);
00135     infoHeader.biYPelsPerMeter    = fromLES32(rawBMPInfoHeader + 28);
00136     infoHeader.biClrUsed          = fromLEU32(rawBMPInfoHeader + 32);
00137     infoHeader.biClrImportant     = fromLEU32(rawBMPInfoHeader + 36);
00138 
00139     // check that format is acceptable
00140     if (infoHeader.biSize != 40 ||
00141         infoHeader.biWidth == 0 || infoHeader.biHeight == 0 ||
00142         infoHeader.biPlanes != 0 || infoHeader.biCompression != 0 ||
00143         (infoHeader.biBitCount != 24 && infoHeader.biBitCount != 32)) {
00144         return CString();
00145     }
00146 
00147     // convert to image format
00148     const UInt8* rawBMPPixels = rawBMPInfoHeader + 40;
00149     if (infoHeader.biBitCount == 24) {
00150         return doBGRFromIClipboard(rawBMPPixels,
00151                             infoHeader.biWidth, infoHeader.biHeight);
00152     }
00153     else {
00154         return doBGRAFromIClipboard(rawBMPPixels,
00155                             infoHeader.biWidth, infoHeader.biHeight);
00156     }
00157 }
00158 
00159 CString
00160 CXWindowsClipboardAnyBitmapConverter::toIClipboard(const CString& image) const
00161 {
00162     // convert to raw BMP data
00163     UInt32 w, h, depth;
00164     CString rawBMP = doToIClipboard(image, w, h, depth);
00165     if (rawBMP.empty() || w == 0 || h == 0 || (depth != 24 && depth != 32)) {
00166         return CString();
00167     }
00168 
00169     // fill BMP info header with little-endian data
00170     UInt8 infoHeader[40];
00171     UInt8* dst = infoHeader;
00172     toLE(dst, static_cast<UInt32>(40));
00173     toLE(dst, static_cast<SInt32>(w));
00174     toLE(dst, static_cast<SInt32>(h));
00175     toLE(dst, static_cast<UInt16>(1));
00176     toLE(dst, static_cast<UInt16>(depth));
00177     toLE(dst, static_cast<UInt32>(0));      // BI_RGB
00178     toLE(dst, static_cast<UInt32>(image.size()));
00179     toLE(dst, static_cast<SInt32>(2834));   // 72 dpi
00180     toLE(dst, static_cast<SInt32>(2834));   // 72 dpi
00181     toLE(dst, static_cast<UInt32>(0));
00182     toLE(dst, static_cast<UInt32>(0));
00183 
00184     // construct image
00185     return CString(reinterpret_cast<const char*>(infoHeader),
00186                             sizeof(infoHeader)) + rawBMP;
00187 }

Generated on Fri Nov 6 00:18:45 2009 for synergy-plus by  doxygen 1.4.7