Acked-by: Christophe Fergeau <cfergeau@xxxxxxxxxx> On Fri, Jul 21, 2017 at 02:51:37PM +0100, Frediano Ziglio wrote: > Remove CxImage linking. > Support Windows BMP format. > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > --- > Makefile.am | 4 +- > configure.ac | 4 +- > mingw-spice-vdagent.spec.in | 10 +-- > vdagent/image.cpp | 172 +++++++++++++++++++++++++++++++++----------- > vdagent/image.h | 21 ++++++ > 5 files changed, 158 insertions(+), 53 deletions(-) > > diff --git a/Makefile.am b/Makefile.am > index 868199e..b35dd57 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -23,8 +23,8 @@ LIBS = -lversion > > bin_PROGRAMS = vdagent vdservice > > -vdagent_LDADD = -lwtsapi32 $(CXIMAGE_LIBS) vdagent_rc.$(OBJEXT) > -vdagent_CXXFLAGS = $(AM_CXXFLAGS) $(CXIMAGE_CFLAGS) > +vdagent_LDADD = -lwtsapi32 -lgdi32 vdagent_rc.$(OBJEXT) > +vdagent_CXXFLAGS = $(AM_CXXFLAGS) > vdagent_LDFLAGS = $(AM_LDFLAGS) -Wl,--subsystem,windows > vdagent_SOURCES = \ > common/vdcommon.cpp \ > diff --git a/configure.ac b/configure.ac > index ff489cc..4eac4b4 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -42,6 +42,7 @@ AC_DEFINE_UNQUOTED([BUILD_YEAR], "$BUILD_YEAR", [Build year]) > # Check for programs > AC_PROG_CC > AC_PROG_CXX > +AX_CXX_COMPILE_STDCXX_11 > AM_PROG_CC_C_O > AC_PROG_INSTALL > AC_CHECK_TOOL(WINDRES, [windres]) > @@ -100,9 +101,6 @@ dnl --------------------------------------------------------------------------- > dnl - Check library dependencies > dnl --------------------------------------------------------------------------- > > -PKG_CHECK_MODULES(CXIMAGE, [cximage]) > -CXIMAGE_LIBS=`$PKG_CONFIG --static --libs cximage` > - > dnl --------------------------------------------------------------------------- > dnl - Makefiles, etc. > dnl --------------------------------------------------------------------------- > diff --git a/mingw-spice-vdagent.spec.in b/mingw-spice-vdagent.spec.in > index 563341d..f874e66 100644 > --- a/mingw-spice-vdagent.spec.in > +++ b/mingw-spice-vdagent.spec.in > @@ -13,16 +13,10 @@ Source0: vdagent-win-%{version}%{?_version_suffix}.tar.xz > > BuildRequires: mingw32-filesystem >= 23 > BuildRequires: mingw64-filesystem >= 23 > -BuildRequires: mingw32-cximage-static > -BuildRequires: mingw64-cximage-static > -BuildRequires: mingw32-jasper-static > -BuildRequires: mingw64-jasper-static > -BuildRequires: mingw32-libjpeg-turbo-static > -BuildRequires: mingw64-libjpeg-turbo-static > +BuildRequires: mingw32-gcc-c++ > +BuildRequires: mingw64-gcc-c++ > BuildRequires: mingw32-libpng-static > BuildRequires: mingw64-libpng-static > -BuildRequires: mingw32-libtiff-static > -BuildRequires: mingw64-libtiff-static > BuildRequires: mingw32-zlib-static > BuildRequires: mingw64-zlib-static > BuildRequires: mingw32-winpthreads-static > diff --git a/vdagent/image.cpp b/vdagent/image.cpp > index 960058d..faec18f 100644 > --- a/vdagent/image.cpp > +++ b/vdagent/image.cpp > @@ -16,39 +16,48 @@ > */ > > #include <spice/macros.h> > +#include <memory> > +#include <vector> > > #include "vdcommon.h" > #include "image.h" > > -#include "ximage.h" > +ImageCoder *create_bitmap_coder(); > +ImageCoder *create_png_coder(); > > -typedef struct ImageType { > - uint32_t type; > - DWORD cximage_format; > -} ImageType; > - > -static const ImageType image_types[] = { > - {VD_AGENT_CLIPBOARD_IMAGE_PNG, CXIMAGE_FORMAT_PNG}, > - {VD_AGENT_CLIPBOARD_IMAGE_BMP, CXIMAGE_FORMAT_BMP}, > -}; > - > -static DWORD get_cximage_format(uint32_t type) > +static ImageCoder *get_coder(uint32_t vdagent_type) > { > - for (unsigned int i = 0; i < SPICE_N_ELEMENTS(image_types); i++) { > - if (image_types[i].type == type) { > - return image_types[i].cximage_format; > - } > + switch (vdagent_type) { > + case VD_AGENT_CLIPBOARD_IMAGE_BMP: > + return create_bitmap_coder(); > + case VD_AGENT_CLIPBOARD_IMAGE_PNG: > + return create_png_coder(); > } > - return 0; > + return NULL; > } > > -HANDLE get_image_handle(const VDAgentClipboard& clipboard, uint32_t size, UINT&) > +HANDLE get_image_handle(const VDAgentClipboard& clipboard, uint32_t size, UINT& format) > { > - HANDLE clip_data; > - DWORD cximage_format = get_cximage_format(clipboard.type); > - ASSERT(cximage_format); > - CxImage image((BYTE*)clipboard.data, size, cximage_format); > - clip_data = image.CopyToHandle(); > + std::unique_ptr<ImageCoder> coder(get_coder(clipboard.type)); > + if (!coder) { > + return NULL; > + } > + > + format = CF_DIB; > + size_t dib_size = coder->get_dib_size(clipboard.data, size); > + if (!dib_size) { > + return NULL; > + } > + HANDLE clip_data = GlobalAlloc(GMEM_MOVEABLE, dib_size); > + if (clip_data) { > + uint8_t* dst = (uint8_t*)GlobalLock(clip_data); > + if (!dst) { > + GlobalFree(clip_data); > + return NULL; > + } > + coder->get_dib_data(dst, clipboard.data, size); > + GlobalUnlock(clip_data); > + } > return clip_data; > } > > @@ -57,32 +66,115 @@ uint8_t* get_raw_clipboard_image(const VDAgentClipboardRequest& clipboard_reques > { > new_size = 0; > > - CxImage image; > - uint8_t *new_data = NULL; > - DWORD cximage_format = get_cximage_format(clipboard_request.type); > - HPALETTE pal = 0; > + if (GetObjectType(clip_data) != OBJ_BITMAP) { > + return NULL; > + } > + > + std::unique_ptr<ImageCoder> coder(get_coder(clipboard_request.type)); > + if (!coder) { > + return NULL; > + } > > - ASSERT(cximage_format); > + HPALETTE pal = 0; > if (IsClipboardFormatAvailable(CF_PALETTE)) { > pal = (HPALETTE)GetClipboardData(CF_PALETTE); > } > - if (!image.CreateFromHBITMAP((HBITMAP)clip_data, pal)) { > - vd_printf("Image create from handle failed"); > - return NULL; > + > + // extract DIB > + BITMAP bitmap; > + GetObject(clip_data, sizeof(bitmap), &bitmap); > + > + struct { > + BITMAPINFOHEADER head; > + RGBQUAD colors[256]; > + } info; > + > + BITMAPINFOHEADER& head(info.head); > + memset(&head, 0, sizeof(head)); > + head.biSize = sizeof(head); > + head.biWidth = bitmap.bmWidth; > + head.biHeight = bitmap.bmHeight; > + head.biPlanes = bitmap.bmPlanes; > + head.biBitCount = bitmap.bmBitsPixel >= 16 ? 24 : bitmap.bmBitsPixel; > + head.biCompression = BI_RGB; > + > + HDC dc = GetDC(NULL); > + HPALETTE old_pal = NULL; > + if (pal) { > + old_pal = (HPALETTE)SelectObject(dc, pal); > + RealizePalette(dc); > + } > + size_t stride = compute_dib_stride(head.biWidth, head.biBitCount); > + std::vector<uint8_t> bits(stride * head.biHeight); > + int res = GetDIBits(dc, (HBITMAP) clip_data, 0, head.biHeight, > + &bits[0], (LPBITMAPINFO)&info, DIB_RGB_COLORS); > + if (pal) { > + SelectObject(dc, old_pal); > } > - if (!image.Encode(new_data, new_size, cximage_format)) { > - vd_printf("Image encode to type %u failed", clipboard_request.type); > + ReleaseDC(NULL, dc); > + if (!res) { > return NULL; > } > - vd_printf("Image encoded to %lu bytes", new_size); > - return new_data; > + > + // convert DIB to desired format > + return coder->from_bitmap(*(LPBITMAPINFO)&info, &bits[0], new_size); > } > > void free_raw_clipboard_image(uint8_t *data) > { > - // this is really just a free however is better to make > - // the free from CxImage code as on Windows the free > - // can be different between libraries > - CxImage image; > - image.FreeMemory(data); > + free(data); > +} > + > +class BitmapCoder: public ImageCoder > +{ > +public: > + BitmapCoder() {}; > + size_t get_dib_size(const uint8_t *data, size_t size); > + void get_dib_data(uint8_t *dib, const uint8_t *data, size_t size); > + uint8_t *from_bitmap(const BITMAPINFO& info, const void *bits, long &size); > +}; > + > +size_t BitmapCoder::get_dib_size(const uint8_t *data, size_t size) > +{ > + if (memcmp(data, "BM", 2) == 0) > + return size > 14 ? size - 14 : 0; > + return size; > +} > + > +void BitmapCoder::get_dib_data(uint8_t *dib, const uint8_t *data, size_t size) > +{ > + // just strip the file header if present, images can be either BMP or DIB > + size_t new_size = get_dib_size(data, size); > + memcpy(dib, data + (size - new_size), new_size); > +} > + > +uint8_t *BitmapCoder::from_bitmap(const BITMAPINFO& info, const void *bits, long &size) > +{ > + const BITMAPINFOHEADER& head(info.bmiHeader); > + > + const DWORD max_palette_colors = head.biBitCount <= 8 ? 1 << head.biBitCount : 0; > + size_t palette_size = sizeof(RGBQUAD) * std::min(head.biClrUsed, max_palette_colors); > + > + const size_t stride = compute_dib_stride(head.biWidth, head.biBitCount); > + const size_t image_size = stride * head.biHeight; > + size = sizeof(head) + palette_size + image_size; > + > + uint8_t *data = (uint8_t *) malloc(size); > + if (!data) { > + return NULL; > + } > + memcpy(data, &info, sizeof(head) + palette_size); > + memcpy(data + sizeof(head) + palette_size, bits, image_size); > + return data; > +} > + > +ImageCoder *create_bitmap_coder() > +{ > + return new BitmapCoder(); > +} > + > +// TODO > +ImageCoder *create_png_coder() > +{ > + return NULL; > } > diff --git a/vdagent/image.h b/vdagent/image.h > index b70f53a..da549d3 100644 > --- a/vdagent/image.h > +++ b/vdagent/image.h > @@ -18,6 +18,27 @@ > #ifndef VDAGENT_IMAGE_H_ > #define VDAGENT_IMAGE_H_ > > +class ImageCoder > +{ > +public: > + ImageCoder() {}; > + virtual ~ImageCoder() {} > + virtual size_t get_dib_size(const uint8_t *data, size_t size)=0; > + virtual void get_dib_data(uint8_t *dib, const uint8_t *data, size_t size)=0; > + virtual uint8_t *from_bitmap(const BITMAPINFO& info, const void *bits, long &size)=0; > +private: > + ImageCoder(const ImageCoder& rhs); > + void operator=(const ImageCoder &rhs); > +}; > + > +/** > + * Compute stride in bytes of a DIB > + */ > +static inline size_t compute_dib_stride(unsigned int width, unsigned int bit_count) > +{ > + return ((width * bit_count + 31u) & ~31u) / 8u; > +} > + > /** > * Returns image to put in the clipboard. > * > -- > 2.13.3 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
signature.asc
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel