Coverage Report

Created: 2026-07-16 07:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/image/src/traits.rs
Line
Count
Source
1
//! This module provides useful traits that were deprecated in rust
2
3
// Note copied from the stdlib under MIT license
4
5
use num_traits::{Bounded, Num, NumCast};
6
use std::ops::AddAssign;
7
8
use crate::color::{Luma, LumaA, Rgb, Rgba};
9
use crate::primitive_sealed::PrimitiveSealed;
10
use crate::ExtendedColorType;
11
12
/// Types which are safe to treat as an immutable byte slice in a pixel layout
13
/// for image encoding.
14
pub trait EncodableLayout: seals::EncodableLayout {
15
    /// Get the bytes of this value.
16
    fn as_bytes(&self) -> &[u8];
17
}
18
19
impl EncodableLayout for [u8] {
20
1.72k
    fn as_bytes(&self) -> &[u8] {
21
1.72k
        bytemuck::cast_slice(self)
22
1.72k
    }
23
}
24
25
impl EncodableLayout for [u16] {
26
0
    fn as_bytes(&self) -> &[u8] {
27
0
        bytemuck::cast_slice(self)
28
0
    }
29
}
30
31
impl EncodableLayout for [f32] {
32
0
    fn as_bytes(&self) -> &[u8] {
33
0
        bytemuck::cast_slice(self)
34
0
    }
35
}
36
37
/// The type of each channel in a pixel. For example, this can be `u8`, `u16`, `f32`.
38
// TODO rename to `PixelComponent`? Split up into separate traits? Seal?
39
pub trait Primitive:
40
    Copy + NumCast + Num + PartialOrd<Self> + Clone + Bounded + PrimitiveSealed
41
{
42
    /// The maximum value for this type of primitive within the context of color.
43
    /// For floats, the maximum is `1.0`, whereas the integer types inherit their usual maximum values.
44
    const DEFAULT_MAX_VALUE: Self;
45
46
    /// The minimum value for this type of primitive within the context of color.
47
    /// For floats, the minimum is `0.0`, whereas the integer types inherit their usual minimum values.
48
    const DEFAULT_MIN_VALUE: Self;
49
}
50
51
macro_rules! declare_primitive {
52
    ($base:ty: ($from:expr)..$to:expr) => {
53
        impl Primitive for $base {
54
            const DEFAULT_MAX_VALUE: Self = $to;
55
            const DEFAULT_MIN_VALUE: Self = $from;
56
        }
57
    };
58
}
59
60
declare_primitive!(usize: (0)..Self::MAX);
61
declare_primitive!(u8: (0)..Self::MAX);
62
declare_primitive!(u16: (0)..Self::MAX);
63
declare_primitive!(u32: (0)..Self::MAX);
64
declare_primitive!(u64: (0)..Self::MAX);
65
66
declare_primitive!(isize: (Self::MIN)..Self::MAX);
67
declare_primitive!(i8: (Self::MIN)..Self::MAX);
68
declare_primitive!(i16: (Self::MIN)..Self::MAX);
69
declare_primitive!(i32: (Self::MIN)..Self::MAX);
70
declare_primitive!(i64: (Self::MIN)..Self::MAX);
71
declare_primitive!(f32: (0.0)..1.0);
72
declare_primitive!(f64: (0.0)..1.0);
73
74
/// An `Enlargable::Larger` value should be enough to calculate
75
/// the sum (average) of a few hundred or thousand Enlargeable values.
76
pub trait Enlargeable: Sized + Bounded + NumCast {
77
    type Larger: Copy + NumCast + Num + PartialOrd<Self::Larger> + Clone + Bounded + AddAssign;
78
79
0
    fn clamp_from(n: Self::Larger) -> Self {
80
0
        if n > Self::max_value().to_larger() {
81
0
            Self::max_value()
82
0
        } else if n < Self::min_value().to_larger() {
83
0
            Self::min_value()
84
        } else {
85
0
            NumCast::from(n).unwrap()
86
        }
87
0
    }
Unexecuted instantiation: <f32 as image::traits::Enlargeable>::clamp_from
Unexecuted instantiation: <u8 as image::traits::Enlargeable>::clamp_from
Unexecuted instantiation: <u16 as image::traits::Enlargeable>::clamp_from
88
89
0
    fn to_larger(self) -> Self::Larger {
90
0
        NumCast::from(self).unwrap()
91
0
    }
Unexecuted instantiation: <f32 as image::traits::Enlargeable>::to_larger
Unexecuted instantiation: <u8 as image::traits::Enlargeable>::to_larger
Unexecuted instantiation: <u16 as image::traits::Enlargeable>::to_larger
92
}
93
94
impl Enlargeable for u8 {
95
    type Larger = u32;
96
}
97
impl Enlargeable for u16 {
98
    type Larger = u32;
99
}
100
impl Enlargeable for u32 {
101
    type Larger = u64;
102
}
103
impl Enlargeable for u64 {
104
    type Larger = u128;
105
}
106
impl Enlargeable for usize {
107
    // Note: On 32-bit architectures, u64 should be enough here.
108
    type Larger = u128;
109
}
110
impl Enlargeable for i8 {
111
    type Larger = i32;
112
}
113
impl Enlargeable for i16 {
114
    type Larger = i32;
115
}
116
impl Enlargeable for i32 {
117
    type Larger = i64;
118
}
119
impl Enlargeable for i64 {
120
    type Larger = i128;
121
}
122
impl Enlargeable for isize {
123
    // Note: On 32-bit architectures, i64 should be enough here.
124
    type Larger = i128;
125
}
126
impl Enlargeable for f32 {
127
    type Larger = f64;
128
}
129
impl Enlargeable for f64 {
130
    type Larger = f64;
131
}
132
133
/// Linear interpolation without involving floating numbers.
134
pub trait Lerp: Bounded + NumCast {
135
    type Ratio: Primitive;
136
137
0
    fn lerp(a: Self, b: Self, ratio: Self::Ratio) -> Self {
138
0
        let a = <Self::Ratio as NumCast>::from(a).unwrap();
139
0
        let b = <Self::Ratio as NumCast>::from(b).unwrap();
140
141
0
        let res = a + (b - a) * ratio;
142
143
0
        if res > NumCast::from(Self::max_value()).unwrap() {
144
0
            Self::max_value()
145
0
        } else if res < NumCast::from(0).unwrap() {
146
0
            NumCast::from(0).unwrap()
147
        } else {
148
0
            NumCast::from(res).unwrap()
149
        }
150
0
    }
151
}
152
153
impl Lerp for u8 {
154
    type Ratio = f32;
155
}
156
157
impl Lerp for u16 {
158
    type Ratio = f32;
159
}
160
161
impl Lerp for u32 {
162
    type Ratio = f64;
163
}
164
165
impl Lerp for f32 {
166
    type Ratio = f32;
167
168
0
    fn lerp(a: Self, b: Self, ratio: Self::Ratio) -> Self {
169
0
        a + (b - a) * ratio
170
0
    }
171
}
172
173
/// The pixel with an associated `ColorType`.
174
/// Not all possible pixels represent one of the predefined `ColorType`s.
175
pub trait PixelWithColorType:
176
    Pixel + private::SealedPixelWithColorType<TransformableSubpixel = <Self as Pixel>::Subpixel>
177
{
178
    /// This pixel has the format of one of the predefined `ColorType`s,
179
    /// such as `Rgb8`, `La16` or `Rgba32F`.
180
    /// This is needed for automatically detecting
181
    /// a color format when saving an image as a file.
182
    const COLOR_TYPE: ExtendedColorType;
183
}
184
185
impl PixelWithColorType for Rgb<u8> {
186
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgb8;
187
}
188
impl PixelWithColorType for Rgb<u16> {
189
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgb16;
190
}
191
impl PixelWithColorType for Rgb<f32> {
192
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgb32F;
193
}
194
195
impl PixelWithColorType for Rgba<u8> {
196
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgba8;
197
}
198
impl PixelWithColorType for Rgba<u16> {
199
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgba16;
200
}
201
impl PixelWithColorType for Rgba<f32> {
202
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::Rgba32F;
203
}
204
205
impl PixelWithColorType for Luma<u8> {
206
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::L8;
207
}
208
impl PixelWithColorType for Luma<u16> {
209
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::L16;
210
}
211
impl PixelWithColorType for Luma<f32> {
212
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::L32F;
213
}
214
215
impl PixelWithColorType for LumaA<u8> {
216
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::La8;
217
}
218
impl PixelWithColorType for LumaA<u16> {
219
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::La16;
220
}
221
impl PixelWithColorType for LumaA<f32> {
222
    const COLOR_TYPE: ExtendedColorType = ExtendedColorType::La32F;
223
}
224
225
/// Prevents down-stream users from implementing the `Primitive` trait
226
pub(crate) mod private {
227
    use crate::color::*;
228
    use crate::metadata::cicp::{self, CicpApplicable};
229
230
    #[derive(Clone, Copy, Debug)]
231
    pub enum LayoutWithColor {
232
        Rgb,
233
        Rgba,
234
        Luma,
235
        LumaAlpha,
236
    }
237
238
    impl From<ColorType> for LayoutWithColor {
239
0
        fn from(color: ColorType) -> LayoutWithColor {
240
0
            match color {
241
0
                ColorType::L8 | ColorType::L16 | ColorType::L32F => LayoutWithColor::Luma,
242
0
                ColorType::La8 | ColorType::La16 | ColorType::La32F => LayoutWithColor::LumaAlpha,
243
0
                ColorType::Rgb8 | ColorType::Rgb16 | ColorType::Rgb32F => LayoutWithColor::Rgb,
244
0
                ColorType::Rgba8 | ColorType::Rgba16 | ColorType::Rgba32F => LayoutWithColor::Rgba,
245
            }
246
0
        }
247
    }
248
249
    impl LayoutWithColor {
250
0
        pub(crate) fn channels(self) -> usize {
251
0
            match self {
252
0
                Self::Rgb => 3,
253
0
                Self::Rgba => 4,
254
0
                Self::Luma => 1,
255
0
                Self::LumaAlpha => 2,
256
            }
257
0
        }
258
    }
259
260
    #[derive(Clone, Copy)]
261
    pub struct PrivateToken;
262
263
    pub trait SealedPixelWithColorType {
264
        #[expect(private_bounds)] // This is a sealed trait.
265
        type TransformableSubpixel: HelpDispatchTransform;
266
        fn layout(_: PrivateToken) -> LayoutWithColor;
267
    }
268
269
    impl SealedPixelWithColorType for Rgb<u8> {
270
        type TransformableSubpixel = u8;
271
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
272
0
            LayoutWithColor::Rgb
273
0
        }
274
    }
275
276
    impl SealedPixelWithColorType for Rgb<u16> {
277
        type TransformableSubpixel = u16;
278
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
279
0
            LayoutWithColor::Rgb
280
0
        }
281
    }
282
283
    impl SealedPixelWithColorType for Rgb<f32> {
284
        type TransformableSubpixel = f32;
285
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
286
0
            LayoutWithColor::Rgb
287
0
        }
288
    }
289
290
    impl SealedPixelWithColorType for Rgba<u8> {
291
        type TransformableSubpixel = u8;
292
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
293
0
            LayoutWithColor::Rgba
294
0
        }
295
    }
296
297
    impl SealedPixelWithColorType for Rgba<u16> {
298
        type TransformableSubpixel = u16;
299
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
300
0
            LayoutWithColor::Rgba
301
0
        }
302
    }
303
304
    impl SealedPixelWithColorType for Rgba<f32> {
305
        type TransformableSubpixel = f32;
306
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
307
0
            LayoutWithColor::Rgba
308
0
        }
309
    }
310
311
    impl SealedPixelWithColorType for Luma<u8> {
312
        type TransformableSubpixel = u8;
313
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
314
0
            LayoutWithColor::Luma
315
0
        }
316
    }
317
318
    impl SealedPixelWithColorType for LumaA<u8> {
319
        type TransformableSubpixel = u8;
320
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
321
0
            LayoutWithColor::LumaAlpha
322
0
        }
323
    }
324
325
    impl SealedPixelWithColorType for Luma<u16> {
326
        type TransformableSubpixel = u16;
327
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
328
0
            LayoutWithColor::Luma
329
0
        }
330
    }
331
332
    impl SealedPixelWithColorType for Luma<f32> {
333
        type TransformableSubpixel = f32;
334
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
335
0
            LayoutWithColor::Luma
336
0
        }
337
    }
338
339
    impl SealedPixelWithColorType for LumaA<u16> {
340
        type TransformableSubpixel = u16;
341
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
342
0
            LayoutWithColor::LumaAlpha
343
0
        }
344
    }
345
346
    impl SealedPixelWithColorType for LumaA<f32> {
347
        type TransformableSubpixel = f32;
348
0
        fn layout(_: PrivateToken) -> LayoutWithColor {
349
0
            LayoutWithColor::LumaAlpha
350
0
        }
351
    }
352
353
    // Consider a situation in a function bounded `Self: Pixel + PixelWithColorType`. Then, if we
354
    // tried this directly:
355
    //
356
    // <
357
    //   <Self as SealedPixelWithColorType>::TransformableSubpixel as HelpDispatchTransform
358
    // >::transform_on::<Self>(tr, LayoutWithColor::Rgb);
359
    //
360
    // the type checker is mightily confused. I think what's going on is as follows: It find the
361
    // fact that `Self::Subpixel` is used for `TransformableSubpixel` from the bound on
362
    // `PixelWithColorType`, but then there is no existing bound on `Subpixel` that would guarantee
363
    // that `HelpDispatchTransform` is fulfilled. That would only be available by substituting
364
    // _back_ so that the bound on `TransformableSubpixel` gets applied to the `Subpixel` generic,
365
    // too. But now there are no variables here, so unification of bounds takes place we never
366
    // never get to see the bound (until next gen, I guess?). It finally find that there is still
367
    // an unfulfilled bound and complains.
368
    //
369
    // Hence we must avoid mentioning the `Pixel` and `PixelWithColorType` bound so that _only_ the
370
    // `TransformableSubpixel` is available. Then all substitutions work forwards, and since we
371
    // return a `TransformableSubpixel` we get the function back without new variables to solve
372
    // for, and that can then be unified just fine. This extra function essentially introduces that
373
    // missing unknown which can unify the available impl set. Yay.
374
0
    pub(crate) fn dispatch_transform_from_sealed<P: SealedPixelWithColorType>(
375
0
        transform: &cicp::CicpTransform,
376
0
        into: LayoutWithColor,
377
0
    ) -> &'_ CicpApplicable<'_, P::TransformableSubpixel> {
378
0
        <P::TransformableSubpixel as HelpDispatchTransform>::transform_on::<P>(transform, into)
379
0
    }
Unexecuted instantiation: image::traits::private::dispatch_transform_from_sealed::<image::color::Rgb<f32>>
Unexecuted instantiation: image::traits::private::dispatch_transform_from_sealed::<image::color::Rgb<u8>>
Unexecuted instantiation: image::traits::private::dispatch_transform_from_sealed::<image::color::Rgb<u16>>
Unexecuted instantiation: image::traits::private::dispatch_transform_from_sealed::<image::color::Rgba<f32>>
Unexecuted instantiation: image::traits::private::dispatch_transform_from_sealed::<image::color::Rgba<u8>>
Unexecuted instantiation: image::traits::private::dispatch_transform_from_sealed::<image::color::Rgba<u16>>
380
381
0
    pub(crate) fn double_dispatch_transform_from_sealed<
382
0
        P: SealedPixelWithColorType,
383
0
        Into: SealedPixelWithColorType,
384
0
    >(
385
0
        transform: &cicp::CicpTransform,
386
0
    ) -> &'_ CicpApplicable<'_, P::TransformableSubpixel> {
387
0
        dispatch_transform_from_sealed::<P>(transform, Into::layout(PrivateToken))
388
0
    }
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgb<f32>, image::color::Rgb<f32>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgb<f32>, image::color::Rgba<f32>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgb<u8>, image::color::Rgb<u8>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgb<u8>, image::color::Rgba<u8>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgb<u16>, image::color::Rgb<u16>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgb<u16>, image::color::Rgba<u16>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgba<f32>, image::color::Rgba<f32>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgba<f32>, image::color::Rgb<f32>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgba<u8>, image::color::Rgba<u8>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgba<u8>, image::color::Rgb<u8>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgba<u16>, image::color::Rgba<u16>>
Unexecuted instantiation: image::traits::private::double_dispatch_transform_from_sealed::<image::color::Rgba<u16>, image::color::Rgb<u16>>
389
390
    pub(crate) trait HelpDispatchTransform: Sized + 'static {
391
        fn transform_on<O: SealedPixelWithColorType<TransformableSubpixel = Self>>(
392
            transform: &cicp::CicpTransform,
393
            into: LayoutWithColor,
394
        ) -> &'_ (dyn Fn(&[Self], &mut [Self]) + Send + Sync);
395
    }
396
397
    impl HelpDispatchTransform for u8 {
398
0
        fn transform_on<O: SealedPixelWithColorType<TransformableSubpixel = Self>>(
399
0
            transform: &cicp::CicpTransform,
400
0
            into: LayoutWithColor,
401
0
        ) -> &'_ (dyn Fn(&[Self], &mut [Self]) + Send + Sync) {
402
0
            &**transform.select_transform_u8::<O>(into)
403
0
        }
Unexecuted instantiation: <u8 as image::traits::private::HelpDispatchTransform>::transform_on::<image::color::Rgb<u8>>
Unexecuted instantiation: <u8 as image::traits::private::HelpDispatchTransform>::transform_on::<image::color::Rgba<u8>>
404
    }
405
406
    impl HelpDispatchTransform for u16 {
407
0
        fn transform_on<O: SealedPixelWithColorType<TransformableSubpixel = Self>>(
408
0
            transform: &cicp::CicpTransform,
409
0
            into: LayoutWithColor,
410
0
        ) -> &'_ (dyn Fn(&[Self], &mut [Self]) + Send + Sync) {
411
0
            &**transform.select_transform_u16::<O>(into)
412
0
        }
Unexecuted instantiation: <u16 as image::traits::private::HelpDispatchTransform>::transform_on::<image::color::Rgb<u16>>
Unexecuted instantiation: <u16 as image::traits::private::HelpDispatchTransform>::transform_on::<image::color::Rgba<u16>>
413
    }
414
415
    impl HelpDispatchTransform for f32 {
416
0
        fn transform_on<O: SealedPixelWithColorType<TransformableSubpixel = Self>>(
417
0
            transform: &cicp::CicpTransform,
418
0
            into: LayoutWithColor,
419
0
        ) -> &'_ (dyn Fn(&[Self], &mut [Self]) + Send + Sync) {
420
0
            &**transform.select_transform_f32::<O>(into)
421
0
        }
Unexecuted instantiation: <f32 as image::traits::private::HelpDispatchTransform>::transform_on::<image::color::Rgb<f32>>
Unexecuted instantiation: <f32 as image::traits::private::HelpDispatchTransform>::transform_on::<image::color::Rgba<f32>>
422
    }
423
}
424
425
/// A generalized pixel.
426
///
427
/// A pixel object is usually not used standalone but as a view into an image buffer.
428
pub trait Pixel: Copy + Clone {
429
    /// The scalar type that is used to store each channel in this pixel.
430
    type Subpixel: Primitive;
431
432
    /// The number of channels of this pixel type.
433
    const CHANNEL_COUNT: u8;
434
435
    /// Returns the components as a slice.
436
    fn channels(&self) -> &[Self::Subpixel];
437
438
    /// Returns the components as a mutable slice
439
    fn channels_mut(&mut self) -> &mut [Self::Subpixel];
440
441
    /// A string that can help to interpret the meaning each channel
442
    /// See [gimp babl](http://gegl.org/babl/).
443
    const COLOR_MODEL: &'static str;
444
445
    /// Returns true if the alpha channel is contained.
446
    const HAS_ALPHA: bool = false;
447
448
    /// Retrieve the value of the alpha channel for this pixel.
449
    ///
450
    /// If there is no alpha channel, returns [Primitive::DEFAULT_MAX_VALUE].
451
    ///
452
    /// ### Note for Pixel trait implementors
453
    ///
454
    /// While this is a provided method, it is a good idea to override it for efficiency
455
    /// if your pixel type does have an alpha channel.
456
    #[inline]
457
0
    fn alpha(&self) -> Self::Subpixel {
458
0
        if Self::HAS_ALPHA {
459
0
            self.to_luma_alpha().0[1]
460
        } else {
461
0
            Self::Subpixel::DEFAULT_MAX_VALUE
462
        }
463
0
    }
464
465
    /// Returns a view into a slice.
466
    ///
467
    /// Note: The slice length is not checked on creation. Thus the caller has to ensure
468
    /// that the slice is long enough to prevent panics if the pixel is used later on.
469
    fn from_slice(slice: &[Self::Subpixel]) -> &Self;
470
471
    /// Returns mutable view into a mutable slice.
472
    ///
473
    /// Note: The slice length is not checked on creation. Thus the caller has to ensure
474
    /// that the slice is long enough to prevent panics if the pixel is used later on.
475
    fn from_slice_mut(slice: &mut [Self::Subpixel]) -> &mut Self;
476
477
    /// Returns a slice of pixels from a slice of subpixels.
478
    ///
479
    /// If `slice.len()` is not a multiple of `CHANNEL_COUNT`, the longest prefix of whole pixels is returned.
480
    fn pixels_from_channels(slice: &[Self::Subpixel]) -> &[Self];
481
482
    /// Returns a mutable slice of pixels from a mutable slice of subpixels.
483
    ///
484
    /// If `slice.len()` is not a multiple of `CHANNEL_COUNT`, the longest prefix of whole pixels is returned.
485
    fn pixels_from_channels_mut(slice: &mut [Self::Subpixel]) -> &mut [Self];
486
487
    /// Returns a slice of subpixels from a slice of pixels.
488
    fn pixels_as_channels(slice: &[Self]) -> &[Self::Subpixel];
489
490
    /// Returns a mutable slice of subpixels from a mutable slice of pixels.
491
    fn pixels_as_channels_mut(slice: &mut [Self]) -> &mut [Self::Subpixel];
492
493
    /// Create a pixel from setting all channels to the same value.
494
    fn broadcast(_: Self::Subpixel) -> Self;
495
496
    /// Convert this pixel to RGB
497
    fn to_rgb(&self) -> Rgb<Self::Subpixel>;
498
499
    /// Convert this pixel to RGB with an alpha channel
500
    fn to_rgba(&self) -> Rgba<Self::Subpixel>;
501
502
    /// Convert this pixel to luma
503
    fn to_luma(&self) -> Luma<Self::Subpixel>;
504
505
    /// Convert this pixel to luma with an alpha channel
506
    fn to_luma_alpha(&self) -> LumaA<Self::Subpixel>;
507
508
    /// Apply the function ```f``` to each channel of this pixel.
509
0
    fn map<F>(&self, f: F) -> Self
510
0
    where
511
0
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
512
    {
513
0
        let mut this = *self;
514
0
        this.apply(f);
515
0
        this
516
0
    }
Unexecuted instantiation: <image::color::Rgb<f32> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>, image::color::Rgb<f32>, f32>::{closure#0}>
Unexecuted instantiation: <image::color::Rgb<u8> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>, image::color::Rgb<u8>, u8>::{closure#0}>
Unexecuted instantiation: <image::color::Rgb<u16> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>, image::color::Rgb<u16>, u16>::{closure#0}>
Unexecuted instantiation: <image::color::Luma<f32> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::Luma<f32>, alloc::vec::Vec<f32>>, image::color::Luma<f32>, f32>::{closure#0}>
Unexecuted instantiation: <image::color::Luma<u8> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>, image::color::Luma<u8>, u8>::{closure#0}>
Unexecuted instantiation: <image::color::Luma<u16> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>, image::color::Luma<u16>, u16>::{closure#0}>
Unexecuted instantiation: <image::color::Rgba<f32> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>, image::color::Rgba<f32>, f32>::{closure#0}>
Unexecuted instantiation: <image::color::Rgba<u8> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>, image::color::Rgba<u8>, u8>::{closure#0}>
Unexecuted instantiation: <image::color::Rgba<u16> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>, image::color::Rgba<u16>, u16>::{closure#0}>
Unexecuted instantiation: <image::color::LumaA<f32> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::LumaA<f32>, alloc::vec::Vec<f32>>, image::color::LumaA<f32>, f32>::{closure#0}>
Unexecuted instantiation: <image::color::LumaA<u8> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>, image::color::LumaA<u8>, u8>::{closure#0}>
Unexecuted instantiation: <image::color::LumaA<u16> as image::traits::Pixel>::map::<image::imageops::colorops::contrast<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>, image::color::LumaA<u16>, u16>::{closure#0}>
517
518
    /// Apply the function ```f``` to each channel of this pixel.
519
    fn apply<F>(&mut self, f: F)
520
    where
521
        F: FnMut(Self::Subpixel) -> Self::Subpixel;
522
523
    /// Apply the function ```f``` to each channel except the alpha channel.
524
    /// Apply the function ```g``` to the alpha channel.
525
0
    fn map_with_alpha<F, G>(&self, f: F, g: G) -> Self
526
0
    where
527
0
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
528
0
        G: FnMut(Self::Subpixel) -> Self::Subpixel,
529
    {
530
0
        let mut this = *self;
531
0
        this.apply_with_alpha(f, g);
532
0
        this
533
0
    }
Unexecuted instantiation: <image::color::Rgb<f32> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>, image::color::Rgb<f32>, f32>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>, image::color::Rgb<f32>, f32>::{closure#1}>
Unexecuted instantiation: <image::color::Rgb<u8> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>, image::color::Rgb<u8>, u8>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>, image::color::Rgb<u8>, u8>::{closure#1}>
Unexecuted instantiation: <image::color::Rgb<u16> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>, image::color::Rgb<u16>, u16>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>, image::color::Rgb<u16>, u16>::{closure#1}>
Unexecuted instantiation: <image::color::Luma<f32> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Luma<f32>, alloc::vec::Vec<f32>>, image::color::Luma<f32>, f32>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Luma<f32>, alloc::vec::Vec<f32>>, image::color::Luma<f32>, f32>::{closure#1}>
Unexecuted instantiation: <image::color::Luma<u8> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>, image::color::Luma<u8>, u8>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>, image::color::Luma<u8>, u8>::{closure#1}>
Unexecuted instantiation: <image::color::Luma<u16> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>, image::color::Luma<u16>, u16>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>, image::color::Luma<u16>, u16>::{closure#1}>
Unexecuted instantiation: <image::color::Rgba<f32> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>, image::color::Rgba<f32>, f32>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>, image::color::Rgba<f32>, f32>::{closure#1}>
Unexecuted instantiation: <image::color::Rgba<u8> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>, image::color::Rgba<u8>, u8>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>, image::color::Rgba<u8>, u8>::{closure#1}>
Unexecuted instantiation: <image::color::Rgba<u16> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>, image::color::Rgba<u16>, u16>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>, image::color::Rgba<u16>, u16>::{closure#1}>
Unexecuted instantiation: <image::color::LumaA<f32> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::LumaA<f32>, alloc::vec::Vec<f32>>, image::color::LumaA<f32>, f32>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::LumaA<f32>, alloc::vec::Vec<f32>>, image::color::LumaA<f32>, f32>::{closure#1}>
Unexecuted instantiation: <image::color::LumaA<u8> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>, image::color::LumaA<u8>, u8>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>, image::color::LumaA<u8>, u8>::{closure#1}>
Unexecuted instantiation: <image::color::LumaA<u16> as image::traits::Pixel>::map_with_alpha::<image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>, image::color::LumaA<u16>, u16>::{closure#0}, image::imageops::colorops::brighten<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>, image::color::LumaA<u16>, u16>::{closure#1}>
534
535
    /// Apply the function ```f``` to each channel except the alpha channel.
536
    /// Apply the function ```g``` to the alpha channel. Works in-place.
537
    fn apply_with_alpha<F, G>(&mut self, f: F, g: G)
538
    where
539
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
540
        G: FnMut(Self::Subpixel) -> Self::Subpixel;
541
542
    /// Apply the function ```f``` to each channel except the alpha channel.
543
0
    fn map_without_alpha<F>(&self, f: F) -> Self
544
0
    where
545
0
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
546
    {
547
0
        self.map_with_alpha(f, |x| x)
548
0
    }
549
550
    /// Apply the function ```f``` to each channel except the alpha channel.
551
    /// Works in place.
552
0
    fn apply_without_alpha<F>(&mut self, f: F)
553
0
    where
554
0
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
555
    {
556
0
        self.apply_with_alpha(f, |x| x);
557
0
    }
558
559
    /// Apply the function ```f``` to each channel of this pixel and
560
    /// ```other``` pairwise.
561
0
    fn map2<F>(&self, other: &Self, f: F) -> Self
562
0
    where
563
0
        F: FnMut(Self::Subpixel, Self::Subpixel) -> Self::Subpixel,
564
    {
565
0
        let mut this = *self;
566
0
        this.apply2(other, f);
567
0
        this
568
0
    }
Unexecuted instantiation: <image::color::Rgb<f32> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>, image::color::Rgb<f32>, f32>::{closure#0}>
Unexecuted instantiation: <image::color::Rgb<u8> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>, image::color::Rgb<u8>, u8>::{closure#0}>
Unexecuted instantiation: <image::color::Rgb<u16> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>, image::color::Rgb<u16>, u16>::{closure#0}>
Unexecuted instantiation: <image::color::Luma<f32> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::Luma<f32>, alloc::vec::Vec<f32>>, image::color::Luma<f32>, f32>::{closure#0}>
Unexecuted instantiation: <image::color::Luma<u8> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>, image::color::Luma<u8>, u8>::{closure#0}>
Unexecuted instantiation: <image::color::Luma<u16> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>, image::color::Luma<u16>, u16>::{closure#0}>
Unexecuted instantiation: <image::color::Rgba<f32> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>, image::color::Rgba<f32>, f32>::{closure#0}>
Unexecuted instantiation: <image::color::Rgba<u8> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>, image::color::Rgba<u8>, u8>::{closure#0}>
Unexecuted instantiation: <image::color::Rgba<u16> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>, image::color::Rgba<u16>, u16>::{closure#0}>
Unexecuted instantiation: <image::color::LumaA<f32> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::LumaA<f32>, alloc::vec::Vec<f32>>, image::color::LumaA<f32>, f32>::{closure#0}>
Unexecuted instantiation: <image::color::LumaA<u8> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>, image::color::LumaA<u8>, u8>::{closure#0}>
Unexecuted instantiation: <image::color::LumaA<u16> as image::traits::Pixel>::map2::<image::imageops::sample::unsharpen<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>, image::color::LumaA<u16>, u16>::{closure#0}>
569
570
    /// Apply the function ```f``` to each channel of this pixel and
571
    /// ```other``` pairwise. Works in-place.
572
    fn apply2<F>(&mut self, other: &Self, f: F)
573
    where
574
        F: FnMut(Self::Subpixel, Self::Subpixel) -> Self::Subpixel;
575
576
    /// Invert this pixel
577
    fn invert(&mut self);
578
579
    /// Blend the color of a given pixel into ourself, taking into account alpha channels
580
    fn blend(&mut self, other: &Self);
581
}
582
583
/// Private module for supertraits of sealed traits.
584
mod seals {
585
    pub trait EncodableLayout {}
586
587
    impl EncodableLayout for [u8] {}
588
    impl EncodableLayout for [u16] {}
589
    impl EncodableLayout for [f32] {}
590
}