[librsvg: 4/12] Define Pixel as an alias for rgb::RGBA8
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 4/12] Define Pixel as an alias for rgb::RGBA8
- Date: Tue, 13 Oct 2020 14:03:23 +0000 (UTC)
commit 5d00cb6a8650c1c4ec0a5285191c3364624064e9
Author: Sven Neumann <sven svenfoo org>
Date: Fri Oct 9 10:19:44 2020 +0200
Define Pixel as an alias for rgb::RGBA8
librsvg/pixbuf_utils.rs | 36 +++--------
librsvg_crate/tests/utils/compare_surfaces.rs | 2 +-
rsvg_internals/benches/pixel_ops.rs | 2 +-
rsvg_internals/src/filters/turbulence.rs | 2 +-
rsvg_internals/src/surface_utils/mod.rs | 74 ++++++++++++----------
rsvg_internals/src/surface_utils/shared_surface.rs | 27 ++------
6 files changed, 57 insertions(+), 86 deletions(-)
---
diff --git a/librsvg/pixbuf_utils.rs b/librsvg/pixbuf_utils.rs
index eb11b5fb..53e1406b 100644
--- a/librsvg/pixbuf_utils.rs
+++ b/librsvg/pixbuf_utils.rs
@@ -4,14 +4,14 @@ use std::ptr;
use gdk_pixbuf::{Colorspace, Pixbuf};
use gio::prelude::*;
use glib::translate::*;
-use rgb::{FromSlice, RGBA8};
+use rgb::FromSlice;
use url::Url;
use crate::c_api::checked_i32;
use rsvg_internals::{
- Dpi, Handle, LoadOptions, LoadingError, Pixel, RenderingError, SharedImageSurface, SurfaceType,
- UrlResolver,
+ surface_utils::PixelOps, Dpi, Handle, LoadOptions, LoadingError, Pixel, RenderingError,
+ SharedImageSurface, SurfaceType, UrlResolver,
};
use crate::c_api::set_gerror;
@@ -42,39 +42,21 @@ pub fn pixbuf_from_surface(surface: &SharedImageSurface) -> Result<Pixbuf, Rende
assert!(pixbuf.get_n_channels() == 4);
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);
// We use chunks_mut(), not chunks_exact_mut(), because gdk-pixbuf tends
// to make the last row *not* have the full stride (i.e. it is
// only as wide as the pixels in that row).
- let pixbuf_rows = pixels.chunks_mut(stride).take(height);
+ let pixbuf_rows = pixels.chunks_mut(stride).take(height as usize);
for (src_row, dest_row) in surface.rows().zip(pixbuf_rows) {
- let row: &mut [RGBA8] = dest_row[..width_in_bytes].as_rgba_mut();
-
+ let row: &mut [Pixel] = dest_row.as_rgba_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)
+ *dest = if src.a == 0 {
+ Pixel::default()
} else {
- let pixel = Pixel {
- r: src.r,
- g: src.g,
- b: src.b,
- a: src.a,
- }
- .unpremultiply();
-
- (pixel.r, pixel.g, pixel.b, pixel.a)
- };
-
- dest.r = r;
- dest.g = g;
- dest.b = b;
- dest.a = a;
+ Pixel::from(*src).unpremultiply()
+ }
}
}
diff --git a/librsvg_crate/tests/utils/compare_surfaces.rs b/librsvg_crate/tests/utils/compare_surfaces.rs
index 0a6e48e2..3b9f2ad9 100644
--- a/librsvg_crate/tests/utils/compare_surfaces.rs
+++ b/librsvg_crate/tests/utils/compare_surfaces.rs
@@ -1,7 +1,7 @@
use self::rsvg_internals::surface_utils::{
iterators::Pixels,
shared_surface::{SharedImageSurface, SurfaceType},
- ImageSurfaceDataExt, Pixel,
+ ImageSurfaceDataExt, Pixel, PixelOps,
};
use self::rsvg_internals::{IRect, RenderingError};
use rsvg_internals;
diff --git a/rsvg_internals/benches/pixel_ops.rs b/rsvg_internals/benches/pixel_ops.rs
index e4cee1e6..58c09ea5 100644
--- a/rsvg_internals/benches/pixel_ops.rs
+++ b/rsvg_internals/benches/pixel_ops.rs
@@ -1,6 +1,6 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
-use rsvg_internals::surface_utils::Pixel;
+use rsvg_internals::surface_utils::{Pixel, PixelOps};
const OTHER: Pixel = Pixel {
r: 0x10,
diff --git a/rsvg_internals/src/filters/turbulence.rs b/rsvg_internals/src/filters/turbulence.rs
index 22caf895..7a76fcdb 100644
--- a/rsvg_internals/src/filters/turbulence.rs
+++ b/rsvg_internals/src/filters/turbulence.rs
@@ -10,7 +10,7 @@ use crate::node::{CascadedValues, Node};
use crate::parsers::{NumberOptionalNumber, Parse, ParseValue};
use crate::surface_utils::{
shared_surface::{ExclusiveImageSurface, SurfaceType},
- ImageSurfaceDataExt, Pixel,
+ ImageSurfaceDataExt, Pixel, PixelOps,
};
use crate::util::clamp;
diff --git a/rsvg_internals/src/surface_utils/mod.rs b/rsvg_internals/src/surface_utils/mod.rs
index 8bbc57d1..5d74eae4 100644
--- a/rsvg_internals/src/surface_utils/mod.rs
+++ b/rsvg_internals/src/surface_utils/mod.rs
@@ -41,15 +41,6 @@ impl<T: Copy> AsCairoARGB<T> for [T] {
}
}
-/// A pixel consisting of R, G, B and A values.
-#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
-pub struct Pixel {
- pub r: u8,
- pub g: u8,
- pub b: u8,
- pub a: u8,
-}
-
/// Modes which specify how the values of out of bounds pixels are computed.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum EdgeMode {
@@ -77,10 +68,22 @@ pub trait ImageSurfaceDataExt: DerefMut<Target = [u8]> {
}
}
-impl Pixel {
+/// A pixel consisting of R, G, B and A values.
+pub type Pixel = rgb::RGBA8;
+
+pub trait PixelOps {
+ fn premultiply(self) -> Self;
+ fn unpremultiply(self) -> Self;
+ fn to_mask(self, opacity: u8) -> Self;
+ fn diff(self, other: &Self) -> Self;
+ fn to_u32(self) -> u32;
+ fn from_u32(x: u32) -> Self;
+}
+
+impl PixelOps for Pixel {
/// Returns an unpremultiplied value of this pixel.
#[inline]
- pub fn unpremultiply(self) -> Self {
+ fn unpremultiply(self) -> Self {
if self.a == 0 {
self
} else {
@@ -98,7 +101,7 @@ impl Pixel {
/// Returns a premultiplied value of this pixel.
#[inline]
- pub fn premultiply(self) -> Self {
+ fn premultiply(self) -> Self {
let alpha = f64::from(self.a) / 255.0;
let premultiply = |x| ((f64::from(x) * alpha) + 0.5) as u8;
@@ -110,26 +113,6 @@ impl Pixel {
}
}
- /// Returns the pixel value as a `u32`, in the same format as `cairo::Format::ARgb32`.
- #[inline]
- pub fn to_u32(self) -> u32 {
- (u32::from(self.a) << 24)
- | (u32::from(self.r) << 16)
- | (u32::from(self.g) << 8)
- | u32::from(self.b)
- }
-
- /// Converts a `u32` in the same format as `cairo::Format::ARgb32` into a `Pixel`.
- #[inline]
- pub fn from_u32(x: u32) -> Self {
- Self {
- r: ((x >> 16) & 0xFF) as u8,
- g: ((x >> 8) & 0xFF) as u8,
- b: (x & 0xFF) as u8,
- a: ((x >> 24) & 0xFF) as u8,
- }
- }
-
/// Returns a 'mask' pixel with only the alpha channel
///
/// Assuming, the pixel is linear RGB (not sRGB)
@@ -145,11 +128,12 @@ impl Pixel {
/// b_mult = 0xFFFFFFFF / (255.0 * 255.0) * .0722 = 4768.88 ~= 4769
///
/// This allows for the following expected behaviour:
- /// (we only care about the most sig byte)
+ /// (we only care about the most significant byte)
/// if pixel = 0x00FFFFFF, pixel' = 0xFF......
/// if pixel = 0x00020202, pixel' = 0x02......
/// if pixel = 0x00000000, pixel' = 0x00......
- pub fn to_mask(self, opacity: u8) -> Self {
+ #[inline]
+ fn to_mask(self, opacity: u8) -> Self {
let r = u32::from(self.r);
let g = u32::from(self.g);
let b = u32::from(self.b);
@@ -164,7 +148,7 @@ impl Pixel {
}
#[inline]
- pub fn diff(self, pixel: &Pixel) -> Pixel {
+ fn diff(self, pixel: &Pixel) -> Pixel {
let a_r = i32::from(self.r);
let a_g = i32::from(self.g);
let a_b = i32::from(self.b);
@@ -182,6 +166,26 @@ impl Pixel {
Pixel { r, g, b, a }
}
+
+ /// Returns the pixel value as a `u32`, in the same format as `cairo::Format::ARgb32`.
+ #[inline]
+ fn to_u32(self) -> u32 {
+ (u32::from(self.a) << 24)
+ | (u32::from(self.r) << 16)
+ | (u32::from(self.g) << 8)
+ | u32::from(self.b)
+ }
+
+ /// Converts a `u32` in the same format as `cairo::Format::ARgb32` into a `Pixel`.
+ #[inline]
+ fn from_u32(x: u32) -> Self {
+ Self {
+ r: ((x >> 16) & 0xFF) as u8,
+ g: ((x >> 8) & 0xFF) as u8,
+ b: (x & 0xFF) as u8,
+ a: ((x >> 24) & 0xFF) as u8,
+ }
+ }
}
impl<'a> ImageSurfaceDataExt for cairo::ImageSurfaceData<'a> {}
diff --git a/rsvg_internals/src/surface_utils/shared_surface.rs
b/rsvg_internals/src/surface_utils/shared_surface.rs
index e954c5ee..6103daba 100644
--- a/rsvg_internals/src/surface_utils/shared_surface.rs
+++ b/rsvg_internals/src/surface_utils/shared_surface.rs
@@ -6,7 +6,7 @@ use std::slice;
use gdk_pixbuf::{Colorspace, Pixbuf};
use nalgebra::{storage::Storage, Dim, Matrix};
-use rgb::{FromSlice, RGB8, RGBA8};
+use rgb::{FromSlice, RGB8};
use crate::rect::{IRect, Rect};
use crate::surface_utils::srgb;
@@ -15,7 +15,7 @@ use crate::util::clamp;
use super::{
iterators::{PixelRectangle, Pixels},
- AsCairoARGB, CairoARGB, EdgeMode, ImageSurfaceDataExt, Pixel,
+ AsCairoARGB, CairoARGB, EdgeMode, ImageSurfaceDataExt, Pixel, PixelOps,
};
/// Types of pixel data in a `ImageSurface`.
@@ -281,32 +281,19 @@ impl ImageSurface<Shared> {
let mut surf = ExclusiveImageSurface::new(width, height, SurfaceType::SRgb)?;
- let width = width as usize;
- let height = height as usize;
-
{
// We use chunks(), not chunks_exact(), because gdk-pixbuf tends
// to make the last row *not* have the full stride (i.e. it is
// only as wide as the pixels in that row).
- let pixbuf_rows = pixbuf_data.chunks(pixbuf_stride).take(height);
-
+ let pixbuf_rows = pixbuf_data.chunks(pixbuf_stride).take(height as usize);
let surf_rows = surf.rows_mut();
if has_alpha {
- let width_in_bytes = width * 4;
-
for (pixbuf_row, surf_row) in pixbuf_rows.zip(surf_rows) {
- let pixbuf_row: &[RGBA8] = pixbuf_row[..width_in_bytes].as_rgba();
+ let pixbuf_row: &[Pixel] = pixbuf_row.as_rgba();
for (src, dest) in pixbuf_row.iter().zip(surf_row.iter_mut()) {
- let pixel = Pixel {
- r: src.r,
- g: src.g,
- b: src.b,
- a: src.a,
- };
-
- let pixel = pixel.premultiply();
+ let pixel = src.premultiply();
dest.r = pixel.r;
dest.g = pixel.g;
dest.b = pixel.b;
@@ -314,10 +301,8 @@ impl ImageSurface<Shared> {
}
}
} else {
- let width_in_bytes = width * 3;
-
for (pixbuf_row, surf_row) in pixbuf_rows.zip(surf_rows) {
- let pixbuf_row: &[RGB8] = pixbuf_row[..width_in_bytes].as_rgb();
+ let pixbuf_row: &[RGB8] = pixbuf_row.as_rgb();
for (src, dest) in pixbuf_row.iter().zip(surf_row.iter_mut()) {
dest.r = src.r;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]