pub struct Pixel {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
Fields§
§r: u8
§g: u8
§b: u8
§a: u8
Implementations§
source§impl Pixel
impl Pixel
sourcepub fn builder() -> PixelBuilder
pub fn builder() -> PixelBuilder
Examples found in repository?
examples/advanced-filters.rs (line 83)
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
fn apply_filter(
canvas: &Canvas,
center: (u32, u32),
kernel: &Vec<f32>,
coords: &Vec<(i32, i32)>,
) -> Pixel {
let scales = kernel
.iter()
.zip(coords.iter())
.fold(Pixel::builder(), |acc, (scale, (x, y))| {
let pixel =
canvas.get_pixel((center.0 as i32 + *x) as u32, (center.1 as i32 + *y) as u32);
acc + PixelBuilder::from(
pixel.r as f32 * scale,
pixel.g as f32 * scale,
pixel.b as f32 * scale,
pixel.a as f32,
)
});
scales.build()
}
sourcepub fn new(red: u8, green: u8, blue: u8, alpha: u8) -> Pixel
pub fn new(red: u8, green: u8, blue: u8, alpha: u8) -> Pixel
Examples found in repository?
More examples
examples/vertical-and-horizontal-chunks.rs (line 7)
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
fn draw_filter(_: &Canvas, _: u32, y: u32) -> Pixel {
let y_level = (y / 10 + 1) as u8;
let pixel = Pixel::new(15 * y_level, 0, 0, 255);
pixel
}
// Slice pictures up and stitch them back together.
fn main() {
let canvas = Canvas::new(100, 100);
// Let's color it.
let canvas = canvas.filter(draw_filter);
let counts = count_colors(&canvas);
assert_eq!(counts.len(), 10);
assert_eq!(counts.get(&Pixel::new(30, 0, 0, 255)), Some(&1000));
assert_eq!(counts.get(&Pixel::new(0, 0, 0, 0)), None);
let chunks = canvas.vertical_chunks(10);
for (i, chunk) in chunks.iter().enumerate() {
let counts = count_colors(&chunk);
assert_eq!(counts.len(), 1, "We are testing chunk {}", i);
assert_eq!(
counts.contains_key(&Pixel::new(((i + 1) * 15) as u8, 0, 0, 255)),
true,
"We are testing chunk {}",
i
);
}
}
examples/advanced-filters.rs (line 66)
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
fn black_or_white_filter(canvas: &Canvas, x: u32, y: u32) -> Pixel {
let pixel = canvas.get_pixel(x, y);
if pixel.r < 128 {
Pixel::new(0, 0, 0, 255)
} else {
Pixel::new(255, 255, 255, 255)
}
}
fn apply_filter(
canvas: &Canvas,
center: (u32, u32),
kernel: &Vec<f32>,
coords: &Vec<(i32, i32)>,
) -> Pixel {
let scales = kernel
.iter()
.zip(coords.iter())
.fold(Pixel::builder(), |acc, (scale, (x, y))| {
let pixel =
canvas.get_pixel((center.0 as i32 + *x) as u32, (center.1 as i32 + *y) as u32);
acc + PixelBuilder::from(
pixel.r as f32 * scale,
pixel.g as f32 * scale,
pixel.b as f32 * scale,
pixel.a as f32,
)
});
scales.build()
}
fn lap_edge_detection_filter(canvas: &Canvas, x: u32, y: u32) -> Pixel {
// NOTE: The kernel (this vector) needs to sum to 1.0. Below 1.0 your image will appear darker
// and above 1.0 it will appear lighter.
let kernel = vec![0.5, 1.0, 0.5, 1.0, -6.0, 1.0, 0.5, 1.0, 0.5];
let coords = vec![
(-1, -1),
(0, -1),
(1, -1),
(-1, 0),
(0, 0),
(1, 0),
(-1, 1),
(0, 1),
(1, 1),
];
// For simplicity, we will leave out the edges of the picture.
let canvas_size = canvas.dimensions();
if x > 0 && y > 0 && x < canvas_size.width - 1 && y < canvas_size.height - 1 {
let pixel = apply_filter(canvas, (x, y), &kernel, &coords);
return pixel;
}
canvas.get_pixel(x, y)
}
fn prewitt_edge_detection_filter(canvas: &Canvas, x: u32, y: u32) -> Pixel {
let kernel_one: Vec<f32> = vec![1f32, 0f32, -1f32, 1f32, 0f32, -1f32, 1f32, 0f32, -1f32];
let kernel_two: Vec<f32> = vec![1f32, 1f32, 1f32, 0f32, 0f32, 0f32, -1f32, -1f32, -1f32];
let coords = vec![
(-1, -1),
(0, -1),
(1, -1),
(-1, 0),
(0, 0),
(1, 0),
(-1, 1),
(0, 1),
(1, 1),
];
let canvas_size = canvas.dimensions();
if x > 0 && y > 0 && x < canvas_size.width - 1 && y < canvas_size.height - 1 {
let pixel_one = apply_filter(canvas, (x, y), &kernel_one, &coords);
let pixel_two = apply_filter(canvas, (x, y), &kernel_two, &coords);
let pixel = PixelBuilder::from(
((pixel_one.r as u32 * pixel_one.r as u32 + pixel_two.r as u32 * pixel_two.r as u32)
as f64)
.sqrt() as f32,
((pixel_one.g as u32 * pixel_one.g as u32 + pixel_two.g as u32 * pixel_two.g as u32)
as f64)
.sqrt() as f32,
((pixel_one.b as u32 * pixel_one.b as u32 + pixel_two.b as u32 * pixel_two.b as u32)
as f64)
.sqrt() as f32,
255f32,
);
return pixel.build();
}
canvas.get_pixel(x, y)
}
fn inverse(pixel: Pixel) -> Pixel {
Pixel {
r: u8::max_value() - pixel.r,
g: u8::max_value() - pixel.g,
b: u8::max_value() - pixel.b,
a: pixel.a,
}
}
fn inverse_filter(canvas: &Canvas, x: u32, y: u32) -> Pixel {
inverse(canvas.get_pixel(x, y))
}
fn main() {
// Gaussian blur
let canvas = Canvas::load(Path::new("assets/lena.png")).unwrap();
let test_image = Canvas::load(Path::new("assets/IMG_0771.JPG")).unwrap();
let gaussian_canvas = canvas.filter(gaussian_filter);
let _ = gaussian_canvas
.save(Path::new("gaussian_canvas.png"))
.unwrap();
let gaussian_canvas = gaussian_canvas.filter(gaussian_filter);
let gaussian_canvas = gaussian_canvas.filter(gaussian_filter);
let gaussian_canvas = gaussian_canvas.filter(gaussian_filter);
let gaussian_canvas = gaussian_canvas.filter(gaussian_filter);
let _ = gaussian_canvas
.save(Path::new("very_gaussian_canvas.png"))
.unwrap();
// Chaining filters
let inverse_gaussian_canvas = canvas.filter(inverse_filter).filter(gaussian_filter);
let _ = inverse_gaussian_canvas
.save(Path::new("inverse_gaussian_canvas.png"))
.unwrap();
let lap_edge_detection_canvas = canvas.filter(lap_edge_detection_filter);
let _ = lap_edge_detection_canvas
.save(Path::new("lap_edge_detection_filter.png"))
.unwrap();
let prewitt_edge_detection_canvas = canvas.filter(prewitt_edge_detection_filter);
let _ = prewitt_edge_detection_canvas
.save(Path::new("prewitt_edge_detection_filter.png"))
.unwrap();
let lap_of_gaussian_filter_canvas = test_image.filter(grey_scale_filter).filter(lap_of_gaussian_filter);
//let counted_colors = count_colors(&lap_of_gaussian_filter_canvas);
//println!("{}", counted_colors_to_html(&counted_colors));
let _ = lap_of_gaussian_filter_canvas
.save(Path::new("lap_of_gaussian_edge_detection_filter.png"))
.unwrap();
let filtered_canvas = lap_of_gaussian_filter_canvas.filter(black_or_white_filter);
let _ = filtered_canvas
.save(Path::new("filtered_canvas.png"))
.unwrap();
let islands = filtered_canvas.find_islands(&Pixel::new(255, 255, 255, 255));
let islands_with_size: Vec<Island> = islands.iter().filter(|x| x.points.len() > 40000).map(|x| x.clone()).collect();
// TODO: Now we have the outline of the islands.
// Copy the islands a blank canvas.
// Fill from the outside
// Now you have the entire form of all the islands
// Transfer the pixels that were not filled from the outside
//
//
// TODO: NEW IDEA AS WELL: Create a 'fattener'. Paints a 2x2, 3x3, 4x4, ... etc around each
// pixel. This way you can expand outwards
}
examples/filling.rs (line 14)
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
fn main() {
let color = Pixel {
r: 0,
g: 0,
b: 255,
a: 255,
};
let new_color = Pixel::new(255, 0, 0, 255);
let canvas = Canvas::new_with_background(100, 100, color.clone())
.draw_square(10, 10, 80, 80, &new_color)
.draw_square(20, 20, 60, 60, &color)
.fill(1, 1, &Pixel::new(172, 172, 172, 255));
canvas.save(Path::new("testing.png")).unwrap();
let canvas = Canvas::load(Path::new("assets/20230709_111142.jpg")).unwrap().rotate90();
println!("Size of canvas: {} x {}", canvas.dimensions().width, canvas.dimensions().height);
/*let subcanvas = canvas.get_subimage(1600, 50, 1400, 400);
let (center, distance) = utility::find_center_and_size(&subcanvas);
println!("center and distance = {center} and {distance}");
let canvas = canvas.fill_by_color_and_distance(1600, 50, &Pixel::new(0,0,0,0), ¢er, 100.0);
println!("Size of canvas: {} x {}", canvas.dimensions().width, canvas.dimensions().height);
canvas.save(Path::new("testing-fill-by-center-and-distance.png")).unwrap();*/
/*for i in (30..90).step_by(1) {
let current_canvas = canvas.clone();
let name = format!("output_liv/distance_{i}.png");
let current = current_canvas.fill_by_distance(1500, 20, &Pixel::new(0,0,0,0), i as f32);
current.save(Path::new(&name)).unwrap();
println!("Number {i} done");
}*/
}
pub fn from(red: f32, green: f32, blue: f32, alpha: f32) -> Pixel
pub fn denormalize(red: f32, green: f32, blue: f32, alpha: f32) -> Pixel
pub fn random() -> Pixel
pub fn is_zero(&self) -> bool
pub fn multiply(&self, x: f32, y: f32, z: f32) -> Pixel
pub fn scale(&self, s: f32) -> Pixel
pub fn diff(&self, other: &Pixel) -> Pixel
pub fn normalize(&self) -> (f32, f32, f32, f32)
pub fn set_red(self, red: u8) -> Pixel
pub fn set_green(self, green: u8) -> Pixel
pub fn set_blue(self, blue: u8) -> Pixel
pub fn set_alpha(self, alpha: u8) -> Pixel
pub fn set_red_mut(&mut self, red: u8)
pub fn set_green_mut(&mut self, green: u8)
pub fn set_blue_mut(&mut self, blue: u8)
pub fn set_alpha_mut(&mut self, alpha: u8)
Trait Implementations§
source§impl Add<Pixel> for Pixel
impl Add<Pixel> for Pixel
§type Output = PixelBuilder
type Output = PixelBuilder
The resulting type after applying the
+
operator.source§impl Add<Pixel> for PixelBuilder
impl Add<Pixel> for PixelBuilder
§type Output = PixelBuilder
type Output = PixelBuilder
The resulting type after applying the
+
operator.source§impl Add<PixelBuilder> for Pixel
impl Add<PixelBuilder> for Pixel
§type Output = PixelBuilder
type Output = PixelBuilder
The resulting type after applying the
+
operator.source§fn add(self, other: PixelBuilder) -> PixelBuilder
fn add(self, other: PixelBuilder) -> PixelBuilder
Performs the
+
operation. Read moresource§impl Div<f32> for Pixel
impl Div<f32> for Pixel
§type Output = PixelBuilder
type Output = PixelBuilder
The resulting type after applying the
/
operator.source§impl Mul<f32> for Pixel
impl Mul<f32> for Pixel
§type Output = PixelBuilder
type Output = PixelBuilder
The resulting type after applying the
*
operator.source§impl PartialEq<Pixel> for Pixel
impl PartialEq<Pixel> for Pixel
impl Eq for Pixel
Auto Trait Implementations§
impl RefUnwindSafe for Pixel
impl Send for Pixel
impl Sync for Pixel
impl Unpin for Pixel
impl UnwindSafe for Pixel
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more