native_windows_gui2/resources/
image_decoder.rs1use crate::win32::image_decoder as img;
2use crate::{Bitmap, NwgError};
3use std::{mem, ptr};
4use winapi::shared::winerror::S_OK;
5use winapi::um::wincodec::{
6 IWICBitmapDecoder, IWICBitmapSource, IWICImagingFactory, WICPixelFormatGUID,
7};
8
9pub struct ImageDecoder {
37 pub factory: *mut IWICImagingFactory,
38}
39
40impl ImageDecoder {
41 pub fn new() -> Result<ImageDecoder, NwgError> {
42 let factory = img::create_image_factory()?;
43 Ok(ImageDecoder { factory })
44 }
45
46 pub fn builder() -> ImageDecoderBuilder {
47 ImageDecoderBuilder {}
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(
92 &self,
93 image: &ImageData,
94 new_size: [u32; 2],
95 ) -> Result<ImageData, NwgError> {
96 unsafe { img::resize_bitmap(&*self.factory, image, new_size) }
97 }
98}
99
100pub struct ImageSource {
104 pub decoder: *mut IWICBitmapDecoder,
105}
106
107impl ImageSource {
108 pub fn frame_count(&self) -> u32 {
113 let mut frame_count = 0;
114 unsafe {
115 (&*self.decoder).GetFrameCount(&mut frame_count);
116 }
117 frame_count
118 }
119
120 pub fn frame(&self, index: u32) -> Result<ImageData, NwgError> {
124 let mut bitmap = ptr::null_mut();
125 let hr = unsafe { (&*self.decoder).GetFrame(index, &mut bitmap) };
126 match hr {
127 S_OK => Ok(ImageData {
128 frame: bitmap as *mut IWICBitmapSource,
129 }),
130 err => Err(NwgError::image_decoder(err, "Could not read image frame")),
131 }
132 }
133
134 pub fn container_format(&self) -> ContainerFormat {
139 use ContainerFormat::*;
140 let mut container = unsafe { mem::zeroed() };
141 unsafe { (&*self.decoder).GetContainerFormat(&mut container) };
142
143 match container.Data1 {
145 0xf3ff6d0d => Adng,
146 0xaf1d87e => Bmp,
147 0x1b7cfaf4 => Png,
148 0xa3a860c4 => Ico,
149 0x19e4a5aa => Jpeg,
150 0x163bcc30 => Tiff,
151 0x1f8a5601 => Gif,
152 0x57a37caa => Wmp,
153 _ => Unknown,
154 }
155 }
156}
157
158pub struct ImageData {
162 pub frame: *mut IWICBitmapSource,
163}
164
165impl ImageData {
166 pub fn resolution(&self) -> (f64, f64) {
168 let (mut rx, mut ry) = (0.0, 0.0);
169 unsafe { (&*self.frame).GetResolution(&mut rx, &mut ry) };
170 (rx, ry)
171 }
172
173 pub fn size(&self) -> (u32, u32) {
175 let (mut sx, mut sy) = (0, 0);
176 unsafe { (&*self.frame).GetSize(&mut sx, &mut sy) };
177 (sx, sy)
178 }
179
180 pub fn pixel_format(&self) -> WICPixelFormatGUID {
185 let mut fmt = unsafe { mem::zeroed() };
186 unsafe { (&*self.frame).GetPixelFormat(&mut fmt) };
187 fmt
188 }
189
190 pub fn pixels(&self, pixel_size: u32) -> Result<Vec<u8>, NwgError> {
200 let (w, h) = self.size();
201 let scanline = w * pixel_size;
202 let buffer_size = (w * h * pixel_size) as usize;
203 let mut buffer: Vec<u8> = Vec::with_capacity(buffer_size);
204
205 let hr = unsafe {
206 buffer.set_len(buffer_size);
207 (&*self.frame).CopyPixels(
208 ptr::null(),
209 scanline,
210 buffer_size as u32,
211 buffer.as_mut_ptr(),
212 )
213 };
214
215 match hr {
216 S_OK => Ok(buffer),
217 err => Err(NwgError::image_decoder(err, "Could not read image pixels")),
218 }
219 }
220
221 pub fn region_pixels(
233 &self,
234 offset: [i32; 2],
235 size: [i32; 2],
236 pixel_size: u32,
237 ) -> Result<Vec<u8>, NwgError> {
238 use winapi::um::wincodec::WICRect;
239
240 let [x, y] = offset;
241 let [w, h] = size;
242 let scanline = (w as u32) * pixel_size;
243 let buffer_size = (scanline * (h as u32)) as usize;
244 let mut buffer: Vec<u8> = Vec::with_capacity(buffer_size);
245
246 let region = WICRect {
247 X: x,
248 Y: y,
249 Width: w,
250 Height: h,
251 };
252
253 let hr = unsafe {
254 buffer.set_len(buffer_size);
255 (&*self.frame).CopyPixels(®ion, scanline, buffer_size as u32, buffer.as_mut_ptr())
256 };
257
258 match hr {
259 S_OK => Ok(buffer),
260 err => Err(NwgError::image_decoder(err, "Could not read image pixels")),
261 }
262 }
263
264 pub fn as_bitmap(&self) -> Result<Bitmap, NwgError> {
269 img::create_bitmap_from_wic(self)
270 }
271}
272
273#[derive(Copy, Clone, Debug, PartialEq, Eq)]
275pub enum ContainerFormat {
276 Unknown,
277 Adng,
278 Bmp,
279 Png,
280 Ico,
281 Jpeg,
282 Tiff,
283 Gif,
284 Wmp,
285}
286
287impl Default for ImageDecoder {
292 fn default() -> ImageDecoder {
293 ImageDecoder {
294 factory: ptr::null_mut(),
295 }
296 }
297}
298
299impl Drop for ImageDecoder {
300 fn drop(&mut self) {
301 if !self.factory.is_null() {
302 unsafe {
303 (&*self.factory).Release();
304 }
305 }
306 }
307}
308
309impl Drop for ImageSource {
310 fn drop(&mut self) {
311 unsafe {
312 (&*self.decoder).Release();
313 }
314 }
315}
316
317impl Drop for ImageData {
318 fn drop(&mut self) {
319 unsafe {
320 (&*self.frame).Release();
321 }
322 }
323}
324
325pub struct ImageDecoderBuilder {}
329
330impl ImageDecoderBuilder {
331 pub fn build(self, out: &mut ImageDecoder) -> Result<(), NwgError> {
332 let factory = img::create_image_factory()?;
333 *out = ImageDecoder { factory };
334 Ok(())
335 }
336}