Serialize images as base64 by rounding channels from floats to u8 (#1120)

Serialise images as base64
This commit is contained in:
0HyperCube 2023-04-13 20:03:25 +01:00 committed by Keavon Chambers
parent 79dade24e5
commit 0e97f352e9
12 changed files with 117 additions and 100 deletions

View file

@ -12,7 +12,7 @@ license = "MIT OR Apache-2.0"
std = ["dyn-any", "dyn-any/std", "alloc", "glam/std", "specta"]
default = ["async", "serde", "kurbo", "log", "std"]
log = ["dep:log"]
serde = ["dep:serde", "glam/serde", "bezier-rs/serde"]
serde = ["dep:serde", "glam/serde", "bezier-rs/serde", "base64"]
gpu = ["spirv-std", "bytemuck", "glam/bytemuck", "dyn-any", "glam/libm"]
async = ["async-trait", "alloc"]
nightly = []
@ -43,6 +43,7 @@ glam = { version = "^0.22", default-features = false, features = [
"scalar-math",
] }
node-macro = { path = "../node-macro" }
base64 = { version = "0.13", optional = true }
specta.workspace = true
specta.optional = true
once_cell = { version = "1.17.0", default-features = false, optional = true }

View file

@ -330,11 +330,47 @@ mod image {
use dyn_any::{DynAny, StaticType};
use glam::{DAffine2, DVec2};
#[cfg(feature = "serde")]
mod base64_serde {
//! Basic wrapper for [`serde`] for [`base64`] encoding
use crate::Color;
use serde::{Deserialize, Deserializer, Serializer};
pub fn as_base64<S>(key: &[Color], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let u8_data = key
.iter()
.flat_map(|color| [color.r(), color.g(), color.b(), color.a()].into_iter().map(|channel| (channel * 255.).clamp(0., 255.) as u8))
.collect::<Vec<_>>();
serializer.serialize_str(&base64::encode(u8_data))
}
pub fn from_base64<'a, D>(deserializer: D) -> Result<Vec<Color>, D::Error>
where
D: Deserializer<'a>,
{
use serde::de::Error;
let color_from_chunk = |chunk: &[u8]| Color::from_rgba8(chunk[0], chunk[1], chunk[2], chunk[3]);
let colors_from_bytes = |bytes: Vec<u8>| bytes.chunks_exact(4).map(color_from_chunk).collect();
String::deserialize(deserializer)
.and_then(|string| base64::decode(string).map_err(|err| Error::custom(err.to_string())))
.map(colors_from_bytes)
.map_err(serde::de::Error::custom)
}
}
#[derive(Clone, Debug, PartialEq, DynAny, Default, specta::Type)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Image {
pub width: u32,
pub height: u32,
#[cfg_attr(feature = "serde", serde(serialize_with = "base64_serde::as_base64", deserialize_with = "base64_serde::from_base64"))]
pub data: Vec<Color>,
}