[perl-Gtk2] Correct length of the Gtk2::Gdk::Pixbuf->get_pixels() return
- From: Torsten Schönfeld <tsch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [perl-Gtk2] Correct length of the Gtk2::Gdk::Pixbuf->get_pixels() return
- Date: Tue, 23 Nov 2010 21:07:35 +0000 (UTC)
commit 2cd14d266700d93aabdd5fe871f0a0ac35869f43
Author: Kevin Ryde <user42 zip com au>
Date: Sat Jul 31 08:03:29 2010 +1000
Correct length of the Gtk2::Gdk::Pixbuf->get_pixels() return
Shorten the assumed length to exclude rowstride padding on last row. It's not
always present, and in particular from $pixbuf->copy() it's not. Reading it
would go past the end of a malloced block.
https://bugzilla.gnome.org/show_bug.cgi?id=625692
NEWS | 5 +++++
t/GdkPixbuf.t | 5 +++--
xs/GdkPixbuf.xs | 33 ++++++++++++++++++++++++++++++---
3 files changed, 38 insertions(+), 5 deletions(-)
---
diff --git a/NEWS b/NEWS
index 82feeb4..9147c8f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Overview of changes in the next unstable release
+================================================
+
+* Fix length of Gtk2::Gdk::Pixbuf->get_pixels() return.
+
Overview of changes in Gtk2 1.230
=================================
diff --git a/t/GdkPixbuf.t b/t/GdkPixbuf.t
index a78a5e7..fb5b790 100644
--- a/t/GdkPixbuf.t
+++ b/t/GdkPixbuf.t
@@ -57,7 +57,7 @@ is ($pixbuf->get_height, 33);
is ($pixbuf->get_rowstride, 244);
$pixels = $pixbuf->get_pixels;
ok ($pixels);
-is (length($pixels), ($pixbuf->get_height * $pixbuf->get_rowstride));
+is (length($pixels), 8052);
$pixbuf = Gtk2::Gdk::Pixbuf->new ('rgb', FALSE, 8, 33, 61);
@@ -71,7 +71,8 @@ is ($pixbuf->get_height, 61);
is ($pixbuf->get_rowstride, 100); # 100 is aligned, 99 is actual
$pixels = $pixbuf->get_pixels;
ok ($pixels);
-is (length($pixels), ($pixbuf->get_height * $pixbuf->get_rowstride));
+# last row is not padded to the rowstride, hence 6099 not 6100
+is (length($pixels), 6099);
isa_ok ($pixbuf->copy, 'Gtk2::Gdk::Pixbuf', 'copy');
diff --git a/xs/GdkPixbuf.xs b/xs/GdkPixbuf.xs
index 14274cc..43116d4 100644
--- a/xs/GdkPixbuf.xs
+++ b/xs/GdkPixbuf.xs
@@ -303,16 +303,43 @@ gdk_pixbuf_get_bits_per_sample (pixbuf)
GdkPixbuf *pixbuf
## guchar *gdk_pixbuf_get_pixels (const GdkPixbuf *pixbuf)
+=for apidoc
+Return a copy of the bytes comprising the pixel data of C<$pixbuf>.
+
+As described in the Gdk Pixbuf reference manual (the "Note" section of
+"The GdkPixbuf Structure"), the last row does not extend to the
+rowstride, but ends with the last byte of the last pixel. The length
+of the C<get_pixels> return reflects this.
+=cut
SV *
gdk_pixbuf_get_pixels (pixbuf)
GdkPixbuf *pixbuf
PREINIT:
guchar * pixels;
+ STRLEN size;
CODE:
+ /* For reference, most pixbuf mallocs are height*rowstride, for
+ example gdk_pixbuf_new() does that. But gdk_pixbuf_copy()
+ mallocs only the lesser "last row unpadded" size. If the code
+ here used height*rowstride it would read past the end of such a
+ block.
+
+ Most of the time rowstride is the next multiple of 4, and a
+ malloced block is the next multiple of 4 too, so it's ok, but for
+ a bigger rowstride it's not.
+
+ The following calculation adapted from gdk_pixbuf_copy() circa
+ Gtk 2.16. bits_per_sample is only ever 8 currently, making it
+ simply n_channels many bytes-per-pixel, but the calculation
+ anticipates bits not a multiple of 8. */
+
+ size = ((gdk_pixbuf_get_height(pixbuf) - 1)
+ * gdk_pixbuf_get_rowstride(pixbuf)
+ + gdk_pixbuf_get_width(pixbuf)
+ * ((gdk_pixbuf_get_n_channels(pixbuf)
+ * gdk_pixbuf_get_bits_per_sample(pixbuf) + 7) / 8));
pixels = gdk_pixbuf_get_pixels (pixbuf);
- RETVAL = newSVpv ((gchar *) pixels,
- gdk_pixbuf_get_height (pixbuf)
- * gdk_pixbuf_get_rowstride (pixbuf));
+ RETVAL = newSVpv ((gchar *) pixels, size);
OUTPUT:
RETVAL
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]