[librsvg: 5/9] 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: 5/9] Reimplement pixbuf_from_surface() in terms of iterators and .as_pixels()
- Date: Fri, 29 May 2020 21:16:13 +0000 (UTC)
commit 950c45c352ba7efb2e511486dd23cf41412cfa7a
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 | 7 ++---
librsvg/Cargo.toml | 1 +
librsvg/pixbuf_utils.rs | 66 +++++++++++++++++++----------------------------
rsvg_internals/src/lib.rs | 2 +-
4 files changed, 32 insertions(+), 44 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 9eee9350..c549c804 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -202,7 +202,7 @@ dependencies = [
[[package]]
name = "crossbeam-queue"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -704,6 +704,7 @@ dependencies = [
"glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rgb 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
"rsvg_internals 0.0.1",
"url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1258,7 +1259,7 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-queue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1767,7 +1768,7 @@ dependencies = [
"checksum criterion-plot 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" =
"ddeaf7989f00f2e1d871a26a110f3ed713632feac17f65f03ca938c542618b60"
"checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" =
"9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" =
"058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
-"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" =
"c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
+"checksum crossbeam-queue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" =
"ab6bffe714b6bb07e42f201352c34f51fefd355ace793f9e638ebd52d23f98d2"
"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" =
"c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
"checksum cssparser 0.27.2 (registry+https://github.com/rust-lang/crates.io-index)" =
"754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a"
"checksum cssparser-macros 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" =
"dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e"
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 0c5f2784..84aa67fd 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -66,7 +66,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]