From: Kshitij Suri <kshitij.suri@nutanix.com>
To: Eric Blake <eblake@redhat.com>
Cc: soham.ghosh@nutanix.com, thuth@redhat.com,
prerna.saxena@nutanix.com, armbru@redhat.com,
qemu-devel@nongnu.org, kraxel@redhat.com,
prachatos.mitra@nutanix.com, dgilbert@redhat.com
Subject: Re: [PATCH 2/2] Added parameter to take screenshot with screendump as PNG
Date: Sat, 26 Feb 2022 00:47:53 +0530 [thread overview]
Message-ID: <1dabf7c5-e408-c357-258f-747e5fe7bd12@nutanix.com> (raw)
In-Reply-To: <20220225190748.uqcdoutdbwwksous@redhat.com>
On 26/02/22 12:37 am, Eric Blake wrote:
> On Fri, Feb 25, 2022 at 11:58:30AM +0000, Kshitij Suri wrote:
>> Currently screendump only supports PPM format, which is un-compressed and not
>> standard. Added a "format" parameter to qemu monitor screendump capabilites
>> to support PNG image capture using libpng. The param was added in QAPI schema
>> of screendump present in ui.json along with png_save() function which converts
>> pixman_image to PNG. HMP command equivalent was also modified to support the
>> feature.
>>
>> Example usage:
>> { "execute": "screendump", "arguments": { "filename": "/tmp/image",
>> "format":"png" } }
>>
>> Resolves: https://urldefense.proofpoint.com/v2/url?u=https-3A__gitlab.com_qemu-2Dproject_qemu_-2D_issues_718&d=DwIBAg&c=s883GpUCOChKOHiocYtGcg&r=utjv19Ej9Fb0TB7_DX0o3faQ-OAm2ypPniPyqVSoj_w&m=N58ni_R8AQHe3XV2MX9aeKN2mCiEkpdyiqhV71sHDUEIuIk3P1HcXc-QfepnNaIE&s=CM400Sor3Oiio6iq3V_F9jFMCrn8UdbeKKXDnIh2QRw&e=
>>
>> Signed-off-by: Kshitij Suri <kshitij.suri@nutanix.com>
>> ---
>> + .args_type = "filename:F,device:s?,head:i?,format:f?",
>> + .params = "filename [device [head]] [format]",
>> + .help = "save screen from head 'head' of display device 'device'"
>> + "in specified format 'format' as image 'filename'."
>> + "Currently only 'png' and 'ppm' formats are supported.",
>> .cmd = hmp_screendump,
>> .coroutine = true,
>> },
>>
>> SRST
>> ``screendump`` *filename*
>> - Save screen into PPM image *filename*.
>> + Save screen as an image *filename*.
> Maybe:
>
> as an image *filename*, with default format of PPM.
>
>> ERST
>>
>> {
>> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
>> index 8c384dc1b2..c300545f34 100644
>> --- a/monitor/hmp-cmds.c
>> +++ b/monitor/hmp-cmds.c
>> @@ -1677,9 +1677,15 @@ hmp_screendump(Monitor *mon, const QDict *qdict)
>> const char *filename = qdict_get_str(qdict, "filename");
>> const char *id = qdict_get_try_str(qdict, "device");
>> int64_t head = qdict_get_try_int(qdict, "head", 0);
>> + const char *input_format = qdict_get_str(qdict, "format");
>> Error *err = NULL;
>> + ImageFormat format = IMAGE_FORMAT_PPM;
>> + if (input_format != NULL && strcmp(input_format, "png") == 0) {
>> + format = IMAGE_FORMAT_PNG;
>> + }
> Instead of open-coding the string-to-enum translation (which will be
> hard to located if we expand to a third format down the road), you
> should use qapi_enum_parse(&ImageFormat_lookup, ...).
>
>> +++ b/ui/console.c
>> @@ -37,6 +37,9 @@
>> #include "exec/memory.h"
>> #include "io/channel-file.h"
>> #include "qom/object.h"
>> +#ifdef CONFIG_PNG
>> +#include <png.h>
>> +#endif
>>
>> #define DEFAULT_BACKSCROLL 512
>> #define CONSOLE_CURSOR_PERIOD 500
>> @@ -289,6 +292,87 @@ void graphic_hw_invalidate(QemuConsole *con)
>> }
>> }
>>
>> +#ifdef CONFIG_PNG
>> +/**
>> + * png_save: Take a screenshot as PNG
>> + *
>> + * Saves screendump as a PNG file
>> + *
>> + * Returns true for success or false for error.
>> + *
>> + * @fd: File descriptor for PNG file.
>> + * @image: Image data in pixman format.
>> + * @errp: Pointer to an error.
>> + */
>> +static bool png_save(int fd, pixman_image_t *image, Error **errp)
>> +{
>> + int width = pixman_image_get_width(image);
>> + int height = pixman_image_get_height(image);
>> + g_autofree png_struct *png_ptr = NULL;
>> + g_autofree png_info *info_ptr = NULL;
>> + g_autoptr(pixman_image_t) linebuf =
>> + qemu_pixman_linebuf_create(PIXMAN_a8r8g8b8, width);
>> + uint8_t *buf = (uint8_t *)pixman_image_get_data(linebuf);
>> + FILE *f = fdopen(fd, "wb");
>> + int y;
>> + if (!f) {
>> + error_setg(errp, "Failed to create file from file descriptor");
> error_setg_errno() might be nicer to use here, since fdopen() failure sets errno.
>
>> + return false;
>> + }
>> +
>> + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
>> + NULL, NULL);
> Indentation looks off.
>
>> + if (!png_ptr) {
>> + error_setg(errp, "PNG creation failed. Unable to write struct");
>> + free(f);
> free() is the wrong function to call on FILE*. You meant fclose().
Apologies for this, will be replaced in the upcoming patch.
>
>> + return false;
>> + }
>> +
>> + info_ptr = png_create_info_struct(png_ptr);
>> +
>> + if (!info_ptr) {
>> + error_setg(errp, "PNG creation failed. Unable to write info");
>> + free(f);
> and again
>
>> + png_destroy_write_struct(&png_ptr, &info_ptr);
>> + return false;
>> + }
>> +
>> + png_init_io(png_ptr, f);
>> +
>> + png_set_IHDR(png_ptr, info_ptr, width, height, 8,
>> + PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
>> + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
>> +
>> + png_write_info(png_ptr, info_ptr);
>> +
>> + for (y = 0; y < height; ++y) {
>> + qemu_pixman_linebuf_fill(linebuf, image, width, 0, y);
>> + png_write_row(png_ptr, buf);
>> + }
>> + qemu_pixman_image_unref(linebuf);
>> +
>> + png_write_end(png_ptr, NULL);
>> +
>> + png_destroy_write_struct(&png_ptr, &info_ptr);
>> +
>> + if (fclose(f) != 0) {
>> + error_setg(errp, "PNG creation failed. Unable to close file");
> Another spot for error_setg_errno
Thank you for your response! Will send the updated patch out soon.
Regards,
Kshitij
>
next prev parent reply other threads:[~2022-02-25 19:22 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-02-25 11:58 [PATCH 1/2] Replacing CONFIG_VNC_PNG with CONFIG_PNG Kshitij Suri
2022-02-25 11:58 ` [PATCH 2/2] Added parameter to take screenshot with screendump as PNG Kshitij Suri
2022-02-25 19:07 ` Eric Blake
2022-02-25 19:17 ` Kshitij Suri [this message]
2022-02-25 19:12 ` [PATCH 1/2] Replacing CONFIG_VNC_PNG with CONFIG_PNG Daniel P. Berrangé
2022-02-25 19:20 ` Kshitij Suri
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1dabf7c5-e408-c357-258f-747e5fe7bd12@nutanix.com \
--to=kshitij.suri@nutanix.com \
--cc=armbru@redhat.com \
--cc=dgilbert@redhat.com \
--cc=eblake@redhat.com \
--cc=kraxel@redhat.com \
--cc=prachatos.mitra@nutanix.com \
--cc=prerna.saxena@nutanix.com \
--cc=qemu-devel@nongnu.org \
--cc=soham.ghosh@nutanix.com \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.