1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
/*
* Copyright (c) 2023.
*
* This software is free software;
*
* You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
*/
//! Image bit depth, information and manipulations
/// The image bit depth.
///
/// The library successfully supports depths up to
/// 16 bits, as the underlying storage is usually a `u16`.
///
/// This allows us to comfortably support a wide variety of images
/// e.g 10 bit av1, 16 bit png and ppm.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum BitDepth {
/// U8 bit depth.
///
/// Images with such bit depth use [`u8`] to store
/// pixels and use the whole range from 0-255.
///
/// It is currently the smallest supported bit depth
/// by the library.
///
/// For images with bit depths lower than this, they will be scaled
/// to this bit depth
Eight,
/// U16 bit depth
///
/// Images with such bit depths use [`u16`] to store values and use the whole range
/// i.e 0-65535
///
/// Data is stored and processed in native endian.
Sixteen,
/// Floating point 32 bit data, range is 0.0 to 1.0
///
/// Uses f32 to store data
Float32,
/// Bit depth information is unknown
Unknown
}
/// The underlying bit representation of the image
///
/// This represents the minimum rust type that
/// can be used to represent image data, required
/// by `Channel` struct in zune-image
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum BitType {
/// Images represented using a [`u8`] as their
/// underlying pixel storage
U8,
/// Images represented using a [`u16`] as their
/// underlying pixel storage.
U16,
/// Images represented using a [`f32`] as their
/// underlying pixel storage
F32
}
impl BitType {
/// Return the equivalent of the image bit type's depth
pub fn to_depth(self) -> BitDepth {
match self {
BitType::U8 => BitDepth::Eight,
BitType::U16 => BitDepth::Sixteen,
BitType::F32 => BitDepth::Float32
}
}
}
impl Default for BitDepth {
fn default() -> Self {
Self::Unknown
}
}
impl BitDepth {
/// Get the max value supported by the bit depth
///
/// During conversion from one bit depth to another
///
/// larger values should be clamped to this bit depth
#[rustfmt::skip]
#[allow(clippy::zero_prefixed_literal)]
pub const fn max_value(self) -> u16
{
match self
{
Self::Eight => (1 << 08) - 1,
Self::Sixteen => u16::MAX,
Self::Float32 => 1,
Self::Unknown => 0,
}
}
/// Return the minimum number of bits that can be used to represent
/// each pixel in the image
///
/// All bit depths below 8 return a bit type of `BitType::U8`.
/// and all those above 8 and below 16 return a bit type of `BitType::SixTeen`
///
/// # Returns
/// An enum whose variants represent the minimum size for an unsigned integer
/// which can store the image pixels without overflow
///
/// # Example
///
/// ```
/// use zune_core::bit_depth::{BitDepth, BitType};
/// assert_eq!(BitDepth::Eight.bit_type(),BitType::U8);
///
/// assert_eq!(BitDepth::Sixteen.bit_type(),BitType::U16);
/// ```
///
/// See also [size_of](BitDepth::size_of)
pub const fn bit_type(self) -> BitType {
match self {
Self::Eight => BitType::U8,
Self::Sixteen => BitType::U16,
Self::Float32 => BitType::F32,
Self::Unknown => panic!("Unknown bit type")
}
}
/// Get the number of bytes needed to store a specific bit depth
///
///
/// # Example
/// For images less than or equal to 8 bits(1 byte), we can use a [`u8`] to store
/// the pixels, and a size_of [`u8`] is 1
///
/// For images greater than 8 bits and less than 16 bits(2 bytes), we can use a [`u16`] to
/// store the pixels, a size_of [`u16`] is 2.
/// ```
/// use zune_core::bit_depth::BitDepth;
/// let depth = BitDepth::Sixteen;
/// // greater 12 bits is greater than 8 and less than 16
/// assert_eq!(depth.size_of(),2);
/// ```
pub const fn size_of(self) -> usize {
match self {
Self::Eight => core::mem::size_of::<u8>(),
Self::Sixteen => core::mem::size_of::<u16>(),
Self::Float32 => core::mem::size_of::<f32>(),
Self::Unknown => panic!("Unknown bit type")
}
}
pub const fn bit_size(&self) -> usize {
self.size_of() * 8
}
}
/// Byte endianness of returned samples
/// this is useful when the decoder returns samples which span more
/// than one byte yet the type returned is `&[u8]`
///
/// This helps you interpret how those bytes should be reconstructed
/// to a higher order type
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ByteEndian {
/// Little Endian byte-order
LE,
/// Big Endian byte-order
BE
}