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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
use core::fmt; use std::{ borrow::Cow, ffi::{CStr, CString}, }; use ffi::BLImageCodecFeatures::*; use crate::{ array::Array, error::{errcode_to_result, Result}, variant::WrappedBlCore, }; bl_enum! { pub enum ImageCodecFeatures { Read = BL_IMAGE_CODEC_FEATURE_READ, Write = BL_IMAGE_CODEC_FEATURE_WRITE, Lossless = BL_IMAGE_CODEC_FEATURE_LOSSLESS, Lossy = BL_IMAGE_CODEC_FEATURE_LOSSY, MultiFrame = BL_IMAGE_CODEC_FEATURE_MULTI_FRAME, Iptc = BL_IMAGE_CODEC_FEATURE_IPTC, Exif = BL_IMAGE_CODEC_FEATURE_EXIF, Xmp = BL_IMAGE_CODEC_FEATURE_XMP, } Default => Read } #[repr(transparent)] pub struct ImageCodec { core: ffi::BLImageCodecCore, } unsafe impl WrappedBlCore for ImageCodec { type Core = ffi::BLImageCodecCore; const IMPL_TYPE_INDEX: usize = ffi::BLImplType::BL_IMPL_TYPE_IMAGE_CODEC as usize; } impl ImageCodec { pub fn find_by_name(codecs: &Array<ImageCodec>, name: &str) -> Result<Self> { unsafe { let mut this = ImageCodec { core: *Self::none(), }; let name = CString::new(name).expect("Failed to create CString"); errcode_to_result(ffi::blImageCodecFindByName( this.core_mut(), codecs.core(), name.as_ptr(), )) .map(|_| this) } } #[inline] pub fn find_by_data(codecs: &Array<ImageCodec>, data: &[u8]) -> Result<Self> { unsafe { let mut this = ImageCodec { core: *Self::none(), }; errcode_to_result(ffi::blImageCodecFindByData( this.core_mut(), codecs.core(), data.as_ptr() as *const _, data.len(), )) .map(|_| this) } } #[inline] pub fn create_decoder(&mut self) -> Result<ImageDecoder> { unsafe { let mut decoder = ImageDecoder { core: *ImageDecoder::none(), }; errcode_to_result(ffi::blImageCodecCreateDecoder( self.core_mut(), decoder.core_mut(), )) .map(|_| decoder) } } #[inline] pub fn create_encoder(&mut self) -> Result<ImageEncoder> { unsafe { let mut encoder = ImageEncoder { core: *ImageEncoder::none(), }; errcode_to_result(ffi::blImageCodecCreateEncoder( self.core_mut(), encoder.core_mut(), )) .map(|_| encoder) } } #[inline] pub fn inspect_data<R: AsRef<[u8]>>(&self, data: R) -> u32 { unsafe { ffi::blImageCodecInspectData( self.core(), data.as_ref().as_ptr() as *const _, data.as_ref().len(), ) } } #[inline] pub fn built_in_codecs() -> &'static Array<ImageCodec> { unsafe { &*(ffi::blImageCodecBuiltInCodecs() as *const _ as *const _) } } #[inline] pub fn name(&self) -> Cow<'_, str> { unsafe { CStr::from_ptr(self.impl_().name).to_string_lossy() } } #[inline] pub fn vendor(&self) -> Cow<'_, str> { unsafe { CStr::from_ptr(self.impl_().vendor).to_string_lossy() } } #[inline] pub fn mime_type(&self) -> Cow<'_, str> { unsafe { CStr::from_ptr(self.impl_().mimeType).to_string_lossy() } } pub fn extensions(&self) -> impl Iterator<Item = &str> { unsafe { CStr::from_ptr(self.impl_().extensions) .to_str() .unwrap_or_default() .split('|') } } #[inline] pub fn features(&self) -> ImageCodecFeatures { (self.impl_().features as u32).into() } } impl fmt::Debug for ImageCodec { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ImageCodec") .field("name", &self.name()) .field("vendor", &self.vendor()) .field("mime_type", &self.mime_type()) .finish() } } impl PartialEq for ImageCodec { #[inline] fn eq(&self, other: &Self) -> bool { self.impl_() as *const _ == other.impl_() as *const _ } } impl Drop for ImageCodec { fn drop(&mut self) { unsafe { ffi::blImageCodecReset(&mut self.core) }; } } #[repr(transparent)] pub struct ImageEncoder { core: ffi::BLImageEncoderCore, } unsafe impl WrappedBlCore for ImageEncoder { type Core = ffi::BLImageEncoderCore; const IMPL_TYPE_INDEX: usize = ffi::BLImplType::BL_IMPL_TYPE_IMAGE_ENCODER as usize; } impl ImageEncoder { #[inline] pub fn restart(&mut self) -> Result<()> { unsafe { errcode_to_result(ffi::blImageEncoderRestart(self.core_mut())) } } } impl PartialEq for ImageEncoder { #[inline] fn eq(&self, other: &Self) -> bool { self.impl_() as *const _ == other.impl_() as *const _ } } impl Drop for ImageEncoder { fn drop(&mut self) { unsafe { ffi::blImageEncoderReset(&mut self.core) }; } } #[repr(transparent)] pub struct ImageDecoder { core: ffi::BLImageDecoderCore, } unsafe impl WrappedBlCore for ImageDecoder { type Core = ffi::BLImageDecoderCore; const IMPL_TYPE_INDEX: usize = ffi::BLImplType::BL_IMPL_TYPE_IMAGE_DECODER as usize; } impl ImageDecoder { #[inline] pub fn restart(&mut self) -> Result<()> { unsafe { errcode_to_result(ffi::blImageDecoderRestart(self.core_mut())) } } } impl PartialEq for ImageDecoder { #[inline] fn eq(&self, other: &Self) -> bool { self.impl_() as *const _ == other.impl_() as *const _ } } impl Drop for ImageDecoder { fn drop(&mut self) { unsafe { ffi::blImageDecoderReset(&mut self.core) }; } }