aseprite/
tiny_skia_conv.rs1use tiny_skia::Pixmap;
2
3use crate::error::AsepriteError;
4use crate::types::Pixels;
5
6fn premultiplied_to_straight(data: &mut [u8]) {
8 for chunk in data.chunks_exact_mut(4) {
9 let a = chunk[3] as u16;
10 if a == 0 {
11 chunk[0] = 0;
12 chunk[1] = 0;
13 chunk[2] = 0;
14 } else if a < 255 {
15 chunk[0] = ((chunk[0] as u16 * 255 + a / 2) / a).min(255) as u8;
16 chunk[1] = ((chunk[1] as u16 * 255 + a / 2) / a).min(255) as u8;
17 chunk[2] = ((chunk[2] as u16 * 255 + a / 2) / a).min(255) as u8;
18 }
19 }
20}
21
22fn straight_to_premultiplied(data: &mut [u8]) {
24 for chunk in data.chunks_exact_mut(4) {
25 let a = chunk[3] as u16;
26 if a == 0 {
27 chunk[0] = 0;
28 chunk[1] = 0;
29 chunk[2] = 0;
30 } else if a < 255 {
31 chunk[0] = ((chunk[0] as u16 * a + 127) / 255) as u8;
32 chunk[1] = ((chunk[1] as u16 * a + 127) / 255) as u8;
33 chunk[2] = ((chunk[2] as u16 * a + 127) / 255) as u8;
34 }
35 }
36}
37
38impl From<Pixmap> for Pixels {
40 fn from(pixmap: Pixmap) -> Self {
41 let width = pixmap.width() as u16;
42 let height = pixmap.height() as u16;
43 let mut data = pixmap.take();
44 premultiplied_to_straight(&mut data);
45 Self {
46 data,
47 width,
48 height,
49 }
50 }
51}
52
53impl From<&Pixmap> for Pixels {
55 fn from(pixmap: &Pixmap) -> Self {
56 let width = pixmap.width() as u16;
57 let height = pixmap.height() as u16;
58 let mut data = pixmap.data().to_vec();
59 premultiplied_to_straight(&mut data);
60 Self {
61 data,
62 width,
63 height,
64 }
65 }
66}
67
68impl TryFrom<Pixels> for Pixmap {
72 type Error = AsepriteError;
73
74 fn try_from(pixels: Pixels) -> Result<Self, Self::Error> {
75 let mut data = pixels.data;
76 straight_to_premultiplied(&mut data);
77 Pixmap::from_vec(
78 data,
79 tiny_skia::IntSize::from_wh(pixels.width as u32, pixels.height as u32).ok_or(
80 AsepriteError::PixelSizeMismatch {
81 expected: pixels.width as usize * pixels.height as usize * 4,
82 actual: 0,
83 },
84 )?,
85 )
86 .ok_or(AsepriteError::PixelSizeMismatch {
87 expected: pixels.width as usize * pixels.height as usize * 4,
88 actual: 0,
89 })
90 }
91}