graphics: ssd1306: reimplement dithering using an ordered dither map
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
#![cfg(feature="oled")]
|
#![cfg(feature="oled")]
|
||||||
use core::cmp::min;
|
use core::{cmp::min, ops::{BitAnd, Shr}};
|
||||||
|
|
||||||
use display_interface::DisplayError;
|
use display_interface::DisplayError;
|
||||||
use embedded_graphics::prelude::*;
|
use embedded_graphics::prelude::*;
|
||||||
use esp_hal::{gpio::Output, i2c::master::I2c, Async};
|
use esp_hal::{gpio::Output, i2c::master::I2c, Async};
|
||||||
use figments::{liber8tion::{interpolate::Fract8, noise}, mappings::embedded_graphics::Matrix2DSpace, prelude::*};
|
use figments::{liber8tion::{interpolate::Fract8, noise}, mappings::embedded_graphics::Matrix2DSpace, prelude::*};
|
||||||
use embedded_graphics::pixelcolor::BinaryColor;
|
use embedded_graphics::pixelcolor::BinaryColor;
|
||||||
use figments::pixels::PixelSink;
|
use figments::pixels::AdditivePixelSink;
|
||||||
use figments_render::output::OutputAsync;
|
use figments_render::output::OutputAsync;
|
||||||
use ssd1306::{prelude::DisplayRotation, size::DisplaySize128x64, I2CDisplayInterface, Ssd1306Async};
|
use ssd1306::{prelude::DisplayRotation, size::DisplaySize128x64, I2CDisplayInterface, Ssd1306Async};
|
||||||
use embassy_time::Delay;
|
use embassy_time::Delay;
|
||||||
@@ -38,29 +38,38 @@ impl SsdPixel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PixelSink<BinaryColor> for SsdPixel {
|
const DITHER_MAP: [u32;15] = [
|
||||||
fn set(&mut self, pixel: &BinaryColor) {
|
0b1000_0000_0000_0000,
|
||||||
self.set_pixel(*pixel);
|
0b1000_0000_0010_0000,
|
||||||
}
|
0b1010_0000_0010_0000,
|
||||||
}
|
0b1010_0000_1010_0000,
|
||||||
|
0b1010_0100_1010_0000,
|
||||||
|
0b1010_0100_1010_0001,
|
||||||
|
0b1010_0101_1010_0001,
|
||||||
|
0b1010_0101_1010_0101,
|
||||||
|
0b1110_0101_1010_0101,
|
||||||
|
0b1110_0101_1011_0101,
|
||||||
|
0b1111_0101_1011_0101,
|
||||||
|
0b1111_0101_1111_0101,
|
||||||
|
0b1111_1101_1111_0101,
|
||||||
|
0b1111_1101_1111_0111,
|
||||||
|
0b1111_1111_1111_0111,
|
||||||
|
];
|
||||||
|
|
||||||
impl PixelBlend<BinaryColor> for SsdPixel {
|
impl AdditivePixelSink<BinaryColor> for SsdPixel {
|
||||||
fn blend_pixel(self, overlay: BinaryColor, opacity: Fract8) -> Self {
|
fn add(&mut self, pixel: BinaryColor, opacity: Fract8) {
|
||||||
let scale = 48;
|
match opacity {
|
||||||
let x = self.coords.x * scale;
|
0 => (),
|
||||||
let y = self.coords.y * scale;
|
255 => self.set_pixel(pixel),
|
||||||
let stiple_idx = noise::inoise8(x as i16, y as i16);
|
_ => {
|
||||||
if opacity >= stiple_idx {
|
let dither_value = DITHER_MAP[opacity as usize / 16];
|
||||||
self.set_pixel(overlay);
|
let dither_x = self.coords.x % 4;
|
||||||
|
let dither_y = self.coords.x % 4;
|
||||||
|
if dither_value.shr(dither_x).shr(dither_y * 4).bitand(0x01) == 1 {
|
||||||
|
self.set_pixel(pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn multiply(self, overlay: BinaryColor) -> Self {
|
|
||||||
if overlay != self.get_pixel() {
|
|
||||||
self.set_pixel(overlay);
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,9 +204,9 @@ impl DrawTarget for SsdOutput {
|
|||||||
|
|
||||||
fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
|
fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
|
||||||
if color.is_on() {
|
if color.is_on() {
|
||||||
self.pixbuf.fill(255);
|
self.pixbuf.fill_with(|| { 255 });
|
||||||
} else {
|
} else {
|
||||||
self.pixbuf.fill(0);
|
self.pixbuf.fill_with(|| { 0 });
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user