/* * synergy -- mouse and keyboard sharing utility * Copyright (C) 2004 Chris Schoeneman, Nick Bolton, Sorin Sbarnea * * This package is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * found in the file COPYING that should have accompanied this file. * * This package is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "CXWindowsClipboardAnyBitmapConverter.h" // BMP info header structure struct CBMPInfoHeader { public: UInt32 biSize; SInt32 biWidth; SInt32 biHeight; UInt16 biPlanes; UInt16 biBitCount; UInt32 biCompression; UInt32 biSizeImage; SInt32 biXPelsPerMeter; SInt32 biYPelsPerMeter; UInt32 biClrUsed; UInt32 biClrImportant; }; // BMP is little-endian static void toLE(UInt8*& dst, UInt16 src) { dst[0] = static_cast<UInt8>(src & 0xffu); dst[1] = static_cast<UInt8>((src >> 8) & 0xffu); dst += 2; } static void toLE(UInt8*& dst, SInt32 src) { dst[0] = static_cast<UInt8>(src & 0xffu); dst[1] = static_cast<UInt8>((src >> 8) & 0xffu); dst[2] = static_cast<UInt8>((src >> 16) & 0xffu); dst[3] = static_cast<UInt8>((src >> 24) & 0xffu); dst += 4; } static void toLE(UInt8*& dst, UInt32 src) { dst[0] = static_cast<UInt8>(src & 0xffu); dst[1] = static_cast<UInt8>((src >> 8) & 0xffu); dst[2] = static_cast<UInt8>((src >> 16) & 0xffu); dst[3] = static_cast<UInt8>((src >> 24) & 0xffu); dst += 4; } static inline UInt16 fromLEU16(const UInt8* data) { return static_cast<UInt16>(data[0]) | (static_cast<UInt16>(data[1]) << 8); } static inline SInt32 fromLES32(const UInt8* data) { return static_cast<SInt32>(static_cast<UInt32>(data[0]) | (static_cast<UInt32>(data[1]) << 8) | (static_cast<UInt32>(data[2]) << 16) | (static_cast<UInt32>(data[3]) << 24)); } static inline UInt32 fromLEU32(const UInt8* data) { return static_cast<UInt32>(data[0]) | (static_cast<UInt32>(data[1]) << 8) | (static_cast<UInt32>(data[2]) << 16) | (static_cast<UInt32>(data[3]) << 24); } // // CXWindowsClipboardAnyBitmapConverter // CXWindowsClipboardAnyBitmapConverter::CXWindowsClipboardAnyBitmapConverter() { // do nothing } CXWindowsClipboardAnyBitmapConverter::~CXWindowsClipboardAnyBitmapConverter() { // do nothing } IClipboard::EFormat CXWindowsClipboardAnyBitmapConverter::getFormat() const { return IClipboard::kBitmap; } int CXWindowsClipboardAnyBitmapConverter::getDataSize() const { return 8; } CString CXWindowsClipboardAnyBitmapConverter::fromIClipboard(const CString& bmp) const { // fill BMP info header with native-endian data CBMPInfoHeader infoHeader; const UInt8* rawBMPInfoHeader = reinterpret_cast<const UInt8*>(bmp.data()); infoHeader.biSize = fromLEU32(rawBMPInfoHeader + 0); infoHeader.biWidth = fromLES32(rawBMPInfoHeader + 4); infoHeader.biHeight = fromLES32(rawBMPInfoHeader + 8); infoHeader.biPlanes = fromLEU16(rawBMPInfoHeader + 12); infoHeader.biBitCount = fromLEU16(rawBMPInfoHeader + 14); infoHeader.biCompression = fromLEU32(rawBMPInfoHeader + 16); infoHeader.biSizeImage = fromLEU32(rawBMPInfoHeader + 20); infoHeader.biXPelsPerMeter = fromLES32(rawBMPInfoHeader + 24); infoHeader.biYPelsPerMeter = fromLES32(rawBMPInfoHeader + 28); infoHeader.biClrUsed = fromLEU32(rawBMPInfoHeader + 32); infoHeader.biClrImportant = fromLEU32(rawBMPInfoHeader + 36); // check that format is acceptable if (infoHeader.biSize != 40 || infoHeader.biWidth == 0 || infoHeader.biHeight == 0 || infoHeader.biPlanes != 0 || infoHeader.biCompression != 0 || (infoHeader.biBitCount != 24 && infoHeader.biBitCount != 32)) { return CString(); } // convert to image format const UInt8* rawBMPPixels = rawBMPInfoHeader + 40; if (infoHeader.biBitCount == 24) { return doBGRFromIClipboard(rawBMPPixels, infoHeader.biWidth, infoHeader.biHeight); } else { return doBGRAFromIClipboard(rawBMPPixels, infoHeader.biWidth, infoHeader.biHeight); } } CString CXWindowsClipboardAnyBitmapConverter::toIClipboard(const CString& image) const { // convert to raw BMP data UInt32 w, h, depth; CString rawBMP = doToIClipboard(image, w, h, depth); if (rawBMP.empty() || w == 0 || h == 0 || (depth != 24 && depth != 32)) { return CString(); } // fill BMP info header with little-endian data UInt8 infoHeader[40]; UInt8* dst = infoHeader; toLE(dst, static_cast<UInt32>(40)); toLE(dst, static_cast<SInt32>(w)); toLE(dst, static_cast<SInt32>(h)); toLE(dst, static_cast<UInt16>(1)); toLE(dst, static_cast<UInt16>(depth)); toLE(dst, static_cast<UInt32>(0)); // BI_RGB toLE(dst, static_cast<UInt32>(image.size())); toLE(dst, static_cast<SInt32>(2834)); // 72 dpi toLE(dst, static_cast<SInt32>(2834)); // 72 dpi toLE(dst, static_cast<UInt32>(0)); toLE(dst, static_cast<UInt32>(0)); // construct image return CString(reinterpret_cast<const char*>(infoHeader), sizeof(infoHeader)) + rawBMP; }