* [PATCH v5 0/2] Option to take screenshot with screendump as PNG
@ 2022-04-08 7:13 Kshitij Suri
2022-04-08 7:13 ` [PATCH v5 1/2] Replacing CONFIG_VNC_PNG with CONFIG_PNG Kshitij Suri
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Kshitij Suri @ 2022-04-08 7:13 UTC (permalink / raw)
To: qemu-devel
Cc: soham.ghosh, peter.maydell, thuth, berrange, prerna.saxena,
dgilbert, armbru, Kshitij Suri, philippe.mathieu.daude, kraxel,
pbonzini, prachatos.mitra, eblake
This patch series aims to add PNG support using libpng to screendump method.
Currently screendump only supports PPM format, which is uncompressed.
PATCH 1 phases out CONFIG_VNC_PNG parameter and replaces it with CONFIG_PNG
which detects libpng support.
PATCH 2 contains core logic for PNG creation from pixman using libpng. HMP
command equivalent is also implemented in this patch.
v4->v5
- Modified format as a flag based optional parameter in HMP.
v3->v4
- Added condition to check for libpng only in PNG option is allowed
v2->v3
- HMP implementation fixes for png.
- Used enum for image format.
- Fixed description and updated QEMU support version.
v1->v2:
- Removed repeated alpha conversion operation.
- Modified logic to mirror png conversion in vnc-enc-tight.c file.
- Added a new CONFIG_PNG parameter for libpng support.
- Changed input format to enum instead of string.
- Improved error handling.
Kshitij Suri (2):
Replacing CONFIG_VNC_PNG with CONFIG_PNG
Added parameter to take screenshot with screendump as PNG
hmp-commands.hx | 11 ++---
meson.build | 12 +++---
meson_options.txt | 4 +-
monitor/hmp-cmds.c | 12 +++++-
qapi/ui.json | 24 +++++++++--
ui/console.c | 101 +++++++++++++++++++++++++++++++++++++++++++--
ui/vnc-enc-tight.c | 18 ++++----
ui/vnc.c | 4 +-
ui/vnc.h | 2 +-
9 files changed, 157 insertions(+), 31 deletions(-)
--
2.22.3
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v5 1/2] Replacing CONFIG_VNC_PNG with CONFIG_PNG
2022-04-08 7:13 [PATCH v5 0/2] Option to take screenshot with screendump as PNG Kshitij Suri
@ 2022-04-08 7:13 ` Kshitij Suri
2022-04-08 7:13 ` [PATCH v5 2/2] Added parameter to take screenshot with screendump as PNG Kshitij Suri
2022-04-14 8:55 ` [PATCH v5 0/2] Option " Kshitij Suri
2 siblings, 0 replies; 8+ messages in thread
From: Kshitij Suri @ 2022-04-08 7:13 UTC (permalink / raw)
To: qemu-devel
Cc: soham.ghosh, peter.maydell, thuth, berrange, prerna.saxena,
dgilbert, armbru, Kshitij Suri, philippe.mathieu.daude, kraxel,
pbonzini, prachatos.mitra, eblake
Libpng is only detected if VNC is enabled currently. This patch adds a
generalised png option in the meson build which is aimed to replace use of
CONFIG_VNC_PNG with CONFIG_PNG.
Signed-off-by: Kshitij Suri <kshitij.suri@nutanix.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
meson.build | 12 +++++++-----
meson_options.txt | 4 ++--
ui/vnc-enc-tight.c | 18 +++++++++---------
ui/vnc.c | 4 ++--
ui/vnc.h | 2 +-
5 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/meson.build b/meson.build
index 282e7c4650..0790ccef99 100644
--- a/meson.build
+++ b/meson.build
@@ -1115,14 +1115,16 @@ if gtkx11.found()
x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(),
kwargs: static_kwargs)
endif
-vnc = not_found
png = not_found
+if get_option('png').allowed() and have_system
+ png = dependency('libpng', required: get_option('png'),
+ method: 'pkg-config', kwargs: static_kwargs)
+endif
+vnc = not_found
jpeg = not_found
sasl = not_found
if get_option('vnc').allowed() and have_system
vnc = declare_dependency() # dummy dependency
- png = dependency('libpng', required: get_option('vnc_png'),
- method: 'pkg-config', kwargs: static_kwargs)
jpeg = dependency('libjpeg', required: get_option('vnc_jpeg'),
method: 'pkg-config', kwargs: static_kwargs)
sasl = cc.find_library('sasl2', has_headers: ['sasl/sasl.h'],
@@ -1554,9 +1556,9 @@ config_host_data.set('CONFIG_TPM', have_tpm)
config_host_data.set('CONFIG_USB_LIBUSB', libusb.found())
config_host_data.set('CONFIG_VDE', vde.found())
config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server)
+config_host_data.set('CONFIG_PNG', png.found())
config_host_data.set('CONFIG_VNC', vnc.found())
config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
-config_host_data.set('CONFIG_VNC_PNG', png.found())
config_host_data.set('CONFIG_VNC_SASL', sasl.found())
config_host_data.set('CONFIG_VIRTFS', have_virtfs)
config_host_data.set('CONFIG_VTE', vte.found())
@@ -3638,11 +3640,11 @@ summary_info += {'curses support': curses}
summary_info += {'virgl support': virgl}
summary_info += {'curl support': curl}
summary_info += {'Multipath support': mpathpersist}
+summary_info += {'PNG support': png}
summary_info += {'VNC support': vnc}
if vnc.found()
summary_info += {'VNC SASL support': sasl}
summary_info += {'VNC JPEG support': jpeg}
- summary_info += {'VNC PNG support': png}
endif
if targetos not in ['darwin', 'haiku', 'windows']
summary_info += {'OSS support': oss}
diff --git a/meson_options.txt b/meson_options.txt
index 52b11cead4..d85734f8e6 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -177,12 +177,12 @@ option('vde', type : 'feature', value : 'auto',
description: 'vde network backend support')
option('virglrenderer', type : 'feature', value : 'auto',
description: 'virgl rendering support')
+option('png', type : 'feature', value : 'auto',
+ description: 'PNG support with libpng')
option('vnc', type : 'feature', value : 'auto',
description: 'VNC server')
option('vnc_jpeg', type : 'feature', value : 'auto',
description: 'JPEG lossy compression for VNC server')
-option('vnc_png', type : 'feature', value : 'auto',
- description: 'PNG compression for VNC server')
option('vnc_sasl', type : 'feature', value : 'auto',
description: 'SASL authentication for VNC server')
option('vte', type : 'feature', value : 'auto',
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 7b86a4713d..e879cca7f5 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -32,7 +32,7 @@
INT32 definitions between jmorecfg.h (included by jpeglib.h) and
Win32 basetsd.h (included by windows.h). */
-#ifdef CONFIG_VNC_PNG
+#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
@@ -95,7 +95,7 @@ static const struct {
};
#endif
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
static const struct {
int png_zlib_level, png_filters;
} tight_png_conf[] = {
@@ -919,7 +919,7 @@ static int send_full_color_rect(VncState *vs, int x, int y, int w, int h)
int stream = 0;
ssize_t bytes;
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
if (tight_can_send_png_rect(vs, w, h)) {
return send_png_rect(vs, x, y, w, h, NULL);
}
@@ -966,7 +966,7 @@ static int send_mono_rect(VncState *vs, int x, int y,
int stream = 1;
int level = tight_conf[vs->tight->compression].mono_zlib_level;
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
if (tight_can_send_png_rect(vs, w, h)) {
int ret;
int bpp = vs->client_pf.bytes_per_pixel * 8;
@@ -1020,7 +1020,7 @@ static int send_mono_rect(VncState *vs, int x, int y,
struct palette_cb_priv {
VncState *vs;
uint8_t *header;
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
png_colorp png_palette;
#endif
};
@@ -1082,7 +1082,7 @@ static int send_palette_rect(VncState *vs, int x, int y,
int colors;
ssize_t bytes;
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
if (tight_can_send_png_rect(vs, w, h)) {
return send_png_rect(vs, x, y, w, h, palette);
}
@@ -1233,7 +1233,7 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality)
/*
* PNG compression stuff.
*/
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
static void write_png_palette(int idx, uint32_t pix, void *opaque)
{
struct palette_cb_priv *priv = opaque;
@@ -1379,7 +1379,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h,
buffer_reset(&vs->tight->png);
return 1;
}
-#endif /* CONFIG_VNC_PNG */
+#endif /* CONFIG_PNG */
static void vnc_tight_start(VncState *vs)
{
@@ -1706,7 +1706,7 @@ void vnc_tight_clear(VncState *vs)
#ifdef CONFIG_VNC_JPEG
buffer_free(&vs->tight->jpeg);
#endif
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
buffer_free(&vs->tight->png);
#endif
}
diff --git a/ui/vnc.c b/ui/vnc.c
index 310a873c21..8376291b47 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2165,7 +2165,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
vs->features |= VNC_FEATURE_TIGHT_MASK;
vs->vnc_encoding = enc;
break;
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
case VNC_ENCODING_TIGHT_PNG:
vs->features |= VNC_FEATURE_TIGHT_PNG_MASK;
vs->vnc_encoding = enc;
@@ -3256,7 +3256,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
#ifdef CONFIG_VNC_JPEG
buffer_init(&vs->tight->jpeg, "vnc-tight-jpeg/%p", sioc);
#endif
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
buffer_init(&vs->tight->png, "vnc-tight-png/%p", sioc);
#endif
buffer_init(&vs->zlib.zlib, "vnc-zlib/%p", sioc);
diff --git a/ui/vnc.h b/ui/vnc.h
index a7149831f9..a60fb13115 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -201,7 +201,7 @@ typedef struct VncTight {
#ifdef CONFIG_VNC_JPEG
Buffer jpeg;
#endif
-#ifdef CONFIG_VNC_PNG
+#ifdef CONFIG_PNG
Buffer png;
#endif
int levels[4];
--
2.22.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v5 2/2] Added parameter to take screenshot with screendump as PNG
2022-04-08 7:13 [PATCH v5 0/2] Option to take screenshot with screendump as PNG Kshitij Suri
2022-04-08 7:13 ` [PATCH v5 1/2] Replacing CONFIG_VNC_PNG with CONFIG_PNG Kshitij Suri
@ 2022-04-08 7:13 ` Kshitij Suri
2022-04-20 9:46 ` Dr. David Alan Gilbert
2022-04-21 13:55 ` Markus Armbruster
2022-04-14 8:55 ` [PATCH v5 0/2] Option " Kshitij Suri
2 siblings, 2 replies; 8+ messages in thread
From: Kshitij Suri @ 2022-04-08 7:13 UTC (permalink / raw)
To: qemu-devel
Cc: soham.ghosh, peter.maydell, thuth, berrange, prerna.saxena,
dgilbert, armbru, Kshitij Suri, philippe.mathieu.daude, kraxel,
pbonzini, prachatos.mitra, eblake
Currently screendump only supports PPM format, which is un-compressed. Added
a "format" parameter to QMP and HMP screendump command to support PNG image
capture using libpng.
QMP example usage:
{ "execute": "screendump", "arguments": { "filename": "/tmp/image",
"format":"png" } }
HMP example usage:
screendump /tmp/image -f png
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/718
Signed-off-by: Kshitij Suri <kshitij.suri@nutanix.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
diff to v4:
- Modified format to be an optional flag based parameter in HMP.
hmp-commands.hx | 11 ++---
monitor/hmp-cmds.c | 12 +++++-
qapi/ui.json | 24 +++++++++--
ui/console.c | 101 +++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 136 insertions(+), 12 deletions(-)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 8476277aa9..808020d005 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -244,11 +244,12 @@ ERST
{
.name = "screendump",
- .args_type = "filename:F,device:s?,head:i?",
- .params = "filename [device [head]]",
- .help = "save screen from head 'head' of display device 'device' "
- "into PPM image 'filename'",
- .cmd = hmp_screendump,
+ .args_type = "filename:F,format:-fs,device:s?,head:i?",
+ .params = "filename [-f format] [device [head]]",
+ .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,
},
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 634968498b..2442bfa989 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -1720,9 +1720,19 @@ 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_try_str(qdict, "format");
Error *err = NULL;
+ ImageFormat format;
- qmp_screendump(filename, id != NULL, id, id != NULL, head, &err);
+ format = qapi_enum_parse(&ImageFormat_lookup, input_format,
+ IMAGE_FORMAT_PPM, &err);
+ if (err) {
+ goto end;
+ }
+
+ qmp_screendump(filename, id != NULL, id, id != NULL, head,
+ input_format != NULL, format, &err);
+end:
hmp_handle_error(mon, err);
}
diff --git a/qapi/ui.json b/qapi/ui.json
index 664da9e462..98f0126999 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -157,12 +157,27 @@
##
{ 'command': 'expire_password', 'boxed': true, 'data': 'ExpirePasswordOptions' }
+##
+# @ImageFormat:
+#
+# Supported image format types.
+#
+# @png: PNG format
+#
+# @ppm: PPM format
+#
+# Since: 7.1
+#
+##
+{ 'enum': 'ImageFormat',
+ 'data': ['ppm', 'png'] }
+
##
# @screendump:
#
-# Write a PPM of the VGA screen to a file.
+# Capture the contents of a screen and write it to a file.
#
-# @filename: the path of a new PPM file to store the image
+# @filename: the path of a new file to store the image
#
# @device: ID of the display device that should be dumped. If this parameter
# is missing, the primary display will be used. (Since 2.12)
@@ -171,6 +186,8 @@
# parameter is missing, head #0 will be used. Also note that the head
# can only be specified in conjunction with the device ID. (Since 2.12)
#
+# @format: image format for screendump. (default: ppm) (Since 7.1)
+#
# Returns: Nothing on success
#
# Since: 0.14
@@ -183,7 +200,8 @@
#
##
{ 'command': 'screendump',
- 'data': {'filename': 'str', '*device': 'str', '*head': 'int'},
+ 'data': {'filename': 'str', '*device': 'str', '*head': 'int',
+ '*format': 'ImageFormat'},
'coroutine': true }
##
diff --git a/ui/console.c b/ui/console.c
index da434ce1b2..f42f64d556 100644
--- a/ui/console.c
+++ 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
@@ -291,6 +294,89 @@ 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_errno(errp, errno,
+ "Failed to create file from file descriptor");
+ return false;
+ }
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
+ NULL, NULL);
+ if (!png_ptr) {
+ error_setg(errp, "PNG creation failed. Unable to write struct");
+ fclose(f);
+ return false;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+
+ if (!info_ptr) {
+ error_setg(errp, "PNG creation failed. Unable to write info");
+ fclose(f);
+ 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_errno(errp, errno,
+ "PNG creation failed. Unable to close file");
+ return false;
+ }
+
+ return true;
+}
+
+#else /* no png support */
+
+static bool png_save(int fd, pixman_image_t *image, Error **errp)
+{
+ error_setg(errp, "Enable PNG support with libpng for screendump");
+ return false;
+}
+
+#endif /* CONFIG_PNG */
+
static bool ppm_save(int fd, pixman_image_t *image, Error **errp)
{
int width = pixman_image_get_width(image);
@@ -329,7 +415,8 @@ static void graphic_hw_update_bh(void *con)
/* Safety: coroutine-only, concurrent-coroutine safe, main thread only */
void coroutine_fn
qmp_screendump(const char *filename, bool has_device, const char *device,
- bool has_head, int64_t head, Error **errp)
+ bool has_head, int64_t head,
+ bool has_format, ImageFormat format, Error **errp)
{
g_autoptr(pixman_image_t) image = NULL;
QemuConsole *con;
@@ -385,8 +472,16 @@ qmp_screendump(const char *filename, bool has_device, const char *device,
* yields and releases the BQL. It could produce corrupted dump, but
* it should be otherwise safe.
*/
- if (!ppm_save(fd, image, errp)) {
- qemu_unlink(filename);
+ if (has_format && format == IMAGE_FORMAT_PNG) {
+ /* PNG format specified for screendump */
+ if (!png_save(fd, image, errp)) {
+ qemu_unlink(filename);
+ }
+ } else {
+ /* PPM format specified/default for screendump */
+ if (!ppm_save(fd, image, errp)) {
+ qemu_unlink(filename);
+ }
}
}
--
2.22.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v5 0/2] Option to take screenshot with screendump as PNG
2022-04-08 7:13 [PATCH v5 0/2] Option to take screenshot with screendump as PNG Kshitij Suri
2022-04-08 7:13 ` [PATCH v5 1/2] Replacing CONFIG_VNC_PNG with CONFIG_PNG Kshitij Suri
2022-04-08 7:13 ` [PATCH v5 2/2] Added parameter to take screenshot with screendump as PNG Kshitij Suri
@ 2022-04-14 8:55 ` Kshitij Suri
2022-04-21 13:57 ` Markus Armbruster
2 siblings, 1 reply; 8+ messages in thread
From: Kshitij Suri @ 2022-04-14 8:55 UTC (permalink / raw)
To: qemu-devel
Cc: soham.ghosh, peter.maydell, thuth, berrange, prerna.saxena,
dgilbert, armbru, philippe.mathieu.daude, kraxel, pbonzini,
prachatos.mitra, eblake
Hi,
Hope this mail finds everyone well! I have updated the code as required
and would be grateful if I could get your reviews for any changes that
are needed to be implemented in the patch. In case no change is
required, please do let me know the next steps for the same.
Regards,
Kshitij Suri
On 08/04/22 12:43 pm, Kshitij Suri wrote:
> This patch series aims to add PNG support using libpng to screendump method.
> Currently screendump only supports PPM format, which is uncompressed.
>
> PATCH 1 phases out CONFIG_VNC_PNG parameter and replaces it with CONFIG_PNG
> which detects libpng support.
>
> PATCH 2 contains core logic for PNG creation from pixman using libpng. HMP
> command equivalent is also implemented in this patch.
>
> v4->v5
> - Modified format as a flag based optional parameter in HMP.
>
> v3->v4
> - Added condition to check for libpng only in PNG option is allowed
>
> v2->v3
> - HMP implementation fixes for png.
> - Used enum for image format.
> - Fixed description and updated QEMU support version.
>
> v1->v2:
> - Removed repeated alpha conversion operation.
> - Modified logic to mirror png conversion in vnc-enc-tight.c file.
> - Added a new CONFIG_PNG parameter for libpng support.
> - Changed input format to enum instead of string.
> - Improved error handling.
>
> Kshitij Suri (2):
> Replacing CONFIG_VNC_PNG with CONFIG_PNG
> Added parameter to take screenshot with screendump as PNG
>
> hmp-commands.hx | 11 ++---
> meson.build | 12 +++---
> meson_options.txt | 4 +-
> monitor/hmp-cmds.c | 12 +++++-
> qapi/ui.json | 24 +++++++++--
> ui/console.c | 101 +++++++++++++++++++++++++++++++++++++++++++--
> ui/vnc-enc-tight.c | 18 ++++----
> ui/vnc.c | 4 +-
> ui/vnc.h | 2 +-
> 9 files changed, 157 insertions(+), 31 deletions(-)
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] Added parameter to take screenshot with screendump as PNG
2022-04-08 7:13 ` [PATCH v5 2/2] Added parameter to take screenshot with screendump as PNG Kshitij Suri
@ 2022-04-20 9:46 ` Dr. David Alan Gilbert
2022-04-21 13:55 ` Markus Armbruster
1 sibling, 0 replies; 8+ messages in thread
From: Dr. David Alan Gilbert @ 2022-04-20 9:46 UTC (permalink / raw)
To: Kshitij Suri
Cc: soham.ghosh, peter.maydell, thuth, berrange, prerna.saxena,
qemu-devel, armbru, philippe.mathieu.daude, kraxel, pbonzini,
prachatos.mitra, eblake
* Kshitij Suri (kshitij.suri@nutanix.com) wrote:
> Currently screendump only supports PPM format, which is un-compressed. Added
> a "format" parameter to QMP and HMP screendump command to support PNG image
> capture using libpng.
>
> QMP example usage:
> { "execute": "screendump", "arguments": { "filename": "/tmp/image",
> "format":"png" } }
>
> HMP example usage:
> screendump /tmp/image -f png
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/718
>
> Signed-off-by: Kshitij Suri <kshitij.suri@nutanix.com>
>
> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
> diff to v4:
> - Modified format to be an optional flag based parameter in HMP.
>
> hmp-commands.hx | 11 ++---
> monitor/hmp-cmds.c | 12 +++++-
> qapi/ui.json | 24 +++++++++--
> ui/console.c | 101 +++++++++++++++++++++++++++++++++++++++++++--
> 4 files changed, 136 insertions(+), 12 deletions(-)
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 8476277aa9..808020d005 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -244,11 +244,12 @@ ERST
>
> {
> .name = "screendump",
> - .args_type = "filename:F,device:s?,head:i?",
> - .params = "filename [device [head]]",
> - .help = "save screen from head 'head' of display device 'device' "
> - "into PPM image 'filename'",
> - .cmd = hmp_screendump,
> + .args_type = "filename:F,format:-fs,device:s?,head:i?",
> + .params = "filename [-f format] [device [head]]",
> + .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,
> },
>
> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
> index 634968498b..2442bfa989 100644
> --- a/monitor/hmp-cmds.c
> +++ b/monitor/hmp-cmds.c
> @@ -1720,9 +1720,19 @@ 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_try_str(qdict, "format");
> Error *err = NULL;
> + ImageFormat format;
>
> - qmp_screendump(filename, id != NULL, id, id != NULL, head, &err);
> + format = qapi_enum_parse(&ImageFormat_lookup, input_format,
> + IMAGE_FORMAT_PPM, &err);
> + if (err) {
> + goto end;
> + }
> +
> + qmp_screendump(filename, id != NULL, id, id != NULL, head,
> + input_format != NULL, format, &err);
> +end:
> hmp_handle_error(mon, err);
> }
For HMP:
Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> diff --git a/qapi/ui.json b/qapi/ui.json
> index 664da9e462..98f0126999 100644
> --- a/qapi/ui.json
> +++ b/qapi/ui.json
> @@ -157,12 +157,27 @@
> ##
> { 'command': 'expire_password', 'boxed': true, 'data': 'ExpirePasswordOptions' }
>
> +##
> +# @ImageFormat:
> +#
> +# Supported image format types.
> +#
> +# @png: PNG format
> +#
> +# @ppm: PPM format
> +#
> +# Since: 7.1
> +#
> +##
> +{ 'enum': 'ImageFormat',
> + 'data': ['ppm', 'png'] }
> +
> ##
> # @screendump:
> #
> -# Write a PPM of the VGA screen to a file.
> +# Capture the contents of a screen and write it to a file.
> #
> -# @filename: the path of a new PPM file to store the image
> +# @filename: the path of a new file to store the image
> #
> # @device: ID of the display device that should be dumped. If this parameter
> # is missing, the primary display will be used. (Since 2.12)
> @@ -171,6 +186,8 @@
> # parameter is missing, head #0 will be used. Also note that the head
> # can only be specified in conjunction with the device ID. (Since 2.12)
> #
> +# @format: image format for screendump. (default: ppm) (Since 7.1)
> +#
> # Returns: Nothing on success
> #
> # Since: 0.14
> @@ -183,7 +200,8 @@
> #
> ##
> { 'command': 'screendump',
> - 'data': {'filename': 'str', '*device': 'str', '*head': 'int'},
> + 'data': {'filename': 'str', '*device': 'str', '*head': 'int',
> + '*format': 'ImageFormat'},
> 'coroutine': true }
>
> ##
> diff --git a/ui/console.c b/ui/console.c
> index da434ce1b2..f42f64d556 100644
> --- a/ui/console.c
> +++ 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
> @@ -291,6 +294,89 @@ 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_errno(errp, errno,
> + "Failed to create file from file descriptor");
> + return false;
> + }
> +
> + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
> + NULL, NULL);
> + if (!png_ptr) {
> + error_setg(errp, "PNG creation failed. Unable to write struct");
> + fclose(f);
> + return false;
> + }
> +
> + info_ptr = png_create_info_struct(png_ptr);
> +
> + if (!info_ptr) {
> + error_setg(errp, "PNG creation failed. Unable to write info");
> + fclose(f);
> + 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_errno(errp, errno,
> + "PNG creation failed. Unable to close file");
> + return false;
> + }
> +
> + return true;
> +}
> +
> +#else /* no png support */
> +
> +static bool png_save(int fd, pixman_image_t *image, Error **errp)
> +{
> + error_setg(errp, "Enable PNG support with libpng for screendump");
> + return false;
> +}
> +
> +#endif /* CONFIG_PNG */
> +
> static bool ppm_save(int fd, pixman_image_t *image, Error **errp)
> {
> int width = pixman_image_get_width(image);
> @@ -329,7 +415,8 @@ static void graphic_hw_update_bh(void *con)
> /* Safety: coroutine-only, concurrent-coroutine safe, main thread only */
> void coroutine_fn
> qmp_screendump(const char *filename, bool has_device, const char *device,
> - bool has_head, int64_t head, Error **errp)
> + bool has_head, int64_t head,
> + bool has_format, ImageFormat format, Error **errp)
> {
> g_autoptr(pixman_image_t) image = NULL;
> QemuConsole *con;
> @@ -385,8 +472,16 @@ qmp_screendump(const char *filename, bool has_device, const char *device,
> * yields and releases the BQL. It could produce corrupted dump, but
> * it should be otherwise safe.
> */
> - if (!ppm_save(fd, image, errp)) {
> - qemu_unlink(filename);
> + if (has_format && format == IMAGE_FORMAT_PNG) {
> + /* PNG format specified for screendump */
> + if (!png_save(fd, image, errp)) {
> + qemu_unlink(filename);
> + }
> + } else {
> + /* PPM format specified/default for screendump */
> + if (!ppm_save(fd, image, errp)) {
> + qemu_unlink(filename);
> + }
> }
> }
>
> --
> 2.22.3
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 2/2] Added parameter to take screenshot with screendump as PNG
2022-04-08 7:13 ` [PATCH v5 2/2] Added parameter to take screenshot with screendump as PNG Kshitij Suri
2022-04-20 9:46 ` Dr. David Alan Gilbert
@ 2022-04-21 13:55 ` Markus Armbruster
1 sibling, 0 replies; 8+ messages in thread
From: Markus Armbruster @ 2022-04-21 13:55 UTC (permalink / raw)
To: Kshitij Suri
Cc: soham.ghosh, peter.maydell, thuth, berrange, prerna.saxena,
qemu-devel, dgilbert, philippe.mathieu.daude, kraxel, pbonzini,
prachatos.mitra, eblake
Kshitij Suri <kshitij.suri@nutanix.com> writes:
> Currently screendump only supports PPM format, which is un-compressed. Added
> a "format" parameter to QMP and HMP screendump command to support PNG image
> capture using libpng.
>
> QMP example usage:
> { "execute": "screendump", "arguments": { "filename": "/tmp/image",
> "format":"png" } }
>
> HMP example usage:
> screendump /tmp/image -f png
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/718
>
> Signed-off-by: Kshitij Suri <kshitij.suri@nutanix.com>
>
> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
QAPI schema
Acked-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 0/2] Option to take screenshot with screendump as PNG
2022-04-14 8:55 ` [PATCH v5 0/2] Option " Kshitij Suri
@ 2022-04-21 13:57 ` Markus Armbruster
2022-04-22 10:50 ` Gerd Hoffmann
0 siblings, 1 reply; 8+ messages in thread
From: Markus Armbruster @ 2022-04-21 13:57 UTC (permalink / raw)
To: Kshitij Suri
Cc: soham.ghosh, peter.maydell, thuth, berrange, prerna.saxena,
qemu-devel, dgilbert, philippe.mathieu.daude, kraxel, pbonzini,
prachatos.mitra, eblake
Kshitij Suri <kshitij.suri@nutanix.com> writes:
> Hi,
>
> Hope this mail finds everyone well! I have updated the code as
> required and would be grateful if I could get your reviews for any
> changes that are needed to be implemented in the patch. In case no
> change is required, please do let me know the next steps for the same.
Unless something still comes up in review, the next step is merging.
Gerd, would you like to take it?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v5 0/2] Option to take screenshot with screendump as PNG
2022-04-21 13:57 ` Markus Armbruster
@ 2022-04-22 10:50 ` Gerd Hoffmann
0 siblings, 0 replies; 8+ messages in thread
From: Gerd Hoffmann @ 2022-04-22 10:50 UTC (permalink / raw)
To: Markus Armbruster
Cc: soham.ghosh, peter.maydell, thuth, berrange, prerna.saxena,
qemu-devel, dgilbert, Kshitij Suri, philippe.mathieu.daude,
pbonzini, prachatos.mitra, eblake
On Thu, Apr 21, 2022 at 03:57:30PM +0200, Markus Armbruster wrote:
> Kshitij Suri <kshitij.suri@nutanix.com> writes:
>
> > Hi,
> >
> > Hope this mail finds everyone well! I have updated the code as
> > required and would be grateful if I could get your reviews for any
> > changes that are needed to be implemented in the patch. In case no
> > change is required, please do let me know the next steps for the same.
>
> Unless something still comes up in review, the next step is merging.
>
> Gerd, would you like to take it?
I'm busy going through the backlog (patches not merged during freeze)
anyway. Queued this now.
take care,
Gerd
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2022-04-22 11:46 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-08 7:13 [PATCH v5 0/2] Option to take screenshot with screendump as PNG Kshitij Suri
2022-04-08 7:13 ` [PATCH v5 1/2] Replacing CONFIG_VNC_PNG with CONFIG_PNG Kshitij Suri
2022-04-08 7:13 ` [PATCH v5 2/2] Added parameter to take screenshot with screendump as PNG Kshitij Suri
2022-04-20 9:46 ` Dr. David Alan Gilbert
2022-04-21 13:55 ` Markus Armbruster
2022-04-14 8:55 ` [PATCH v5 0/2] Option " Kshitij Suri
2022-04-21 13:57 ` Markus Armbruster
2022-04-22 10:50 ` Gerd Hoffmann
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.