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
#[allow(unused)]
use crate::{buffer, Document, Error, Result};
#[cfg(feature = "import")]
#[cfg_attr(docsrs, doc(cfg(feature = "import")))]
use image_crate::DynamicImage;
/// Format of image pixel data.
#[cfg(feature = "import")]
#[cfg_attr(docsrs, doc(cfg(feature = "import")))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Format {
/// Red only.
R8,
/// Red, green.
R8G8,
/// Red, green, blue.
R8G8B8,
/// Red, green, blue, alpha.
R8G8B8A8,
/// Red only (16 bits).
R16,
/// Red, green (16 bits).
R16G16,
/// Red, green, blue (16 bits).
R16G16B16,
/// Red, green, blue, alpha (16 bits).
R16G16B16A16,
/// Red, green, blue (32 bits float)
R32G32B32FLOAT,
/// Red, green, blue, alpha (32 bits float)
R32G32B32A32FLOAT,
}
/// Describes an image data source.
#[derive(Clone, Debug)]
pub enum Source<'a> {
/// Image data is contained in a buffer view.
View {
/// The buffer view containing the encoded image data.
view: buffer::View<'a>,
/// The image data MIME type.
mime_type: &'a str,
},
/// Image data is contained in an external data source.
Uri {
/// The URI of the external data source.
uri: &'a str,
/// The image data MIME type, if provided.
mime_type: Option<&'a str>,
},
}
/// Image data used to create a texture.
#[derive(Clone, Debug)]
pub struct Image<'a> {
/// The parent `Document` struct.
document: &'a Document,
/// The corresponding JSON index.
index: usize,
/// The corresponding JSON struct.
json: &'a json::image::Image,
}
/// Image data belonging to an imported glTF asset.
#[cfg(feature = "import")]
#[cfg_attr(docsrs, doc(cfg(feature = "import")))]
#[derive(Clone, Debug)]
pub struct Data {
/// The image pixel data (8 bits per channel).
pub pixels: Vec<u8>,
/// The image pixel data format.
pub format: Format,
/// The image width in pixels.
pub width: u32,
/// The image height in pixels.
pub height: u32,
}
impl<'a> Image<'a> {
/// Constructs an `Image` from owned data.
pub(crate) fn new(document: &'a Document, index: usize, json: &'a json::image::Image) -> Self {
Self {
document,
index,
json,
}
}
/// Returns the internal JSON index.
pub fn index(&self) -> usize {
self.index
}
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(docsrs, doc(cfg(feature = "names")))]
pub fn name(&self) -> Option<&'a str> {
self.json.name.as_deref()
}
/// Returns the image data source.
pub fn source(&self) -> Source<'a> {
if let Some(index) = self.json.buffer_view.as_ref() {
let view = self.document.views().nth(index.value()).unwrap();
let mime_type = self.json.mime_type.as_ref().map(|x| x.0.as_str()).unwrap();
Source::View { view, mime_type }
} else {
let uri = self.json.uri.as_ref().unwrap();
let mime_type = self.json.mime_type.as_ref().map(|x| x.0.as_str());
Source::Uri { uri, mime_type }
}
}
/// Optional application specific data.
pub fn extras(&self) -> &'a json::Extras {
&self.json.extras
}
}
#[cfg(feature = "import")]
impl Data {
/// Note: We don't implement `From<DynamicImage>` since we don't want
/// to expose such functionality to the user.
pub(crate) fn new(image: DynamicImage) -> Result<Self> {
use image_crate::GenericImageView;
let format = match image {
DynamicImage::ImageLuma8(_) => Format::R8,
DynamicImage::ImageLumaA8(_) => Format::R8G8,
DynamicImage::ImageRgb8(_) => Format::R8G8B8,
DynamicImage::ImageRgba8(_) => Format::R8G8B8A8,
DynamicImage::ImageLuma16(_) => Format::R16,
DynamicImage::ImageLumaA16(_) => Format::R16G16,
DynamicImage::ImageRgb16(_) => Format::R16G16B16,
DynamicImage::ImageRgba16(_) => Format::R16G16B16A16,
DynamicImage::ImageRgb32F(_) => Format::R32G32B32FLOAT,
DynamicImage::ImageRgba32F(_) => Format::R32G32B32A32FLOAT,
image => return Err(Error::UnsupportedImageFormat(image)),
};
let (width, height) = image.dimensions();
let pixels = image.into_bytes();
Ok(Data {
format,
width,
height,
pixels,
})
}
}