Skip to main content

magick_rust/wand/
pixel.rs

1/*
2 * Copyright 2016 Mattis Marjak
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16use std::ffi::{CStr, CString};
17use std::fmt;
18
19use crate::bindings;
20use crate::result::MagickError;
21
22use super::MagickTrue;
23use crate::result::Result;
24
25/// A color expressed in the hue, saturation, and lightness color space.
26#[derive(Default, Debug)]
27pub struct HSL {
28    /// Hue component.
29    pub hue: f64,
30    /// Saturation component.
31    pub saturation: f64,
32    /// Lightness component.
33    pub lightness: f64,
34}
35
36wand_common!(
37    PixelWand,
38    NewPixelWand,
39    ClearPixelWand,
40    IsPixelWand,
41    ClonePixelWand,
42    DestroyPixelWand,
43    PixelClearException,
44    PixelGetExceptionType,
45    PixelGetException
46);
47
48impl PixelWand {
49    /// Return true if the distance between this pixel's color and the other's is
50    /// within the given `fuzz` factor.
51    pub fn is_similar(&self, other: &PixelWand, fuzz: f64) -> bool {
52        let result = unsafe { bindings::IsPixelWandSimilar(self.wand, other.wand, fuzz) };
53        result == MagickTrue
54    }
55
56    /// Return the pixel's color as hue, saturation, and lightness values.
57    pub fn get_hsl(&self) -> HSL {
58        let mut hsl = HSL::default();
59        unsafe {
60            bindings::PixelGetHSL(
61                self.wand,
62                &mut hsl.hue as *mut _,
63                &mut hsl.saturation as *mut _,
64                &mut hsl.lightness as *mut _,
65            );
66        }
67        hsl
68    }
69
70    /// Set the pixel's color from hue, saturation, and lightness values.
71    pub fn set_hsl(&self, hsl: &HSL) {
72        unsafe {
73            bindings::PixelSetHSL(self.wand, hsl.hue, hsl.saturation, hsl.lightness);
74        }
75    }
76
77    /// Format the wand's settings for debugging, indenting each line with the
78    /// given `prefix`.
79    pub fn fmt_w_prefix(&self, f: &mut fmt::Formatter, prefix: &str) -> fmt::Result {
80        let mut prf = prefix.to_string();
81        prf.push_str("    ");
82        writeln!(f, "{prefix}PixelWand {{")?;
83        writeln!(f, "{}Exception: {:?}", prf, self.get_exception())?;
84        writeln!(f, "{}IsWand: {:?}", prf, self.is_wand())?;
85        self.fmt_unchecked_settings(f, &prf)?;
86        self.fmt_color_settings(f, &prf)?;
87        writeln!(f, "{prefix}}}")
88    }
89
90    /// Set the pixel's color from a color string such as `"#ff0000"` or `"red"`.
91    pub fn set_color(&mut self, s: &str) -> Result<()> {
92        let c_string = CString::new(s).map_err(|_| "could not convert to cstring")?;
93        match unsafe { bindings::PixelSetColor(self.wand, c_string.as_ptr()) } {
94            MagickTrue => Ok(()),
95            _ => Err(MagickError(self.get_exception()?.0)),
96        }
97    }
98
99    string_get!(get_color_as_string, PixelGetColorAsString);
100    string_get!(
101        get_color_as_normalized_string,
102        PixelGetColorAsNormalizedString
103    );
104
105    set_get_unchecked!(
106        get_color_count, set_color_count, PixelGetColorCount, PixelSetColorCount,   usize
107        get_index,       set_index,       PixelGetIndex,      PixelSetIndex,        bindings::Quantum
108        get_fuzz,        set_fuzz,        PixelGetFuzz,       PixelSetFuzz,         f64
109    );
110
111    color_set_get!(
112        get_alpha,        get_alpha_quantum,       set_alpha,        set_alpha_quantum,
113        PixelGetAlpha,    PixelGetAlphaQuantum,    PixelSetAlpha,    PixelSetAlphaQuantum
114        get_black,        get_black_quantum,       set_black,        set_black_quantum,
115        PixelGetBlack,    PixelGetBlackQuantum,    PixelSetBlack,    PixelSetBlackQuantum
116        get_blue,         get_blue_quantum,        set_blue,         set_blue_quantum,
117        PixelGetBlue,     PixelGetBlueQuantum,     PixelSetBlue,     PixelSetBlueQuantum
118        get_cyan,         get_cyan_quantum,        set_cyan,         set_cyan_quantum,
119        PixelGetCyan,     PixelGetCyanQuantum,     PixelSetCyan,     PixelSetCyanQuantum
120        get_green,        get_green_quantum,       set_green,        set_green_quantum,
121        PixelGetGreen,    PixelGetGreenQuantum,    PixelSetGreen,    PixelSetGreenQuantum
122        get_magenta,      get_magenta_quantum,     set_magenta,      set_magenta_quantum,
123        PixelGetMagenta,  PixelGetMagentaQuantum,  PixelSetMagenta,  PixelSetMagentaQuantum
124        get_red,          get_red_quantum,         set_red,          set_red_quantum,
125        PixelGetRed,      PixelGetRedQuantum,      PixelSetRed,      PixelSetRedQuantum
126        get_yellow,       get_yellow_quantum,      set_yellow,       set_yellow_quantum,
127        PixelGetYellow,   PixelGetYellowQuantum,   PixelSetYellow,   PixelSetYellowQuantum
128    );
129}
130
131impl fmt::Debug for PixelWand {
132    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133        self.fmt_w_prefix(f, "")
134    }
135}