diff --git a/src/buffer.rs b/src/buffer.rs index b1a8d308e9..64762779c2 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -86,24 +86,12 @@ pub trait Pixel: Copy + Clone { /// that the slice is long enough to present panics if the pixel is used later on. fn from_slice_mut(slice: &mut [Self::Subpixel]) -> &mut Self; - /// Convert this pixel to RGB - fn to_rgb(&self) -> Rgb; - /// Convert this pixel to RGB with an alpha channel fn to_rgba(&self) -> Rgba; - /// Convert this pixel to luma - fn to_luma(&self) -> Luma; - /// Convert this pixel to luma with an alpha channel fn to_luma_alpha(&self) -> LumaA; - /// Convert this pixel to BGR - fn to_bgr(&self) -> Bgr; - - /// Convert this pixel to BGR with an alpha channel - fn to_bgra(&self) -> Bgra; - /// Apply the function ```f``` to each channel of this pixel. fn map(&self, f: F) -> Self where @@ -159,9 +147,6 @@ pub trait Pixel: Copy + Clone { where F: FnMut(Self::Subpixel, Self::Subpixel) -> Self::Subpixel; - /// Invert this pixel - fn invert(&mut self); - /// Blend the color of a given pixel into ourself, taking into account alpha channels fn blend(&mut self, other: &Self); } diff --git a/src/color.rs b/src/color.rs index d1e678a6a1..7f57bdef53 100644 --- a/src/color.rs +++ b/src/color.rs @@ -214,36 +214,12 @@ impl Pixel for $ident { unsafe { &mut *(slice.as_ptr() as *mut $ident) } } - fn to_rgb(&self) -> Rgb { - let mut pix = Rgb([Zero::zero(), Zero::zero(), Zero::zero()]); - pix.from_color(self); - pix - } - - fn to_bgr(&self) -> Bgr { - let mut pix = Bgr([Zero::zero(), Zero::zero(), Zero::zero()]); - pix.from_color(self); - pix - } - fn to_rgba(&self) -> Rgba { let mut pix = Rgba([Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]); pix.from_color(self); pix } - fn to_bgra(&self) -> Bgra { - let mut pix = Bgra([Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]); - pix.from_color(self); - pix - } - - fn to_luma(&self) -> Luma { - let mut pix = Luma([Zero::zero()]); - pix.from_color(self); - pix - } - fn to_luma_alpha(&self) -> LumaA { let mut pix = LumaA([Zero::zero(), Zero::zero()]); pix.from_color(self); @@ -292,10 +268,6 @@ impl Pixel for $ident { } } - fn invert(&mut self) { - Invert::invert(self) - } - fn blend(&mut self, other: &$ident) { Blend::blend(self, other) } @@ -1016,83 +988,6 @@ impl Blend for Bgr { } } - -/// Invert a color -pub(crate) trait Invert { - /// Inverts a color in-place. - fn invert(&mut self); -} - -impl Invert for LumaA { - fn invert(&mut self) { - let l = self.0; - let max = T::max_value(); - - *self = LumaA([max - l[0], l[1]]) - } -} - -impl Invert for Luma { - fn invert(&mut self) { - let l = self.0; - - let max = T::max_value(); - let l1 = max - l[0]; - - *self = Luma([l1]) - } -} - -impl Invert for Rgba { - fn invert(&mut self) { - let rgba = self.0; - - let max = T::max_value(); - - *self = Rgba([max - rgba[0], max - rgba[1], max - rgba[2], rgba[3]]) - } -} - - -impl Invert for Bgra { - fn invert(&mut self) { - let bgra = self.0; - - let max = T::max_value(); - - *self = Bgra([max - bgra[2], max - bgra[1], max - bgra[0], bgra[3]]) - } -} - - -impl Invert for Rgb { - fn invert(&mut self) { - let rgb = self.0; - - let max = T::max_value(); - - let r1 = max - rgb[0]; - let g1 = max - rgb[1]; - let b1 = max - rgb[2]; - - *self = Rgb([r1, g1, b1]) - } -} - -impl Invert for Bgr { - fn invert(&mut self) { - let bgr = self.0; - - let max = T::max_value(); - - let r1 = max - bgr[2]; - let g1 = max - bgr[1]; - let b1 = max - bgr[0]; - - *self = Bgr([b1, g1, r1]) - } -} - #[cfg(test)] mod tests { use super::{Luma, LumaA, Pixel, Rgb, Rgba, Bgr, Bgra}; diff --git a/src/dynimage.rs b/src/dynimage.rs index 60badd5922..c9f08faf8f 100644 --- a/src/dynimage.rs +++ b/src/dynimage.rs @@ -457,7 +457,12 @@ impl DynamicImage { /// Invert the colors of this image. /// This method operates inplace. pub fn invert(&mut self) { - dynamic_map!(*self, ref mut p -> imageops::invert(p)) + use traits::Primitive; + fn invert_pixel(p: &mut impl Pixel) { + p.apply_with_alpha(|c|T::max_value() - c, |a|a); + } + + dynamic_map!(*self, ref mut img -> img.pixels_mut().for_each(invert_pixel)) } /// Resize this image using the specified filter algorithm. @@ -747,32 +752,54 @@ impl GenericImage for DynamicImage { type InnerImage = DynamicImage; fn put_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba) { + let color::Rgba([r, g, b, a]) = pixel; + let (r16, g16, b16, a16) = (r as u16 * 257, b as u16 * 257, g as u16 * 257, a as u16 * 257); match *self { - DynamicImage::ImageLuma8(ref mut p) => p.put_pixel(x, y, pixel.to_luma()), + DynamicImage::ImageLuma8(ref mut p) => { + let color::LumaA([l, _]) = pixel.to_luma_alpha(); + p.put_pixel(x, y, color::Luma([l])) + } DynamicImage::ImageLumaA8(ref mut p) => p.put_pixel(x, y, pixel.to_luma_alpha()), - DynamicImage::ImageRgb8(ref mut p) => p.put_pixel(x, y, pixel.to_rgb()), + DynamicImage::ImageRgb8(ref mut p) => p.put_pixel(x, y, color::Rgb([r, g, b])), DynamicImage::ImageRgba8(ref mut p) => p.put_pixel(x, y, pixel), - DynamicImage::ImageBgr8(ref mut p) => p.put_pixel(x, y, pixel.to_bgr()), - DynamicImage::ImageBgra8(ref mut p) => p.put_pixel(x, y, pixel.to_bgra()), - DynamicImage::ImageLuma16(ref mut p) => p.put_pixel(x, y, pixel.to_luma().into_color()), - DynamicImage::ImageLumaA16(ref mut p) => p.put_pixel(x, y, pixel.to_luma_alpha().into_color()), - DynamicImage::ImageRgb16(ref mut p) => p.put_pixel(x, y, pixel.to_rgb().into_color()), - DynamicImage::ImageRgba16(ref mut p) => p.put_pixel(x, y, pixel.into_color()), + DynamicImage::ImageBgr8(ref mut p) => p.put_pixel(x, y, color::Bgr([b, g, r])), + DynamicImage::ImageBgra8(ref mut p) => p.put_pixel(x, y, color::Bgra([b, g, r, a])), + DynamicImage::ImageLuma16(ref mut p) =>{ + let color::LumaA([l, _]) = color::Rgb([r16, g16, b16]).to_luma_alpha(); + p.put_pixel(x, y, color::Luma([l])) + } + DynamicImage::ImageLumaA16(ref mut p) => + p.put_pixel(x, y, color::Rgba([r16, g16, b16, a16]).to_luma_alpha()), + DynamicImage::ImageRgb16(ref mut p) => + p.put_pixel(x, y, color::Rgb([r16, g16, b16])), + DynamicImage::ImageRgba16(ref mut p) => + p.put_pixel(x, y, color::Rgba([r16, g16, b16, a16])), } } /// DEPRECATED: Use iterator `pixels_mut` to blend the pixels directly. fn blend_pixel(&mut self, x: u32, y: u32, pixel: color::Rgba) { + let color::Rgba([r, g, b, a]) = pixel; + let (r16, g16, b16, a16) = (r as u16 * 257, b as u16 * 257, g as u16 * 257, a as u16 * 257); match *self { - DynamicImage::ImageLuma8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma()), + DynamicImage::ImageLuma8(ref mut p) => { + let color::LumaA([l, _]) = pixel.to_luma_alpha(); + p.blend_pixel(x, y, color::Luma([l])) + } DynamicImage::ImageLumaA8(ref mut p) => p.blend_pixel(x, y, pixel.to_luma_alpha()), - DynamicImage::ImageRgb8(ref mut p) => p.blend_pixel(x, y, pixel.to_rgb()), + DynamicImage::ImageRgb8(ref mut p) => p.blend_pixel(x, y, color::Rgb([r, g, b])), DynamicImage::ImageRgba8(ref mut p) => p.blend_pixel(x, y, pixel), - DynamicImage::ImageBgr8(ref mut p) => p.blend_pixel(x, y, pixel.to_bgr()), - DynamicImage::ImageBgra8(ref mut p) => p.blend_pixel(x, y, pixel.to_bgra()), - DynamicImage::ImageLuma16(ref mut p) => p.blend_pixel(x, y, pixel.to_luma().into_color()), - DynamicImage::ImageLumaA16(ref mut p) => p.blend_pixel(x, y, pixel.to_luma_alpha().into_color()), - DynamicImage::ImageRgb16(ref mut p) => p.blend_pixel(x, y, pixel.to_rgb().into_color()), - DynamicImage::ImageRgba16(ref mut p) => p.blend_pixel(x, y, pixel.into_color()), + DynamicImage::ImageBgr8(ref mut p) => p.blend_pixel(x, y, color::Bgr([b, g, r])), + DynamicImage::ImageBgra8(ref mut p) => p.blend_pixel(x, y, color::Bgra([b, g, r, a])), + DynamicImage::ImageRgb16(ref mut p) => + p.blend_pixel(x, y, color::Rgb([r16, g16, b16])), + DynamicImage::ImageRgba16(ref mut p) => + p.blend_pixel(x, y, color::Rgba([r16, g16, b16, a16])), + DynamicImage::ImageLuma16(ref mut p) =>{ + let color::LumaA([l, _]) = color::Rgb([r16, g16, b16]).to_luma_alpha(); + p.blend_pixel(x, y, color::Luma([l])) + } + DynamicImage::ImageLumaA16(ref mut p) => + p.blend_pixel(x, y, color::Rgba([r16, g16, b16, a16]).to_luma_alpha()), } } diff --git a/src/imageops/colorops.rs b/src/imageops/colorops.rs index 053b8271b2..3245e10dbb 100644 --- a/src/imageops/colorops.rs +++ b/src/imageops/colorops.rs @@ -1,8 +1,8 @@ //! Functions for altering and converting the color of pixelbufs use buffer::{ImageBuffer, Pixel}; -use color::{Luma, Rgba}; -use image::{GenericImage, GenericImageView}; +use color::{Luma, LumaA, Rgba}; +use image::GenericImageView; use math::nq; use math::utils::clamp; use num_traits::{Num, NumCast}; @@ -24,29 +24,14 @@ where for y in 0..height { for x in 0..width { - let p = image.get_pixel(x, y).to_luma(); - out.put_pixel(x, y, p); + let LumaA([l, _]) = image.get_pixel(x, y).to_luma_alpha(); + out.put_pixel(x, y, Luma([l])); } } out } -/// Invert each pixel within the supplied image. -/// This function operates in place. -pub fn invert(image: &mut I) { - let (width, height) = image.dimensions(); - - for y in 0..height { - for x in 0..width { - let mut p = image.get_pixel(x, y); - p.invert(); - - image.put_pixel(x, y, p); - } - } -} - /// Adjust the contrast of the supplied image. /// ```contrast``` is the amount to adjust the contrast by. /// Negative values decrease the contrast and positive values increase the contrast. diff --git a/src/imageops/mod.rs b/src/imageops/mod.rs index 83c1de5d4a..246c7c78fa 100644 --- a/src/imageops/mod.rs +++ b/src/imageops/mod.rs @@ -16,7 +16,7 @@ pub use self::affine::{flip_horizontal, flip_vertical, rotate180, rotate270, rot pub use self::sample::{blur, filter3x3, resize, thumbnail, unsharpen}; /// Color operations -pub use self::colorops::{brighten, contrast, dither, grayscale, huerotate, index_colors, invert, +pub use self::colorops::{brighten, contrast, dither, grayscale, huerotate, index_colors, BiLevel, ColorMap}; mod affine;