[librsvg/librsvg-2.48] Reimplement pixbuf_from_surface() in terms of iterators and .as_pixels()
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/librsvg-2.48] Reimplement pixbuf_from_surface() in terms of iterators and .as_pixels()
- Date: Fri, 29 May 2020 20:48:26 +0000 (UTC)
commit 7719415a560957220a75f43622155ef95b40074d
Author: Federico Mena Quintero <federico gnome org>
Date: Thu May 28 19:41:55 2020 -0500
Reimplement pixbuf_from_surface() in terms of iterators and .as_pixels()
This gets rid of the calculation and checking of the offset of each
pixel.
Baseline:
pixbuf_from_surface time: [1.5888 ms 1.5899 ms 1.5911 ms]
Use SharedImageSurface.rows():
pixbuf_from_surface time: [1.4434 ms 1.4514 ms 1.4592 ms]
change: [-9.5490% -9.2322% -8.8676%] (p = 0.00 < 0.05)
Use as_pixels() and iterators for GdkPixbuf:
pixbuf_from_surface time: [672.70 us 673.20 us 673.75 us]
change: [-53.489% -53.329% -53.174%] (p = 0.00 < 0.05)
This is part of https://gitlab.gnome.org/GNOME/librsvg/-/issues/585
Cargo.lock | 1 +
librsvg/Cargo.toml | 1 +
librsvg/pixbuf_utils.rs | 66 +++++++++++++++++++----------------------------
rsvg_internals/src/lib.rs | 2 +-
4 files changed, 29 insertions(+), 41 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index e91ae772..a13f3a85 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -695,6 +695,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
+ "rgb",
"rsvg_internals",
"url",
]
diff --git a/librsvg/Cargo.toml b/librsvg/Cargo.toml
index 669ec866..cb2c9f19 100644
--- a/librsvg/Cargo.toml
+++ b/librsvg/Cargo.toml
@@ -23,6 +23,7 @@ gio = { version="0.8.0", features=["v2_50"] } # per configure.ac
gio-sys = "0.9.0"
gobject-sys = "0.9.0"
libc = "0.2"
+rgb = "0.8.17"
rsvg_internals = { path = "../rsvg_internals" }
url = "2"
diff --git a/librsvg/pixbuf_utils.rs b/librsvg/pixbuf_utils.rs
index e6dcef7c..6d5df5a7 100644
--- a/librsvg/pixbuf_utils.rs
+++ b/librsvg/pixbuf_utils.rs
@@ -4,6 +4,7 @@ use std::ptr;
use gdk_pixbuf::{Colorspace, Pixbuf};
use gio::prelude::*;
use glib::translate::*;
+use rgb::{AsPixels, RGBA8};
use url::Url;
use crate::c_api::checked_i32;
@@ -36,61 +37,46 @@ pub fn pixbuf_from_surface(surface: &SharedImageSurface) -> Result<Pixbuf, Rende
let height = surface.height();
let pixbuf = pixbuf_new(width, height)?;
+ assert!(pixbuf.get_colorspace() == Colorspace::Rgb);
+ assert!(pixbuf.get_bits_per_sample() == 8);
+ assert!(pixbuf.get_n_channels() == 4);
- for (y, row) in surface.rows().enumerate() {
- for (x, pixel) in row.iter().enumerate() {
- let (r, g, b, a) = if pixel.a == 0 {
+ let pixels = unsafe { pixbuf.get_pixels() };
+ let width = width as usize;
+ let height = height as usize;
+ let stride = pixbuf.get_rowstride() as usize;
+ let width_in_bytes = width * 4;
+ assert!(width_in_bytes <= stride);
+
+ let pixbuf_rows = pixels.chunks_exact_mut(stride).take(height);
+
+ for (src_row, dest_row) in surface.rows().zip(pixbuf_rows) {
+ let row: &mut [RGBA8] = dest_row[..width_in_bytes].as_pixels_mut();
+
+ for (src, dest) in src_row.iter().zip(row.iter_mut()) {
+ let (r, g, b, a) = if src.a == 0 {
(0, 0, 0, 0)
} else {
let pixel = Pixel {
- r: pixel.r,
- g: pixel.g,
- b: pixel.b,
- a: pixel.a,
+ r: src.r,
+ g: src.g,
+ b: src.b,
+ a: src.a,
}.unpremultiply();
(pixel.r, pixel.g, pixel.b, pixel.a)
};
- // FIXME: Use pixbuf.put_pixel when
- // https://github.com/gtk-rs/gdk-pixbuf/issues/147
- // is integrated
- my_put_pixel(&pixbuf, x as i32, y as i32, r, g, b, a);
+ dest.r = r;
+ dest.g = g;
+ dest.b = b;
+ dest.a = a;
}
}
Ok(pixbuf)
}
-// Copied from gtk-rs/gdk-pixbuf
-//
-// See the following:
-// https://gitlab.gnome.org/GNOME/librsvg/-/issues/584
-// https://github.com/gtk-rs/gdk-pixbuf/issues/147
-//
-// Arithmetic can overflow in the computation of `pos` if it is not done with usize
-// values (everything coming out of a Pixbuf is i32).
-//
-// When this fix appears in a gtk-rs release, we can remove this.
-fn my_put_pixel(pixbuf: &Pixbuf, x: i32, y: i32, red: u8, green: u8, blue: u8, alpha: u8) {
- unsafe {
- let x = x as usize;
- let y = y as usize;
- let n_channels = pixbuf.get_n_channels() as usize;
- assert!(n_channels == 3 || n_channels == 4);
- let rowstride = pixbuf.get_rowstride() as usize;
- let pixels = pixbuf.get_pixels();
- let pos = y * rowstride + x * n_channels;
-
- pixels[pos] = red;
- pixels[pos + 1] = green;
- pixels[pos + 2] = blue;
- if n_channels == 4 {
- pixels[pos + 3] = alpha;
- }
- }
-}
-
enum SizeKind {
Zoom,
WidthHeight,
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 9abe74ca..3b833565 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -58,7 +58,7 @@ pub use crate::structure::IntrinsicDimensions;
pub use crate::surface_utils::{
iterators::Pixels,
shared_surface::{SharedImageSurface, SurfaceType},
- Pixel,
+ CairoARGB, Pixel,
};
pub use crate::viewbox::ViewBox;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]