fast image operations
Diffstat (limited to 'src/drawing/circle.rs')
-rw-r--r--src/drawing/circle.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/drawing/circle.rs b/src/drawing/circle.rs
new file mode 100644
index 0000000..793dd92
--- /dev/null
+++ b/src/drawing/circle.rs
@@ -0,0 +1,67 @@
+//! draw 2d circles
+use crate::Image;
+use std::ops::DerefMut;
+
+impl<T: DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
+ /// Draws a circle, using the [Bresenham's circle](https://en.wikipedia.org/wiki/Midpoint_circle_algorithm) algorithm.
+ /// ```
+ /// # use fimg::Image;
+ /// let mut i = Image::alloc(50, 50);
+ /// i.border_circle((25, 25), 20, [255]);
+ /// # assert_eq!(i.buffer(), include_bytes!("../../tdata/circle.imgbuf"));
+ /// ```
+ pub fn border_circle(&mut self, (xc, yc): (i32, i32), radius: i32, c: [u8; CHANNELS]) {
+ let mut x = 0;
+ let mut y = radius;
+ let mut p = 1 - radius;
+ /// bounds the pixels
+ macro_rules! bound {
+ ($($x:expr,$y:expr);+;) => {
+ $(if $x >= 0 && $x < self.width() as i32 && $y >= 0 && $y < self.height() as i32 {
+ // SAFETY: ^
+ unsafe { self.set_pixel($x as u32, $y as u32, c) };
+ })+
+ };
+ }
+ while x <= y {
+ bound! {
+ xc + x, yc + y;
+ xc + y, yc + x;
+ xc - y, yc + x;
+ xc - x, yc + y;
+ xc - x, yc - y;
+ xc - y, yc - x;
+ xc + y, yc - x;
+ xc + x, yc - y;
+ };
+ x += 1;
+ if p < 0 {
+ p += 2 * x + 1;
+ } else {
+ y -= 1;
+ p += 2 * (x - y) + 1;
+ }
+ }
+ }
+
+ /// Draw a filled circle.
+ /// ```
+ /// # use fimg::Image;
+ /// let mut i = Image::alloc(50, 50);
+ /// i.circle((25, 25), 20, [255]);
+ /// # assert_eq!(i.buffer(), include_bytes!("../../tdata/circle2.imgbuf"));
+ /// ```
+ pub fn circle(&mut self, (xc, yc): (i32, i32), radius: i32, c: [u8; CHANNELS]) {
+ for x in -radius..radius {
+ let h = ((radius * radius - x * x) as f32).sqrt().round() as i32;
+ for y in -h..h {
+ let x = x + xc;
+ let y = y + yc;
+ if x >= 0 && x < self.width() as i32 && y >= 0 && y < self.height() as i32 {
+ // SAFETY: ^
+ unsafe { self.set_pixel(x as u32, y as u32, c) };
+ }
+ }
+ }
+ }
+}