1use std::ops::DerefMut;
2
3use image::{ColorType, DynamicImage, ImageBuffer, Pixel};
4
5use crate::{BufferBlend, BufferGetAlpha, BufferSetAlpha, BufferStripAlpha, Error};
6
7pub trait DynamicChops {
8 fn blend (
89 &mut self,
90 other: &Self,
91 op: fn(f64, f64) -> f64,
92 apply_to_color: bool,
93 apply_to_alpha: bool,
94 ) -> Result<(), Error>;
95 fn get_alpha(
122 &self,
123 ) -> Option<Self> where Self: std::marker::Sized;
124 fn transplant_alpha(
151 &mut self,
152 other: &Self
153 ) -> Result<(), Error>;
154 fn set_alpha(
186 &mut self,
187 other: &Self
188 ) -> Result<(), Error> where Self: std::marker::Sized;
189
190 fn strip_alpha(
213 &mut self
214 ) -> Result<(), Error> where Self: std::marker::Sized;
215}
216impl DynamicChops for DynamicImage {
217 fn blend (
218 &mut self,
219 other: &Self,
220 op: fn(f64, f64) -> f64,
221 apply_to_color: bool,
222 apply_to_alpha: bool,
223 ) -> Result<(), Error> {
224 match self.color() {
225 ColorType::L8 => blend_step_a(self.as_mut_luma8().unwrap(), other, op, apply_to_color, apply_to_alpha),
226 ColorType::La8 => blend_step_a(self.as_mut_luma_alpha8().unwrap(), other, op, apply_to_color, apply_to_alpha),
227 ColorType::Rgb8 => blend_step_a(self.as_mut_rgb8().unwrap(), other, op, apply_to_color, apply_to_alpha),
228 ColorType::Rgba8 => blend_step_a(self.as_mut_rgba8().unwrap(), other, op, apply_to_color, apply_to_alpha),
229 ColorType::L16 => blend_step_a(self.as_mut_luma16().unwrap(), other, op, apply_to_color, apply_to_alpha),
230 ColorType::La16 => blend_step_a(self.as_mut_luma_alpha16().unwrap(), other, op, apply_to_color, apply_to_alpha),
231 ColorType::Rgb16 => blend_step_a(self.as_mut_rgb16().unwrap(), other, op, apply_to_color, apply_to_alpha),
232 ColorType::Rgba16 => blend_step_a(self.as_mut_rgba16().unwrap(), other, op, apply_to_color, apply_to_alpha),
233 ColorType::Rgb32F => blend_step_a(self.as_mut_rgb32f().unwrap(), other, op, apply_to_color, apply_to_alpha),
234 ColorType::Rgba32F => blend_step_a(self.as_mut_rgba32f().unwrap(), other, op, apply_to_color, apply_to_alpha),
235 _ => Err(Error::UnsupportedType),
236
237 }
238 }
239 fn get_alpha(
240 &self,
241 ) -> Option<DynamicImage> {
242 let color = self.color();
243 let mut copy = self.clone();
244 match color {
245 ColorType::L8 => get_alpha_step_a(copy.as_mut_luma8().unwrap()),
246 ColorType::La8 => get_alpha_step_a(copy.as_mut_luma_alpha8().unwrap()),
247 ColorType::Rgb8 => get_alpha_step_a(copy.as_mut_rgb8().unwrap()),
248 ColorType::Rgba8 => get_alpha_step_a(copy.as_mut_rgba8().unwrap()),
249 ColorType::L16 => get_alpha_step_a(copy.as_mut_luma16().unwrap()),
250 ColorType::La16 => get_alpha_step_a(copy.as_mut_luma_alpha16().unwrap()),
251 ColorType::Rgb16 => get_alpha_step_a(copy.as_mut_rgb16().unwrap()),
252 ColorType::Rgba16 => get_alpha_step_a(copy.as_mut_rgba16().unwrap()),
253 ColorType::Rgb32F => get_alpha_step_a(copy.as_mut_rgb32f().unwrap()),
254 ColorType::Rgba32F => get_alpha_step_a(copy.as_mut_rgba32f().unwrap()),
255 _ => Err(Error::UnsupportedType),
256 }.ok()?;
257 Some(copy)
258 }
259 fn transplant_alpha(
260 &mut self,
261 other: &Self
262 ) -> Result<(), Error> {
263 match self.color() {
264 ColorType::L8 => transplant_alpha_step_a(self.as_mut_luma8().unwrap(), other),
265 ColorType::La8 => transplant_alpha_step_a(self.as_mut_luma_alpha8().unwrap(), other),
266 ColorType::Rgb8 => transplant_alpha_step_a(self.as_mut_rgb8().unwrap(), other),
267 ColorType::Rgba8 => transplant_alpha_step_a(self.as_mut_rgba8().unwrap(), other),
268 ColorType::L16 => transplant_alpha_step_a(self.as_mut_luma16().unwrap(), other),
269 ColorType::La16 => transplant_alpha_step_a(self.as_mut_luma_alpha16().unwrap(), other),
270 ColorType::Rgb16 => transplant_alpha_step_a(self.as_mut_rgb16().unwrap(), other),
271 ColorType::Rgba16 => transplant_alpha_step_a(self.as_mut_rgba16().unwrap(), other),
272 ColorType::Rgb32F => transplant_alpha_step_a(self.as_mut_rgb32f().unwrap(), other),
273 ColorType::Rgba32F => transplant_alpha_step_a(self.as_mut_rgba32f().unwrap(), other),
274 _ => Err(Error::UnsupportedType),
275 }?;
276 Ok(())
277 }
278 fn set_alpha(
279 &mut self,
280 other: &Self
281 ) -> Result<(), Error> {
282 match self.color() {
283 ColorType::L8 => set_alpha_step_a(self.as_mut_luma8().unwrap(), other),
284 ColorType::La8 => set_alpha_step_a(self.as_mut_luma_alpha8().unwrap(), other),
285 ColorType::Rgb8 => set_alpha_step_a(self.as_mut_rgb8().unwrap(), other),
286 ColorType::Rgba8 => set_alpha_step_a(self.as_mut_rgba8().unwrap(), other),
287 ColorType::L16 => set_alpha_step_a(self.as_mut_luma16().unwrap(), other),
288 ColorType::La16 => set_alpha_step_a(self.as_mut_luma_alpha16().unwrap(), other),
289 ColorType::Rgb16 => set_alpha_step_a(self.as_mut_rgb16().unwrap(), other),
290 ColorType::Rgba16 => set_alpha_step_a(self.as_mut_rgba16().unwrap(), other),
291 ColorType::Rgb32F => set_alpha_step_a(self.as_mut_rgb32f().unwrap(), other),
292 ColorType::Rgba32F => set_alpha_step_a(self.as_mut_rgba32f().unwrap(), other),
293 _ => Err(Error::UnsupportedType),
294 }?;
295 Ok(())
296 }
297 fn strip_alpha(
298 &mut self
299 ) -> Result<(), Error> where Self: std::marker::Sized {
300 match self.color() {
301 ColorType::L8 => self.as_mut_luma8().unwrap().strip_alpha(),
302 ColorType::La8 => self.as_mut_luma_alpha8().unwrap().strip_alpha(),
303 ColorType::Rgb8 => self.as_mut_rgb8().unwrap().strip_alpha(),
304 ColorType::Rgba8 => self.as_mut_rgba8().unwrap().strip_alpha(),
305 ColorType::L16 => self.as_mut_luma16().unwrap().strip_alpha(),
306 ColorType::La16 => self.as_mut_luma_alpha16().unwrap().strip_alpha(),
307 ColorType::Rgb16 => self.as_mut_rgb16().unwrap().strip_alpha(),
308 ColorType::Rgba16 => self.as_mut_rgba16().unwrap().strip_alpha(),
309 ColorType::Rgb32F => self.as_mut_rgb32f().unwrap().strip_alpha(),
310 ColorType::Rgba32F => self.as_mut_rgba32f().unwrap().strip_alpha(),
311 _ => Err(Error::UnsupportedType),
312 }?;
313 Ok(())
314 }
315}
316fn blend_step_a<Pmut, ContainerMut>(subject: &mut ImageBuffer<Pmut, ContainerMut>, other: &DynamicImage, op: fn(f64, f64) -> f64, apply_to_color: bool, apply_to_alpha: bool) -> Result<(), Error>
317where
318 Pmut: Pixel,
319 ContainerMut: DerefMut<Target = [Pmut::Subpixel]>
320 + DerefMut<Target = [Pmut::Subpixel]>
321 + AsMut<[<Pmut as Pixel>::Subpixel]>
322{
323 match other.color() {
324 ColorType::L8 => subject.blend(other.as_luma8().unwrap(), op, apply_to_color, apply_to_alpha),
325 ColorType::La8 => subject.blend(other.as_luma_alpha8().unwrap(), op, apply_to_color, apply_to_alpha),
326 ColorType::Rgb8 => subject.blend(other.as_rgb8().unwrap(), op, apply_to_color, apply_to_alpha),
327 ColorType::Rgba8 => subject.blend(other.as_rgba8().unwrap(), op, apply_to_color, apply_to_alpha),
328 ColorType::L16 => subject.blend(other.as_luma16().unwrap(), op, apply_to_color, apply_to_alpha),
329 ColorType::La16 => subject.blend(other.as_luma_alpha16().unwrap(), op, apply_to_color, apply_to_alpha),
330 ColorType::Rgb16 => subject.blend(other.as_rgb16().unwrap(), op, apply_to_color, apply_to_alpha),
331 ColorType::Rgba16 => subject.blend(other.as_rgba16().unwrap(), op, apply_to_color, apply_to_alpha),
332 ColorType::Rgb32F => subject.blend(other.as_rgb32f().unwrap(), op, apply_to_color, apply_to_alpha),
333 ColorType::Rgba32F => subject.blend(other.as_rgba32f().unwrap(), op, apply_to_color, apply_to_alpha),
334 _ => Err(Error::UnsupportedType),
335 }
336}
337fn get_alpha_step_a<P, Container>(subject: &mut ImageBuffer<P, Container>) -> Result<(), Error>
338where
339 P: Pixel,
340 Container: DerefMut<Target = [P::Subpixel]> + AsRef<[<P as image::Pixel>::Subpixel]> + Clone,
341{
342 let alpha = subject.get_alpha().ok_or(Error::NoAlphaChannel)?;
343 *subject = alpha;
344 Ok(())
345}
346fn set_alpha_step_a<Pmut, ContainerMut>(subject: &mut ImageBuffer<Pmut, ContainerMut>, other: &DynamicImage) -> Result<(), Error>
347where
348 Pmut: Pixel,
349 ContainerMut: DerefMut<Target = [Pmut::Subpixel]>
350 + DerefMut<Target = [Pmut::Subpixel]>
351 + AsMut<[<Pmut as Pixel>::Subpixel]>
352{
353 match other.color() {
354 ColorType::L8 => subject.set_alpha(other.as_luma8().unwrap()),
355 ColorType::La8 => subject.set_alpha(other.as_luma_alpha8().unwrap()),
356 ColorType::Rgb8 => subject.set_alpha(other.as_rgb8().unwrap()),
357 ColorType::Rgba8 => subject.set_alpha(other.as_rgba8().unwrap()),
358 ColorType::L16 => subject.set_alpha(other.as_luma16().unwrap()),
359 ColorType::La16 => subject.set_alpha(other.as_luma_alpha16().unwrap()),
360 ColorType::Rgb16 => subject.set_alpha(other.as_rgb16().unwrap()),
361 ColorType::Rgba16 => subject.set_alpha(other.as_rgba16().unwrap()),
362 ColorType::Rgb32F => subject.set_alpha(other.as_rgb32f().unwrap()),
363 ColorType::Rgba32F => subject.set_alpha(other.as_rgba32f().unwrap()),
364 _ => Err(Error::UnsupportedType),
365 }
366}
367fn transplant_alpha_step_a<Pmut, ContainerMut>(subject: &mut ImageBuffer<Pmut, ContainerMut>, other: &DynamicImage) -> Result<(), Error>
368where
369 Pmut: Pixel,
370 ContainerMut: DerefMut<Target = [Pmut::Subpixel]>
371 + DerefMut<Target = [Pmut::Subpixel]>
372 + AsMut<[<Pmut as Pixel>::Subpixel]>,
373{
374 match other.color() {
375 ColorType::L8 => subject.transplant_alpha(other.as_luma8().unwrap()),
376 ColorType::La8 => subject.transplant_alpha(other.as_luma_alpha8().unwrap()),
377 ColorType::Rgb8 => subject.transplant_alpha(other.as_rgb8().unwrap()),
378 ColorType::Rgba8 => subject.transplant_alpha(other.as_rgba8().unwrap()),
379 ColorType::L16 => subject.transplant_alpha(other.as_luma16().unwrap()),
380 ColorType::La16 => subject.transplant_alpha(other.as_luma_alpha16().unwrap()),
381 ColorType::Rgb16 => subject.transplant_alpha(other.as_rgb16().unwrap()),
382 ColorType::Rgba16 => subject.transplant_alpha(other.as_rgba16().unwrap()),
383 ColorType::Rgb32F => subject.transplant_alpha(other.as_rgb32f().unwrap()),
384 ColorType::Rgba32F => subject.transplant_alpha(other.as_rgba32f().unwrap()),
385 _ => Err(Error::UnsupportedType),
386 }
387}