fast image operations
Diffstat (limited to 'src/drawing/circle.rs')
| -rw-r--r-- | src/drawing/circle.rs | 67 |
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) }; + } + } + } + } +} |