1use crate::*;
2use std::path::Path;
3use windows::Win32::{Foundation::GENERIC_READ, Graphics::Direct2D::*, Graphics::Imaging::*};
4use windows::core::{GUID, HSTRING, Interface};
5
6#[derive(Clone, Copy, PartialEq, Eq, Debug)]
7#[repr(i32)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub enum Interpolation {
10 NearestNeighbor = D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR.0,
11 Linear = D2D1_INTERPOLATION_MODE_LINEAR.0,
12 Cubic = D2D1_INTERPOLATION_MODE_CUBIC.0,
13 MultiSampleLinear = D2D1_INTERPOLATION_MODE_DEFINITION_MULTI_SAMPLE_LINEAR.0,
14 Anisotropic = D2D1_INTERPOLATION_MODE_ANISOTROPIC.0,
15 HighQualityCubic = D2D1_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC.0,
16}
17
18impl From<Interpolation> for D2D1_INTERPOLATION_MODE {
19 fn from(value: Interpolation) -> Self {
20 Self(value as i32)
21 }
22}
23
24#[derive(Clone, PartialEq, Eq, Debug)]
25pub struct Image(ID2D1Bitmap1);
26
27impl Image {
28 pub fn from_file<T>(ctx: &Context<T>, path: impl AsRef<Path>) -> Result<Self>
29 where
30 T: Backend,
31 {
32 let factory = &ctx.wic_imaging_factory;
33 unsafe {
34 let decoder = factory.CreateDecoderFromFilename(
35 &HSTRING::from(path.as_ref().to_string_lossy().as_ref()),
36 Some(&GUID::zeroed()),
37 GENERIC_READ,
38 WICDecodeMetadataCacheOnDemand,
39 )?;
40 let frame = decoder.GetFrame(0)?;
41 let converter = factory.CreateFormatConverter()?;
42 converter.Initialize(
43 &frame,
44 &GUID_WICPixelFormat32bppPBGRA,
45 WICBitmapDitherTypeNone,
46 None,
47 1.0,
48 WICBitmapPaletteTypeMedianCut,
49 )?;
50 let bitmap = ctx
51 .d2d1_device_context
52 .CreateBitmapFromWicBitmap(&converter, None)?
53 .cast()?;
54 Ok(Self(bitmap))
55 }
56 }
57
58 #[inline]
59 pub fn size(&self) -> Size<f32> {
60 unsafe { self.0.GetSize().into() }
61 }
62
63 #[inline]
64 pub fn pixel_size(&self) -> Size<u32> {
65 unsafe { self.0.GetPixelSize().into() }
66 }
67
68 pub(crate) fn handle(&self) -> &ID2D1Bitmap1 {
69 &self.0
70 }
71}