[Spice-devel] [vdagent-win PATCH v11 4/6] Support encoding PNG images
Christophe Fergeau
cfergeau at redhat.com
Tue Jul 25 16:56:23 UTC 2017
Acked-by: Christophe Fergeau <cfergeau at redhat.com>
On Mon, Jul 24, 2017 at 01:10:24PM +0100, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> Acked-by: Christophe Fergeau <cfergeau at redhat.com>
> ---
> 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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20170725/dc132945/attachment.sig>
More information about the Spice-devel
mailing list