From 5e376cc7da8a198e7f9e83207d864de0bf40dee1 Mon Sep 17 00:00:00 2001 From: Sean Davis Date: Sat, 22 May 2021 07:56:58 -0400 Subject: [PATCH 1/9] Add support for image-data --- meson.build | 1 + src/Bubble.vala | 20 ++++++++++++- src/ImageData.vala | 66 +++++++++++++++++++++++++++++++++++++++++++ src/Notification.vala | 6 ++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/ImageData.vala diff --git a/meson.build b/meson.build index 47a994fa..d031b340 100644 --- a/meson.build +++ b/meson.build @@ -19,6 +19,7 @@ executable( 'src/Bubble.vala', 'src/Confirmation.vala', 'src/DBus.vala', + 'src/ImageData.vala', 'src/Notification.vala', 'src/Widgets/MaskedImage.vala', css_gresource, diff --git a/src/Bubble.vala b/src/Bubble.vala index c11ee60e..61abff7c 100644 --- a/src/Bubble.vala +++ b/src/Bubble.vala @@ -119,7 +119,25 @@ public class Notifications.Bubble : AbstractBubble { var image_overlay = new Gtk.Overlay (); image_overlay.valign = Gtk.Align.START; - if (notification.image_path != null) { + if (notification.image_data != null) { + try { + var scale = get_style_context ().get_scale (); + var pixbuf = notification.image_data.to_pixbuf_at_size (48 * scale, 48 * scale); + + var masked_image = new Notifications.MaskedImage (pixbuf); + + app_image.pixel_size = 24; + app_image.halign = app_image.valign = Gtk.Align.END; + + image_overlay.add (masked_image); + image_overlay.add_overlay (app_image); + } catch (Error e) { + critical ("Unable to mask image: %s", e.message); + + app_image.pixel_size = 48; + image_overlay.add (app_image); + } + } else if (notification.image_path != null) { try { var scale = get_style_context ().get_scale (); var pixbuf = new Gdk.Pixbuf.from_file_at_size (notification.image_path, 48 * scale, 48 * scale); diff --git a/src/ImageData.vala b/src/ImageData.vala new file mode 100644 index 00000000..54833be7 --- /dev/null +++ b/src/ImageData.vala @@ -0,0 +1,66 @@ +/* +* Copyright 2020 elementary, Inc. (https://elementary.io) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public +* License as published by the Free Software Foundation; either +* version 3 of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301 USA +* +*/ + +public class Notifications.ImageData : GLib.Object { + public int width { get; construct; } + public int height { get; construct; } + public int rowstride { get; construct; } + public bool has_alpha { get; construct; } + public int bits_per_sample { get; construct; } + public int n_channels { get; construct; } + public void* raw { get; set; } + + public ImageData (int width, int height, int rowstride, bool has_alpha, int bits_per_sample, int n_channels, void* raw) { + Object ( + width: width, + height: height, + rowstride: rowstride, + has_alpha: has_alpha, + bits_per_sample: bits_per_sample, + n_channels: n_channels, + raw: raw + ); + } + + /** + * Decode a raw image (iiibiiay) sent through 'hints' + */ + public static ImageData from_variant(Variant img) + { + // Read the image fields + int v_width = img.get_child_value(0).get_int32(); + int v_height = img.get_child_value(1).get_int32(); + int v_rowstride = img.get_child_value(2).get_int32(); + bool v_has_alpha = img.get_child_value(3).get_boolean(); + int v_bits_per_sample = img.get_child_value(4).get_int32(); + int v_n_channels = img.get_child_value(5).get_int32(); + void* v_raw = img.get_child_value (6).get_data(); + + return new ImageData(v_width, v_height, v_rowstride, v_has_alpha, v_bits_per_sample, v_n_channels, v_raw); + } + + public Gdk.Pixbuf to_pixbuf_at_size(int w, int h) { + unowned uint8[] data = (uint8[]) raw; + var pixbuf = new Gdk.Pixbuf.with_unowned_data (data, Gdk.Colorspace.RGB, + has_alpha, bits_per_sample, width, height, rowstride, null); + var scaled_pixbuf = pixbuf.scale_simple(w, h, Gdk.InterpType.BILINEAR); + return scaled_pixbuf; + } +} diff --git a/src/Notification.vala b/src/Notification.vala index f2ae2132..433b278d 100644 --- a/src/Notification.vala +++ b/src/Notification.vala @@ -30,6 +30,7 @@ public class Notifications.Notification : GLib.Object { public string app_name { get; construct; } public string body { get; construct set; } public string? image_path { get; private set; default = null; } + public Notifications.ImageData? image_data { get; private set; default = null; } public string summary { get; construct set; } private static Regex entity_regex; @@ -67,6 +68,10 @@ public class Notifications.Notification : GLib.Object { unowned Variant? variant = null; + if ((variant = hints.lookup ("image-data")) != null) { + image_data = ImageData.from_variant (variant); + } + if ((variant = hints.lookup ("urgency")) != null && variant.is_of_type (VariantType.BYTE)) { priority = (GLib.NotificationPriority) variant.get_byte (); } @@ -113,4 +118,5 @@ public class Notifications.Notification : GLib.Object { return text; } + } From 806fa1bb8c9996cfee112c2071d0a90af00b1603 Mon Sep 17 00:00:00 2001 From: Sean Davis Date: Sat, 22 May 2021 10:42:57 -0400 Subject: [PATCH 2/9] Simplify Pixbuf generation, ImageData construction --- src/Bubble.vala | 27 +++++++-------------------- src/ImageData.vala | 38 +++++++++++++++----------------------- src/Notification.vala | 2 +- 3 files changed, 23 insertions(+), 44 deletions(-) diff --git a/src/Bubble.vala b/src/Bubble.vala index 61abff7c..95226980 100644 --- a/src/Bubble.vala +++ b/src/Bubble.vala @@ -119,28 +119,15 @@ public class Notifications.Bubble : AbstractBubble { var image_overlay = new Gtk.Overlay (); image_overlay.valign = Gtk.Align.START; - if (notification.image_data != null) { + if (notification.image_data != null || notification.image_path != null) { try { + Gdk.Pixbuf pixbuf; var scale = get_style_context ().get_scale (); - var pixbuf = notification.image_data.to_pixbuf_at_size (48 * scale, 48 * scale); - - var masked_image = new Notifications.MaskedImage (pixbuf); - - app_image.pixel_size = 24; - app_image.halign = app_image.valign = Gtk.Align.END; - - image_overlay.add (masked_image); - image_overlay.add_overlay (app_image); - } catch (Error e) { - critical ("Unable to mask image: %s", e.message); - - app_image.pixel_size = 48; - image_overlay.add (app_image); - } - } else if (notification.image_path != null) { - try { - var scale = get_style_context ().get_scale (); - var pixbuf = new Gdk.Pixbuf.from_file_at_size (notification.image_path, 48 * scale, 48 * scale); + if (notification.image_data != null) { + pixbuf = notification.image_data.get_pixbuf (); + } else { + pixbuf = new Gdk.Pixbuf.from_file_at_size (notification.image_path, 48 * scale, 48 * scale); + } var masked_image = new Notifications.MaskedImage (pixbuf); diff --git a/src/ImageData.vala b/src/ImageData.vala index 54833be7..c4ef7e80 100644 --- a/src/ImageData.vala +++ b/src/ImageData.vala @@ -25,42 +25,34 @@ public class Notifications.ImageData : GLib.Object { public bool has_alpha { get; construct; } public int bits_per_sample { get; construct; } public int n_channels { get; construct; } - public void* raw { get; set; } - - public ImageData (int width, int height, int rowstride, bool has_alpha, int bits_per_sample, int n_channels, void* raw) { - Object ( - width: width, - height: height, - rowstride: rowstride, - has_alpha: has_alpha, - bits_per_sample: bits_per_sample, - n_channels: n_channels, - raw: raw - ); - } + public void* raw { get; construct; } /** * Decode a raw image (iiibiiay) sent through 'hints' */ - public static ImageData from_variant(Variant img) - { - // Read the image fields + public ImageData.from_variant(Variant img) { int v_width = img.get_child_value(0).get_int32(); int v_height = img.get_child_value(1).get_int32(); int v_rowstride = img.get_child_value(2).get_int32(); bool v_has_alpha = img.get_child_value(3).get_boolean(); int v_bits_per_sample = img.get_child_value(4).get_int32(); int v_n_channels = img.get_child_value(5).get_int32(); - void* v_raw = img.get_child_value (6).get_data(); + // Storing a pointer to the uint8[] since Glib does not allow it as a property + void* v_raw = img.get_child_value (6).get_data(); - return new ImageData(v_width, v_height, v_rowstride, v_has_alpha, v_bits_per_sample, v_n_channels, v_raw); + Object ( + width: v_width, + height: v_height, + rowstride: v_rowstride, + has_alpha: v_has_alpha, + bits_per_sample: v_bits_per_sample, + n_channels: v_n_channels, + raw: v_raw + ); } - public Gdk.Pixbuf to_pixbuf_at_size(int w, int h) { - unowned uint8[] data = (uint8[]) raw; - var pixbuf = new Gdk.Pixbuf.with_unowned_data (data, Gdk.Colorspace.RGB, + public Gdk.Pixbuf get_pixbuf () { + return new Gdk.Pixbuf.with_unowned_data ((uint8[]) raw, Gdk.Colorspace.RGB, has_alpha, bits_per_sample, width, height, rowstride, null); - var scaled_pixbuf = pixbuf.scale_simple(w, h, Gdk.InterpType.BILINEAR); - return scaled_pixbuf; } } diff --git a/src/Notification.vala b/src/Notification.vala index 433b278d..60ea2fc6 100644 --- a/src/Notification.vala +++ b/src/Notification.vala @@ -69,7 +69,7 @@ public class Notifications.Notification : GLib.Object { unowned Variant? variant = null; if ((variant = hints.lookup ("image-data")) != null) { - image_data = ImageData.from_variant (variant); + image_data = new ImageData.from_variant (variant); } if ((variant = hints.lookup ("urgency")) != null && variant.is_of_type (VariantType.BYTE)) { From ca88c4bfd982e0b21a79ac211704fdddf79e160b Mon Sep 17 00:00:00 2001 From: Sean Davis Date: Sat, 22 May 2021 10:48:15 -0400 Subject: [PATCH 3/9] Pass linting --- src/ImageData.vala | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ImageData.vala b/src/ImageData.vala index c4ef7e80..f4232634 100644 --- a/src/ImageData.vala +++ b/src/ImageData.vala @@ -30,15 +30,15 @@ public class Notifications.ImageData : GLib.Object { /** * Decode a raw image (iiibiiay) sent through 'hints' */ - public ImageData.from_variant(Variant img) { - int v_width = img.get_child_value(0).get_int32(); - int v_height = img.get_child_value(1).get_int32(); - int v_rowstride = img.get_child_value(2).get_int32(); - bool v_has_alpha = img.get_child_value(3).get_boolean(); - int v_bits_per_sample = img.get_child_value(4).get_int32(); - int v_n_channels = img.get_child_value(5).get_int32(); + public ImageData.from_variant (Variant img) { + int v_width = img.get_child_value (0).get_int32 (); + int v_height = img.get_child_value (1).get_int32 (); + int v_rowstride = img.get_child_value (2).get_int32 (); + bool v_has_alpha = img.get_child_value (3).get_boolean (); + int v_bits_per_sample = img.get_child_value (4).get_int32 (); + int v_n_channels = img.get_child_value (5).get_int32 (); // Storing a pointer to the uint8[] since Glib does not allow it as a property - void* v_raw = img.get_child_value (6).get_data(); + void* v_raw = img.get_child_value (6).get_data (); Object ( width: v_width, From f8e448789be1bd15db0e30c2d40ffa27b08d76d9 Mon Sep 17 00:00:00 2001 From: Sean Davis Date: Sun, 23 May 2021 01:47:29 -0400 Subject: [PATCH 4/9] Simplify image-data handling, copy our own pixbuf from the unowned buffer --- meson.build | 1 - src/Bubble.vala | 6 ++--- src/ImageData.vala | 58 ------------------------------------------- src/Notification.vala | 18 ++++++++++++-- 4 files changed, 19 insertions(+), 64 deletions(-) delete mode 100644 src/ImageData.vala diff --git a/meson.build b/meson.build index d031b340..47a994fa 100644 --- a/meson.build +++ b/meson.build @@ -19,7 +19,6 @@ executable( 'src/Bubble.vala', 'src/Confirmation.vala', 'src/DBus.vala', - 'src/ImageData.vala', 'src/Notification.vala', 'src/Widgets/MaskedImage.vala', css_gresource, diff --git a/src/Bubble.vala b/src/Bubble.vala index 95226980..bc312da7 100644 --- a/src/Bubble.vala +++ b/src/Bubble.vala @@ -119,12 +119,12 @@ public class Notifications.Bubble : AbstractBubble { var image_overlay = new Gtk.Overlay (); image_overlay.valign = Gtk.Align.START; - if (notification.image_data != null || notification.image_path != null) { + if (notification.pixbuf != null || notification.image_path != null) { try { Gdk.Pixbuf pixbuf; var scale = get_style_context ().get_scale (); - if (notification.image_data != null) { - pixbuf = notification.image_data.get_pixbuf (); + if (notification.pixbuf != null) { + pixbuf = notification.pixbuf; } else { pixbuf = new Gdk.Pixbuf.from_file_at_size (notification.image_path, 48 * scale, 48 * scale); } diff --git a/src/ImageData.vala b/src/ImageData.vala deleted file mode 100644 index f4232634..00000000 --- a/src/ImageData.vala +++ /dev/null @@ -1,58 +0,0 @@ -/* -* Copyright 2020 elementary, Inc. (https://elementary.io) -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public -* License as published by the Free Software Foundation; either -* version 3 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public -* License along with this program; if not, write to the -* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -* Boston, MA 02110-1301 USA -* -*/ - -public class Notifications.ImageData : GLib.Object { - public int width { get; construct; } - public int height { get; construct; } - public int rowstride { get; construct; } - public bool has_alpha { get; construct; } - public int bits_per_sample { get; construct; } - public int n_channels { get; construct; } - public void* raw { get; construct; } - - /** - * Decode a raw image (iiibiiay) sent through 'hints' - */ - public ImageData.from_variant (Variant img) { - int v_width = img.get_child_value (0).get_int32 (); - int v_height = img.get_child_value (1).get_int32 (); - int v_rowstride = img.get_child_value (2).get_int32 (); - bool v_has_alpha = img.get_child_value (3).get_boolean (); - int v_bits_per_sample = img.get_child_value (4).get_int32 (); - int v_n_channels = img.get_child_value (5).get_int32 (); - // Storing a pointer to the uint8[] since Glib does not allow it as a property - void* v_raw = img.get_child_value (6).get_data (); - - Object ( - width: v_width, - height: v_height, - rowstride: v_rowstride, - has_alpha: v_has_alpha, - bits_per_sample: v_bits_per_sample, - n_channels: v_n_channels, - raw: v_raw - ); - } - - public Gdk.Pixbuf get_pixbuf () { - return new Gdk.Pixbuf.with_unowned_data ((uint8[]) raw, Gdk.Colorspace.RGB, - has_alpha, bits_per_sample, width, height, rowstride, null); - } -} diff --git a/src/Notification.vala b/src/Notification.vala index 60ea2fc6..3af062a0 100644 --- a/src/Notification.vala +++ b/src/Notification.vala @@ -30,7 +30,7 @@ public class Notifications.Notification : GLib.Object { public string app_name { get; construct; } public string body { get; construct set; } public string? image_path { get; private set; default = null; } - public Notifications.ImageData? image_data { get; private set; default = null; } + public Gdk.Pixbuf? pixbuf { get; private set; default = null; } public string summary { get; construct set; } private static Regex entity_regex; @@ -69,7 +69,7 @@ public class Notifications.Notification : GLib.Object { unowned Variant? variant = null; if ((variant = hints.lookup ("image-data")) != null) { - image_data = new ImageData.from_variant (variant); + pixbuf = read_image_data (variant); } if ((variant = hints.lookup ("urgency")) != null && variant.is_of_type (VariantType.BYTE)) { @@ -119,4 +119,18 @@ public class Notifications.Notification : GLib.Object { return text; } + private Gdk.Pixbuf? read_image_data (Variant img) { + int width = img.get_child_value (0).get_int32 (); + int height = img.get_child_value (1).get_int32 (); + int rowstride = img.get_child_value (2).get_int32 (); + bool has_alpha = img.get_child_value (3).get_boolean (); + int bits_per_sample = img.get_child_value (4).get_int32 (); + unowned uint8[] raw = (uint8[]) img.get_child_value (6).get_data (); + + // Build the pixbuf from the unowned buffer, and copy it to maintain our own instance. + Gdk.Pixbuf pixbuf = new Gdk.Pixbuf.with_unowned_data (raw, Gdk.Colorspace.RGB, + has_alpha, bits_per_sample, width, height, rowstride, null); + return pixbuf.copy (); + } + } From a63f0ea30c1bb93ece3764409873b334ec07392d Mon Sep 17 00:00:00 2001 From: Sean Davis Date: Sun, 23 May 2021 01:58:00 -0400 Subject: [PATCH 5/9] Do not overlay notification images with fallback app icon --- src/Bubble.vala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Bubble.vala b/src/Bubble.vala index bc312da7..862369c9 100644 --- a/src/Bubble.vala +++ b/src/Bubble.vala @@ -130,12 +130,13 @@ public class Notifications.Bubble : AbstractBubble { } var masked_image = new Notifications.MaskedImage (pixbuf); - - app_image.pixel_size = 24; - app_image.halign = app_image.valign = Gtk.Align.END; - image_overlay.add (masked_image); - image_overlay.add_overlay (app_image); + + if (app_image.icon_name != "dialog-information") { + app_image.pixel_size = 24; + app_image.halign = app_image.valign = Gtk.Align.END; + image_overlay.add_overlay (app_image); + } } catch (Error e) { critical ("Unable to mask image: %s", e.message); From 89e738056aef6021e58283e1bf8ebb5dfdfeb2fd Mon Sep 17 00:00:00 2001 From: Sean Davis Date: Sun, 23 May 2021 02:21:29 -0400 Subject: [PATCH 6/9] Support all variants of image-data --- src/Notification.vala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Notification.vala b/src/Notification.vala index 3af062a0..b9f11537 100644 --- a/src/Notification.vala +++ b/src/Notification.vala @@ -68,10 +68,6 @@ public class Notifications.Notification : GLib.Object { unowned Variant? variant = null; - if ((variant = hints.lookup ("image-data")) != null) { - pixbuf = read_image_data (variant); - } - if ((variant = hints.lookup ("urgency")) != null && variant.is_of_type (VariantType.BYTE)) { priority = (GLib.NotificationPriority) variant.get_byte (); } @@ -86,6 +82,10 @@ public class Notifications.Notification : GLib.Object { } } + if ((variant = hints.lookup ("image-data")) != null || (variant = hints.lookup ("image_data")) != null || (variant = hints.lookup ("icon_data")) != null) { + pixbuf = read_image_data (variant); + } + if ((variant = hints.lookup ("image-path")) != null || (variant = hints.lookup ("image_path")) != null) { image_path = variant.get_string (); From 50d911f316b77ef3312e8f7886a37e8037229198 Mon Sep 17 00:00:00 2001 From: Sean Davis Date: Tue, 25 May 2021 21:15:11 -0400 Subject: [PATCH 7/9] Rename image_data variable and function --- src/Bubble.vala | 6 +++--- src/Notification.vala | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Bubble.vala b/src/Bubble.vala index 862369c9..9673bc4f 100644 --- a/src/Bubble.vala +++ b/src/Bubble.vala @@ -119,12 +119,12 @@ public class Notifications.Bubble : AbstractBubble { var image_overlay = new Gtk.Overlay (); image_overlay.valign = Gtk.Align.START; - if (notification.pixbuf != null || notification.image_path != null) { + if (notification.image_data != null || notification.image_path != null) { try { Gdk.Pixbuf pixbuf; var scale = get_style_context ().get_scale (); - if (notification.pixbuf != null) { - pixbuf = notification.pixbuf; + if (notification.image_data != null) { + pixbuf = notification.image_data; } else { pixbuf = new Gdk.Pixbuf.from_file_at_size (notification.image_path, 48 * scale, 48 * scale); } diff --git a/src/Notification.vala b/src/Notification.vala index b9f11537..fd37349a 100644 --- a/src/Notification.vala +++ b/src/Notification.vala @@ -30,7 +30,7 @@ public class Notifications.Notification : GLib.Object { public string app_name { get; construct; } public string body { get; construct set; } public string? image_path { get; private set; default = null; } - public Gdk.Pixbuf? pixbuf { get; private set; default = null; } + public Gdk.Pixbuf? image_data { get; private set; default = null; } public string summary { get; construct set; } private static Regex entity_regex; @@ -83,7 +83,7 @@ public class Notifications.Notification : GLib.Object { } if ((variant = hints.lookup ("image-data")) != null || (variant = hints.lookup ("image_data")) != null || (variant = hints.lookup ("icon_data")) != null) { - pixbuf = read_image_data (variant); + image_data = image_data_variant_to_pixbuf (variant); } if ((variant = hints.lookup ("image-path")) != null || (variant = hints.lookup ("image_path")) != null) { @@ -119,7 +119,7 @@ public class Notifications.Notification : GLib.Object { return text; } - private Gdk.Pixbuf? read_image_data (Variant img) { + private Gdk.Pixbuf? image_data_variant_to_pixbuf (Variant img) { int width = img.get_child_value (0).get_int32 (); int height = img.get_child_value (1).get_int32 (); int rowstride = img.get_child_value (2).get_int32 (); From 105a6dd6e0939f2d92ea99f8b5afdf8f722cee54 Mon Sep 17 00:00:00 2001 From: Sean Davis Date: Tue, 25 May 2021 21:25:34 -0400 Subject: [PATCH 8/9] Add type check to image_data --- src/Notification.vala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Notification.vala b/src/Notification.vala index fd37349a..30516465 100644 --- a/src/Notification.vala +++ b/src/Notification.vala @@ -120,6 +120,10 @@ public class Notifications.Notification : GLib.Object { } private Gdk.Pixbuf? image_data_variant_to_pixbuf (Variant img) { + if (img.get_type_string() != "(iiibiiay)") { + warning ("Invalid type string: %s", img.get_type_string()); + return null; + } int width = img.get_child_value (0).get_int32 (); int height = img.get_child_value (1).get_int32 (); int rowstride = img.get_child_value (2).get_int32 (); From dc77223c4d1de5d4f3fb127a688305193102dfcc Mon Sep 17 00:00:00 2001 From: Sean Davis Date: Tue, 25 May 2021 21:27:12 -0400 Subject: [PATCH 9/9] Fix linting --- src/Notification.vala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Notification.vala b/src/Notification.vala index 30516465..63b7ea3d 100644 --- a/src/Notification.vala +++ b/src/Notification.vala @@ -120,8 +120,8 @@ public class Notifications.Notification : GLib.Object { } private Gdk.Pixbuf? image_data_variant_to_pixbuf (Variant img) { - if (img.get_type_string() != "(iiibiiay)") { - warning ("Invalid type string: %s", img.get_type_string()); + if (img.get_type_string () != "(iiibiiay)") { + warning ("Invalid type string: %s", img.get_type_string ()); return null; } int width = img.get_child_value (0).get_int32 ();