mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-11 07:02:41 +00:00
feat(core): implement rgba8888 canvas blur
[no changelog]
This commit is contained in:
parent
76e73f684a
commit
db546d8bf8
@ -135,7 +135,31 @@ impl<'a> Canvas for Rgba8888Canvas<'a> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_blurring")]
|
||||
fn blur_rect(&mut self, _r: Rect, _radius: usize, _cache: &DrawingCache) {
|
||||
// TODO
|
||||
fn blur_rect(&mut self, r: Rect, radius: usize, cache: &DrawingCache) {
|
||||
let clip = r.translate(self.viewport.origin).clamp(self.viewport.clip);
|
||||
|
||||
let ofs = radius as i16;
|
||||
|
||||
if clip.width() > 2 * ofs - 1 && clip.height() > 2 * ofs - 1 {
|
||||
let mut blur_cache = cache.blur();
|
||||
let (blur, _) = unwrap!(
|
||||
blur_cache.get(clip.size(), radius, None),
|
||||
"Too small blur buffer"
|
||||
);
|
||||
|
||||
loop {
|
||||
if let Some(y) = blur.push_ready() {
|
||||
let row = unwrap!(self.row_mut(y + clip.y0)); // can't panic
|
||||
blur.push(&row[clip.x0 as usize..clip.x1 as usize]);
|
||||
}
|
||||
if let Some(y) = blur.pop_ready() {
|
||||
let row = unwrap!(self.row_mut(y + clip.y0)); // can't panic
|
||||
blur.pop(&mut row[clip.x0 as usize..clip.x1 as usize], None);
|
||||
if y + 1 >= clip.height() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -197,14 +197,14 @@ impl<'a> Shape<'a> for JpegImage<'a> {
|
||||
if let Some(y) = blur.push_ready() {
|
||||
if y < row_r.y1 {
|
||||
// should never fail
|
||||
blur.push(unwrap!(jpeg_slice.row(y - row_r.y0)));
|
||||
blur.push(unwrap!(jpeg_slice.row::<u16>(y - row_r.y0)));
|
||||
} else {
|
||||
return true; // need more data
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(y) = blur.pop_ready() {
|
||||
blur.pop(unwrap!(slice.row_mut(0)), Some(self.dim)); // should never fail
|
||||
blur.pop(unwrap!(slice.row_mut::<u16>(0)), Some(self.dim)); // should never fail
|
||||
let dst_r = Rect::from_top_left_and_size(bounds.top_left(), jpeg_size)
|
||||
.translate(Offset::new(0, y));
|
||||
canvas.draw_bitmap(dst_r, slice.view());
|
||||
|
@ -46,10 +46,8 @@ const MAX_WIDTH: usize = display::DISPLAY_RESX as usize;
|
||||
|
||||
pub type BlurBuff = [u8; MAX_WIDTH * (MAX_SIDE * 3 + size_of::<u16>() * 3) + 8];
|
||||
|
||||
type PixelColor = u16;
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
struct Rgb<T> {
|
||||
pub struct Rgb<T> {
|
||||
pub r: T,
|
||||
pub g: T,
|
||||
pub b: T,
|
||||
@ -77,6 +75,17 @@ impl From<u16> for Rgb<u16> {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Rgb<u16> {
|
||||
#[inline(always)]
|
||||
fn from(value: u32) -> Self {
|
||||
Self {
|
||||
r: ((value >> 16) & 0xFF) as u16,
|
||||
g: ((value >> 8) & 0xFF) as u16,
|
||||
b: (value & 0xFF) as u16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::AddAssign<u16> for Rgb<u16> {
|
||||
#[inline(always)]
|
||||
fn add_assign(&mut self, rhs: u16) {
|
||||
@ -85,6 +94,14 @@ impl core::ops::AddAssign<u16> for Rgb<u16> {
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::AddAssign<u32> for Rgb<u16> {
|
||||
#[inline(always)]
|
||||
fn add_assign(&mut self, rhs: u32) {
|
||||
let rgb: Self = rhs.into();
|
||||
*self += rgb;
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::SubAssign<u16> for Rgb<u16> {
|
||||
#[inline(always)]
|
||||
fn sub_assign(&mut self, rhs: u16) {
|
||||
@ -93,6 +110,14 @@ impl core::ops::SubAssign<u16> for Rgb<u16> {
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::SubAssign<u32> for Rgb<u16> {
|
||||
#[inline(always)]
|
||||
fn sub_assign(&mut self, rhs: u32) {
|
||||
let rgb: Self = rhs.into();
|
||||
*self -= rgb;
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::AddAssign for Rgb<u16> {
|
||||
#[inline(always)]
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
@ -121,6 +146,17 @@ impl From<Rgb<u8>> for u16 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rgb<u8>> for u32 {
|
||||
#[inline(always)]
|
||||
fn from(value: Rgb<u8>) -> u32 {
|
||||
let r = (value.r as u32) << 16;
|
||||
let g = (value.g as u32) << 8;
|
||||
let b = value.b as u32;
|
||||
let alpha = 0xFF000000;
|
||||
alpha | r | g | b
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rgb<u16>> for Rgb<u8> {
|
||||
#[inline(always)]
|
||||
fn from(value: Rgb<u16>) -> Self {
|
||||
@ -209,7 +245,10 @@ impl<'a> BlurAlgorithm<'a> {
|
||||
/// as the floating average of n subsequent elements where n = 2 * radius +
|
||||
/// 1. Finally, it stores it into the specifed row in the sliding
|
||||
/// window.
|
||||
fn average_to_row(&mut self, inp: &[PixelColor], row: usize) {
|
||||
fn average_to_row<T>(&mut self, inp: &[T], row: usize)
|
||||
where
|
||||
T: Copy + Into<Rgb<u16>>,
|
||||
{
|
||||
let radius = self.radius;
|
||||
let offset = self.size.x as usize * row;
|
||||
let row = &mut self.window[offset..offset + self.size.x as usize];
|
||||
@ -222,29 +261,29 @@ impl<'a> BlurAlgorithm<'a> {
|
||||
|
||||
// Prepare before averaging
|
||||
for i in 0..radius {
|
||||
sum += inp[0]; // Duplicate pixels on the left
|
||||
sum += inp[i]; // Add first radius pixels
|
||||
sum += inp[0].into(); // Duplicate pixels on the left
|
||||
sum += inp[i].into(); // Add first radius pixels
|
||||
}
|
||||
|
||||
// Process the first few pixels of the row
|
||||
for i in 0..radius {
|
||||
sum += inp[i + radius];
|
||||
sum += inp[i + radius].into();
|
||||
row[i] = sum.mulshift(multiplier, shift);
|
||||
sum -= inp[0];
|
||||
sum -= inp[0].into();
|
||||
}
|
||||
|
||||
// Process the inner part of the row
|
||||
for i in radius..row.len() - radius {
|
||||
sum += inp[i + radius];
|
||||
sum += inp[i + radius].into();
|
||||
row[i] = sum.mulshift(multiplier, shift);
|
||||
sum -= inp[i - radius];
|
||||
sum -= inp[i - radius].into();
|
||||
}
|
||||
|
||||
// Process the last few pixels of the row
|
||||
for i in (row.len() - radius)..row.len() {
|
||||
sum += inp[inp.len() - 1];
|
||||
sum += inp[inp.len() - 1].into();
|
||||
row[i] = sum.mulshift(multiplier, shift);
|
||||
sum -= inp[i - radius]; // Duplicate pixels on the right
|
||||
sum -= inp[i - radius].into(); // Duplicate pixels on the right
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,7 +344,10 @@ impl<'a> BlurAlgorithm<'a> {
|
||||
}
|
||||
|
||||
/// Takes the source row and pushes it into the sliding window.
|
||||
pub fn push(&mut self, input: &[PixelColor]) {
|
||||
pub fn push<T>(&mut self, input: &[T])
|
||||
where
|
||||
T: Copy + Into<Rgb<u16>>,
|
||||
{
|
||||
let row = self.row;
|
||||
|
||||
self.subtract_row(row);
|
||||
@ -331,7 +373,10 @@ impl<'a> BlurAlgorithm<'a> {
|
||||
}
|
||||
|
||||
/// Copies the current content of `totals[]` to the output buffer.
|
||||
pub fn pop(&mut self, output: &mut [PixelColor], dim: Option<u8>) {
|
||||
pub fn pop<T>(&mut self, output: &mut [T], dim: Option<u8>)
|
||||
where
|
||||
T: Copy + Into<Rgb<u16>> + From<Rgb<u8>>,
|
||||
{
|
||||
let divisor = match dim {
|
||||
Some(dim) => {
|
||||
if dim > 0 {
|
||||
|
Loading…
Reference in New Issue
Block a user