native_windows_gui/resources/
image_decoder.rs1use winapi::um::wincodec::{IWICImagingFactory, IWICBitmapDecoder, IWICBitmapSource, WICPixelFormatGUID};
2use winapi::shared::winerror::S_OK;
3use crate::win32::image_decoder as img;
4use crate::{NwgError, Bitmap};
5use std::{ptr, mem};
6
7
8pub struct ImageDecoder {
36 pub factory: *mut IWICImagingFactory,
37}
38
39impl ImageDecoder {
40 pub fn new() -> Result<ImageDecoder, NwgError> {
41 let factory = unsafe { img::create_image_factory() }?;
42 Ok(ImageDecoder { factory })
43 }
44
45 pub fn builder() -> ImageDecoderBuilder {
46 ImageDecoderBuilder {
47 }
48 }
49
50 pub fn from_filename<'a>(&self, path: &'a str) -> Result<ImageSource, NwgError> {
60 if self.factory.is_null() {
61 panic!("ImageDecoder is not yet bound to a winapi object");
62 }
63
64 let decoder = unsafe { img::create_decoder_from_file(&*self.factory, path) }?;
65
66 Ok(ImageSource { decoder })
67 }
68
69 pub fn from_stream(&self, stream: &[u8]) -> Result<ImageSource, NwgError> {
79 if self.factory.is_null() {
80 panic!("ImageDecoder is not yet bound to a winapi object");
81 }
82
83 let decoder = unsafe { img::create_decoder_from_stream(&*self.factory, stream) }?;
84
85 Ok(ImageSource { decoder })
86 }
87
88 pub fn resize_image(&self, image: &ImageData, new_size: [u32;2]) -> Result<ImageData, NwgError> {
92 unsafe { img::resize_bitmap(&*self.factory, image, new_size) }
93 }
94
95}
96
97
98pub struct ImageSource {
102 pub decoder: *mut IWICBitmapDecoder,
103}
104
105impl ImageSource {
106
107 pub fn frame_count(&self) -> u32 {
112 let mut frame_count = 0;
113 unsafe { (&*self.decoder).GetFrameCount(&mut frame_count); }
114 frame_count
115 }
116
117 pub fn frame(&self, index: u32) -> Result<ImageData, NwgError> {
121 let mut bitmap = ptr::null_mut();
122 let hr = unsafe { (&*self.decoder).GetFrame(index, &mut bitmap) };
123 match hr {
124 S_OK => Ok(ImageData { frame: bitmap as *mut IWICBitmapSource }),
125 err => Err(NwgError::image_decoder(err, "Could not read image frame"))
126 }
127 }
128
129 pub fn container_format(&self) -> ContainerFormat {
134 use ContainerFormat::*;
135 let mut container = unsafe { mem::zeroed() };
136 unsafe { (&*self.decoder).GetContainerFormat(&mut container) };
137
138 match container.Data1 {
140 0xf3ff6d0d => Adng,
141 0xaf1d87e => Bmp,
142 0x1b7cfaf4 => Png,
143 0xa3a860c4 => Ico,
144 0x19e4a5aa => Jpeg,
145 0x163bcc30 => Tiff,
146 0x1f8a5601 => Gif,
147 0x57a37caa => Wmp,
148 _ => Unknown
149 }
150
151 }
152
153}
154
155
156pub struct ImageData {
160 pub frame: *mut IWICBitmapSource
161}
162
163impl ImageData {
164
165 pub fn resolution(&self) -> (f64, f64) {
167 let (mut rx, mut ry) = (0.0, 0.0);
168 unsafe { (&*self.frame).GetResolution(&mut rx, &mut ry) };
169 (rx, ry)
170 }
171
172 pub fn size(&self) -> (u32, u32) {
174 let (mut sx, mut sy) = (0, 0);
175 unsafe { (&*self.frame).GetSize(&mut sx, &mut sy) };
176 (sx, sy)
177 }
178
179 pub fn pixel_format(&self) -> WICPixelFormatGUID {
184 let mut fmt = unsafe { mem::zeroed() };
185 unsafe { (&*self.frame).GetPixelFormat(&mut fmt) };
186 fmt
187 }
188
189 pub fn pixels(&self, pixel_size: u32) -> Result<Vec<u8>, NwgError> {
199 let (w, h) = self.size();
200 let scanline = w * pixel_size;
201 let buffer_size = (w * h * pixel_size) as usize;
202 let mut buffer: Vec<u8> = Vec::with_capacity(buffer_size);
203
204 let hr = unsafe {
205 buffer.set_len(buffer_size);
206 (&*self.frame).CopyPixels(ptr::null(), scanline, buffer_size as u32, buffer.as_mut_ptr())
207 };
208
209 match hr {
210 S_OK => Ok(buffer),
211 err => Err(NwgError::image_decoder(err, "Could not read image pixels"))
212 }
213 }
214
215 pub fn region_pixels(&self, offset: [i32;2], size: [i32;2], pixel_size: u32) -> Result<Vec<u8>, NwgError> {
227 use winapi::um::wincodec::WICRect;
228
229 let [x, y] = offset;
230 let [w, h] = size;
231 let scanline = (w as u32) * pixel_size;
232 let buffer_size = (scanline * (h as u32)) as usize;
233 let mut buffer: Vec<u8> = Vec::with_capacity(buffer_size);
234
235 let region = WICRect { X: x, Y: y, Width: w, Height: h };
236
237 let hr = unsafe {
238 buffer.set_len(buffer_size);
239 (&*self.frame).CopyPixels(®ion, scanline, buffer_size as u32, buffer.as_mut_ptr())
240 };
241
242 match hr {
243 S_OK => Ok(buffer),
244 err => Err(NwgError::image_decoder(err, "Could not read image pixels"))
245 }
246 }
247
248 pub fn as_bitmap(&self) -> Result<Bitmap, NwgError> {
253 unsafe { img::create_bitmap_from_wic(self) }
254 }
255
256}
257
258#[derive(Copy, Clone, Debug, PartialEq, Eq)]
260pub enum ContainerFormat {
261 Unknown,
262 Adng,
263 Bmp,
264 Png,
265 Ico,
266 Jpeg,
267 Tiff,
268 Gif,
269 Wmp,
270}
271
272impl Default for ImageDecoder {
277 fn default() -> ImageDecoder {
278 ImageDecoder {
279 factory: ptr::null_mut()
280 }
281 }
282}
283
284impl Drop for ImageDecoder {
285 fn drop(&mut self) {
286 if !self.factory.is_null() {
287 unsafe { (&*self.factory).Release(); }
288 }
289 }
290}
291
292impl Drop for ImageSource {
293 fn drop(&mut self) {
294 unsafe { (&*self.decoder).Release(); }
295 }
296}
297
298impl Drop for ImageData {
299 fn drop(&mut self) {
300 unsafe { (&*self.frame).Release(); }
301 }
302}
303
304
305pub struct ImageDecoderBuilder {
309}
310
311impl ImageDecoderBuilder {
312 pub fn build(self, out: &mut ImageDecoder) -> Result<(), NwgError> {
313 let factory = unsafe { img::create_image_factory() }?;
314 *out = ImageDecoder { factory };
315 Ok(())
316 }
317}