Acked-by: Christophe Fergeau <cfergeau@xxxxxxxxxx> On Mon, Jul 24, 2017 at 01:10:24PM +0100, Frediano Ziglio wrote: > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > Acked-by: Christophe Fergeau <cfergeau@xxxxxxxxxx> > --- > vdagent/imagepng.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 115 insertions(+), 3 deletions(-) > > diff --git a/vdagent/imagepng.cpp b/vdagent/imagepng.cpp > index f966cc2..d15f2a8 100644 > --- a/vdagent/imagepng.cpp > +++ b/vdagent/imagepng.cpp > @@ -19,6 +19,7 @@ > > #include <png.h> > #include <algorithm> > +#include <vector> > > #include "imagepng.h" > > @@ -50,6 +51,43 @@ static void read_from_bufio(png_structp png, png_bytep out, png_size_t size) > io.pos += size; > } > > +struct WriteBufferIo { > + uint8_t *buf; > + uint32_t pos, size; > + WriteBufferIo(): > + buf(NULL), pos(0), size(0) > + {} > + ~WriteBufferIo() { free(buf); } > + uint8_t *release() { > + uint8_t *res = buf; > + buf = NULL; > + pos = size = 0; > + return res; > + } > +}; > + > +static void write_to_bufio(png_structp png, png_bytep in, png_size_t size) > +{ > + WriteBufferIo& io(*(WriteBufferIo*)png_get_io_ptr(png)); > + if (io.pos + size > io.size) { > + uint32_t new_size = io.size ? io.size * 2 : 4096; > + while (io.pos + size >= new_size) { > + new_size *= 2; > + } > + uint8_t *p = (uint8_t*) realloc(io.buf, new_size); > + if (!p) > + png_error(png, "out of memory"); > + io.buf = p; > + io.size = new_size; > + } > + memcpy(io.buf+io.pos, in, size); > + io.pos += size; > +} > + > +static void flush_bufio(png_structp png) > +{ > +} > + > size_t PngCoder::get_dib_size(const uint8_t *data, size_t size) > { > return convert_to_dib(NULL, data, size); > @@ -226,10 +264,84 @@ void PngCoder::get_dib_data(uint8_t *dib, const uint8_t *data, size_t size) > convert_to_dib(dib, data, size); > } > > -uint8_t *PngCoder::from_bitmap(const BITMAPINFO& info, const void *bits, long &size) > +uint8_t *PngCoder::from_bitmap(const BITMAPINFO& bmp_info, const void *bits, long &size) > { > - // TODO not implemented > - return NULL; > + // this vector is here to avoid leaking resources if libpng use setjmp/longjmp > + std::vector<png_color> palette; > + WriteBufferIo io; > + > + png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); > + if (!png) > + return 0; > + > + png_infop info = png_create_info_struct(png); > + if (!info) { > + png_destroy_write_struct(&png, &info); > + return 0; > + } > + > + if (setjmp(png_jmpbuf(png))) { > + png_destroy_write_struct(&png, &info); > + return 0; > + } > + > + png_set_write_fn(png, &io, write_to_bufio, flush_bufio); > + > + const BITMAPINFOHEADER& head(bmp_info.bmiHeader); > + int color_type; > + int out_bits = head.biBitCount; > + switch (out_bits) { > + case 1: > + case 4: > + case 8: > + color_type = PNG_COLOR_TYPE_PALETTE; > + break; > + case 24: > + case 32: > + png_set_bgr(png); > + color_type = PNG_COLOR_TYPE_RGB; > + break; > + default: > + png_error(png, "BMP bit count not supported"); > + break; > + } > + // TODO detect gray > + png_set_IHDR(png, info, head.biWidth, head.biHeight, > + out_bits > 8 ? 8 : out_bits, color_type, > + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, > + PNG_FILTER_TYPE_DEFAULT); > + > + // palette > + if (color_type == PNG_COLOR_TYPE_PALETTE) { > + palette.resize(head.biClrUsed); > + const RGBQUAD *rgb = bmp_info.bmiColors; > + for (unsigned int color = 0; color < head.biClrUsed; ++color) { > + palette[color].red = rgb->rgbRed; > + palette[color].green = rgb->rgbGreen; > + palette[color].blue = rgb->rgbBlue; > + ++rgb; > + } > + png_set_PLTE(png, info, &palette[0], palette.size()); > + } > + > + png_write_info(png, info); > + > + const unsigned int width = head.biWidth; > + const unsigned int height = head.biHeight; > + const size_t stride = compute_dib_stride(width, out_bits); > + const size_t image_size = stride * height; > + > + // now do the actual conversion! > + const uint8_t *src = (const uint8_t*)bits + image_size; > + for (unsigned int row = 0; row < height; ++row) { > + src -= stride; > + png_write_row(png, src); > + } > + png_write_end(png, NULL); > + > + png_destroy_write_struct(&png, &info); > + size = io.pos; > + return io.release(); > } > > ImageCoder *create_png_coder() > -- > 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