Dump an image in PNG format if the URI ends with ".png" and PNG support is enabled. --- hw/vga.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 74 insertions(+), 1 deletions(-)
diff --git a/hw/vga.c b/hw/vga.c index 9f7ca89..0210cde 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -32,6 +32,13 @@ #include "xen.h" #include "qemu_socket.h" +#ifdef CONFIG_PNG +/* The following define is needed by pngconf.h. Otherwise it won't compile, + because setjmp.h was already included by qemu-common.h. */ +#define PNG_SKIP_SETJMP_CHECK +#include <png.h> +#endif + //#define DEBUG_VGA //#define DEBUG_VGA_MEM //#define DEBUG_VGA_REG @@ -2422,6 +2429,39 @@ QEMUFile *qemu_fopen_uri(const char *uri, const char *mode) return f; } +#ifdef CONFIG_PNG +static void *vga_png_malloc(png_structp png_ptr, png_size_t size) +{ + return g_malloc(size); +} + +static void vga_png_free(png_structp png_ptr, png_voidp ptr) +{ + g_free(ptr); +} + +static void vga_png_write_data(png_structp png_ptr, png_bytep data, + png_size_t length) +{ + QEMUFile *f = png_get_io_ptr(png_ptr); + + qemu_put_buffer(f, (uint8_t*)data, length); +} + +static void vga_png_flush_data(png_structp png_ptr) +{ +} + +static int png_line_handler(void *opaque, uint8_t *line, size_t length) +{ + png_structp png_ptr = opaque; + + png_write_row(png_ptr, line); + + return length; +} +#endif + static int ppm_line_handler(void *opaque, uint8_t *line, size_t length) { QEMUFile *f = opaque; @@ -2482,7 +2522,39 @@ int ppm_save(const char *uri, struct DisplaySurface *ds) f = qemu_fopen_uri(uri, "wb"); g_return_val_if_fail(f != NULL, -1); - { + if (g_str_has_suffix(uri, ".png")) { +#ifdef CONFIG_PNG + png_structp png_ptr; + png_infop info_ptr; + + png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL, + NULL, vga_png_malloc, + vga_png_free); + if (png_ptr == NULL) { + goto out; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, NULL); + goto out; + } + + png_set_write_fn(png_ptr, (void *)f, + vga_png_write_data, vga_png_flush_data); + png_set_IHDR(png_ptr, info_ptr, ds->width, ds->height, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(png_ptr, info_ptr); + screen_dump_lines(ds, png_line_handler, png_ptr); + png_write_end(png_ptr, NULL); + png_destroy_write_struct(&png_ptr, &info_ptr); +#else + DPRINTF("PNG support is disabled"); + goto out; +#endif + } else { gchar *header; header = g_strdup_printf("P6\n%d %d\n%d\n", ds->width, ds->height, 255); qemu_put_buffer(f, (uint8_t*)header, strlen(header)); @@ -2491,6 +2563,7 @@ int ppm_save(const char *uri, struct DisplaySurface *ds) } ret = 0; +out: qemu_fclose(f); return ret; } -- 1.7.7.6