Instance tables refactor part 3: flatten ImageFrame<P> in lieu of Image<P> (#2256)
* Remove ImageFrame<T> by flattening it into Image<T> * Rename TextureFrame to ImageTexture * Fix tests
This commit is contained in:
parent
f1160e1ca6
commit
2f6c6e28f0
|
|
@ -28,7 +28,7 @@ use crate::node_graph_executor::NodeGraphExecutor;
|
|||
use bezier_rs::Subpath;
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::{NodeId, NodeInput, NodeNetwork, OldNodeNetwork};
|
||||
use graphene_core::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use graphene_core::raster::image::ImageFrameTable;
|
||||
use graphene_core::raster::BlendMode;
|
||||
use graphene_core::vector::style::ViewMode;
|
||||
use graphene_std::renderer::{ClickTarget, Quad};
|
||||
|
|
@ -818,7 +818,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
|
|||
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
|
||||
let layer = graph_modification_utils::new_image_layer(ImageFrameTable::new(ImageFrame { image }), layer_node_id, self.new_layer_parent(true), responses);
|
||||
let layer = graph_modification_utils::new_image_layer(ImageFrameTable::new(image), layer_node_id, self.new_layer_parent(true), responses);
|
||||
|
||||
if let Some(name) = name {
|
||||
responses.add(NodeGraphMessage::SetDisplayName {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use graphene_core::raster::{
|
|||
use graphene_core::text::Font;
|
||||
use graphene_core::vector::misc::CentroidType;
|
||||
use graphene_core::vector::style::{GradientType, LineCap, LineJoin};
|
||||
use graphene_std::application_io::TextureFrame;
|
||||
use graphene_std::application_io::TextureFrameTable;
|
||||
use graphene_std::transform::Footprint;
|
||||
use graphene_std::vector::misc::BooleanOperation;
|
||||
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops};
|
||||
|
|
@ -159,7 +159,7 @@ pub(crate) fn property_from_type(
|
|||
Some(x) if x == TypeId::of::<Curve>() => curves_widget(document_node, node_id, index, name, true),
|
||||
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(document_node, node_id, index, name, ColorInput::default().allow_none(false), true),
|
||||
Some(x) if x == TypeId::of::<VectorDataTable>() => vector_widget(document_node, node_id, index, name, true).into(),
|
||||
Some(x) if x == TypeId::of::<RasterFrame>() || x == TypeId::of::<ImageFrameTable<Color>>() || x == TypeId::of::<TextureFrame>() => {
|
||||
Some(x) if x == TypeId::of::<RasterFrame>() || x == TypeId::of::<ImageFrameTable<Color>>() || x == TypeId::of::<TextureFrameTable>() => {
|
||||
raster_widget(document_node, node_id, index, name, true).into()
|
||||
}
|
||||
Some(x) if x == TypeId::of::<GraphicGroupTable>() => group_widget(document_node, node_id, index, name, true).into(),
|
||||
|
|
|
|||
|
|
@ -6222,10 +6222,11 @@ impl PropertiesRow {
|
|||
fn migrate_output_names<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Vec<String>, D::Error> {
|
||||
use serde::Deserialize;
|
||||
|
||||
const REPLACEMENTS: [(&str, &str); 3] = [
|
||||
const REPLACEMENTS: [(&str, &str); 4] = [
|
||||
("VectorData", "Instances<VectorData>"),
|
||||
("GraphicGroup", "Instances<GraphicGroup>"),
|
||||
("ImageFrame", "Instances<ImageFrame>"),
|
||||
("ImageFrame", "Instances<Image>"),
|
||||
("Instances<ImageFrame>", "Instances<Image>"),
|
||||
];
|
||||
|
||||
let mut names = Vec::<String>::deserialize(deserializer)?;
|
||||
|
|
|
|||
|
|
@ -64,17 +64,18 @@ impl Size for web_sys::HtmlCanvasElement {
|
|||
}
|
||||
}
|
||||
|
||||
pub type TextureFrameTable = Instances<TextureFrame>;
|
||||
// TODO: Rename to ImageTextureTable
|
||||
pub type TextureFrameTable = Instances<ImageTexture>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TextureFrame {
|
||||
pub struct ImageTexture {
|
||||
#[cfg(feature = "wgpu")]
|
||||
pub texture: Arc<wgpu::Texture>,
|
||||
#[cfg(not(feature = "wgpu"))]
|
||||
pub texture: (),
|
||||
}
|
||||
|
||||
impl Hash for TextureFrame {
|
||||
impl Hash for ImageTexture {
|
||||
#[cfg(feature = "wgpu")]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.texture.hash(state);
|
||||
|
|
@ -83,18 +84,18 @@ impl Hash for TextureFrame {
|
|||
fn hash<H: Hasher>(&self, _state: &mut H) {}
|
||||
}
|
||||
|
||||
impl PartialEq for TextureFrame {
|
||||
impl PartialEq for ImageTexture {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.texture == other.texture
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl StaticType for TextureFrame {
|
||||
type Static = TextureFrame;
|
||||
unsafe impl StaticType for ImageTexture {
|
||||
type Static = ImageTexture;
|
||||
}
|
||||
|
||||
#[cfg(feature = "wgpu")]
|
||||
impl Size for TextureFrame {
|
||||
impl Size for ImageTexture {
|
||||
fn size(&self) -> UVec2 {
|
||||
UVec2::new(self.texture.width(), self.texture.height())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::application_io::{TextureFrame, TextureFrameTable};
|
||||
use crate::application_io::{ImageTexture, TextureFrameTable};
|
||||
use crate::instances::Instances;
|
||||
use crate::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use crate::raster::image::{Image, ImageFrameTable};
|
||||
use crate::raster::BlendMode;
|
||||
use crate::transform::{Transform, TransformMut};
|
||||
use crate::uuid::NodeId;
|
||||
|
|
@ -111,9 +111,9 @@ impl From<VectorDataTable> for GraphicGroupTable {
|
|||
Self::new(GraphicGroup::new(vec![GraphicElement::VectorData(vector_data)]))
|
||||
}
|
||||
}
|
||||
impl From<ImageFrame<Color>> for GraphicGroupTable {
|
||||
fn from(image_frame: ImageFrame<Color>) -> Self {
|
||||
Self::new(GraphicGroup::new(vec![GraphicElement::RasterFrame(RasterFrame::ImageFrame(ImageFrameTable::new(image_frame)))]))
|
||||
impl From<Image<Color>> for GraphicGroupTable {
|
||||
fn from(image: Image<Color>) -> Self {
|
||||
Self::new(GraphicGroup::new(vec![GraphicElement::RasterFrame(RasterFrame::ImageFrame(ImageFrameTable::new(image)))]))
|
||||
}
|
||||
}
|
||||
impl From<ImageFrameTable<Color>> for GraphicGroupTable {
|
||||
|
|
@ -121,9 +121,9 @@ impl From<ImageFrameTable<Color>> for GraphicGroupTable {
|
|||
Self::new(GraphicGroup::new(vec![GraphicElement::RasterFrame(RasterFrame::ImageFrame(image_frame))]))
|
||||
}
|
||||
}
|
||||
impl From<TextureFrame> for GraphicGroupTable {
|
||||
fn from(texture_frame: TextureFrame) -> Self {
|
||||
Self::new(GraphicGroup::new(vec![GraphicElement::RasterFrame(RasterFrame::TextureFrame(TextureFrameTable::new(texture_frame)))]))
|
||||
impl From<ImageTexture> for GraphicGroupTable {
|
||||
fn from(image_texture: ImageTexture) -> Self {
|
||||
Self::new(GraphicGroup::new(vec![GraphicElement::RasterFrame(RasterFrame::TextureFrame(TextureFrameTable::new(image_texture)))]))
|
||||
}
|
||||
}
|
||||
impl From<TextureFrameTable> for GraphicGroupTable {
|
||||
|
|
@ -194,11 +194,14 @@ impl GraphicElement {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Rename to Raster
|
||||
#[derive(Clone, Debug, Hash, PartialEq, DynAny)]
|
||||
pub enum RasterFrame {
|
||||
/// A CPU-based bitmap image with a finite position and extent, equivalent to the SVG <image> tag: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image
|
||||
// TODO: Rename to ImageTable
|
||||
ImageFrame(ImageFrameTable<Color>),
|
||||
/// A GPU texture with a finite position and extent
|
||||
// TODO: Rename to ImageTextureTable
|
||||
TextureFrame(TextureFrameTable),
|
||||
}
|
||||
|
||||
|
|
@ -207,7 +210,7 @@ impl<'de> serde::Deserialize<'de> for RasterFrame {
|
|||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Ok(RasterFrame::ImageFrame(ImageFrameTable::new(ImageFrame::deserialize(deserializer)?)))
|
||||
Ok(RasterFrame::ImageFrame(ImageFrameTable::new(Image::deserialize(deserializer)?)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -239,7 +242,7 @@ impl Artboard {
|
|||
pub fn new(location: IVec2, dimensions: IVec2) -> Self {
|
||||
Self {
|
||||
graphic_group: GraphicGroupTable::default(),
|
||||
label: String::from("Artboard"),
|
||||
label: "Artboard".to_string(),
|
||||
location: location.min(location + dimensions),
|
||||
dimensions: dimensions.abs(),
|
||||
background: Color::WHITE,
|
||||
|
|
@ -382,16 +385,13 @@ async fn to_artboard<Data: Into<GraphicGroupTable> + 'n>(
|
|||
}
|
||||
|
||||
#[node_macro::node(category(""))]
|
||||
async fn append_artboard(ctx: impl Ctx, mut artboards: ArtboardGroup, artboard: Artboard, node_path: Vec<NodeId>) -> ArtboardGroup {
|
||||
async fn append_artboard(_ctx: impl Ctx, mut artboards: ArtboardGroup, artboard: Artboard, node_path: Vec<NodeId>) -> ArtboardGroup {
|
||||
// let mut artboards = artboards.eval(ctx.clone()).await;
|
||||
// let artboard = artboard.eval(ctx).await;
|
||||
// let foot = ctx.footprint();
|
||||
// log::debug!("{:?}", foot);
|
||||
// Get the penultimate element of the node path, or None if the path is too short
|
||||
|
||||
// TODO: Delete this line
|
||||
let _ctx = ctx;
|
||||
|
||||
// Get the penultimate element of the node path, or None if the path is too short.
|
||||
// This is used to get the ID of the user-facing "Artboard" node (which encapsulates this internal "Append Artboard" node).
|
||||
let encapsulating_node_id = node_path.get(node_path.len().wrapping_sub(2)).copied();
|
||||
artboards.append_artboard(artboard, encapsulating_node_id);
|
||||
|
||||
|
|
@ -399,8 +399,8 @@ async fn append_artboard(ctx: impl Ctx, mut artboards: ArtboardGroup, artboard:
|
|||
}
|
||||
|
||||
// TODO: Remove this one
|
||||
impl From<ImageFrame<Color>> for GraphicElement {
|
||||
fn from(image_frame: ImageFrame<Color>) -> Self {
|
||||
impl From<Image<Color>> for GraphicElement {
|
||||
fn from(image_frame: Image<Color>) -> Self {
|
||||
GraphicElement::RasterFrame(RasterFrame::ImageFrame(ImageFrameTable::new(image_frame)))
|
||||
}
|
||||
}
|
||||
|
|
@ -410,8 +410,8 @@ impl From<ImageFrameTable<Color>> for GraphicElement {
|
|||
}
|
||||
}
|
||||
// TODO: Remove this one
|
||||
impl From<TextureFrame> for GraphicElement {
|
||||
fn from(texture: TextureFrame) -> Self {
|
||||
impl From<ImageTexture> for GraphicElement {
|
||||
fn from(texture: ImageTexture) -> Self {
|
||||
GraphicElement::RasterFrame(RasterFrame::TextureFrame(TextureFrameTable::new(texture)))
|
||||
}
|
||||
}
|
||||
|
|
@ -462,7 +462,7 @@ trait ToGraphicElement: Into<GraphicElement> {}
|
|||
|
||||
impl ToGraphicElement for VectorDataTable {}
|
||||
impl ToGraphicElement for ImageFrameTable<Color> {}
|
||||
impl ToGraphicElement for TextureFrame {}
|
||||
impl ToGraphicElement for ImageTexture {}
|
||||
|
||||
impl<T> From<T> for GraphicGroup
|
||||
where
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ pub struct RenderMetadata {
|
|||
pub clip_targets: HashSet<NodeId>,
|
||||
}
|
||||
|
||||
// TODO: Rename to "Graphical"
|
||||
pub trait GraphicElementRendered {
|
||||
fn render_svg(&self, render: &mut SvgRender, render_params: &RenderParams);
|
||||
|
||||
|
|
@ -831,7 +832,7 @@ impl GraphicElementRendered for ImageFrameTable<Color> {
|
|||
|
||||
match render_params.image_render_mode {
|
||||
ImageRenderMode::Base64 => {
|
||||
let image = &instance.instance.image;
|
||||
let image = &instance.instance;
|
||||
if image.data.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -894,7 +895,7 @@ impl GraphicElementRendered for ImageFrameTable<Color> {
|
|||
use vello::peniko;
|
||||
|
||||
for instance in self.instances() {
|
||||
let image = &instance.instance.image;
|
||||
let image = &instance.instance;
|
||||
if image.data.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -918,7 +919,7 @@ impl GraphicElementRendered for RasterFrame {
|
|||
};
|
||||
|
||||
for instance in image.instances() {
|
||||
let (image, blending) = (&instance.instance.image, instance.alpha_blending);
|
||||
let (image, blending) = (&instance.instance, instance.alpha_blending);
|
||||
if image.data.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -992,9 +993,9 @@ impl GraphicElementRendered for RasterFrame {
|
|||
};
|
||||
|
||||
match self {
|
||||
RasterFrame::ImageFrame(image_frame) => {
|
||||
for instance in image_frame.instances() {
|
||||
let image = &instance.instance.image;
|
||||
RasterFrame::ImageFrame(image) => {
|
||||
for instance in image.instances() {
|
||||
let image = &instance.instance;
|
||||
if image.data.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1004,8 +1005,8 @@ impl GraphicElementRendered for RasterFrame {
|
|||
render_stuff(image, *instance.alpha_blending);
|
||||
}
|
||||
}
|
||||
RasterFrame::TextureFrame(texture) => {
|
||||
for instance in texture.instances() {
|
||||
RasterFrame::TextureFrame(image_texture) => {
|
||||
for instance in image_texture.instances() {
|
||||
let image =
|
||||
vello::peniko::Image::new(vec![].into(), peniko::Format::Rgba8, instance.instance.texture.width(), instance.instance.texture.height()).with_extend(peniko::Extend::Repeat);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::application_io::{TextureFrame, TextureFrameTable};
|
||||
use crate::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use crate::application_io::{ImageTexture, TextureFrameTable};
|
||||
use crate::raster::image::{Image, ImageFrameTable};
|
||||
use crate::raster::Pixel;
|
||||
use crate::transform::{Transform, TransformMut};
|
||||
use crate::vector::{InstanceId, VectorData, VectorDataTable};
|
||||
|
|
@ -180,18 +180,18 @@ impl TransformMut for GraphicGroupTable {
|
|||
}
|
||||
}
|
||||
|
||||
// TEXTURE FRAME
|
||||
impl Transform for Instance<'_, TextureFrame> {
|
||||
// IMAGE TEXTURE
|
||||
impl Transform for Instance<'_, ImageTexture> {
|
||||
fn transform(&self) -> DAffine2 {
|
||||
*self.transform
|
||||
}
|
||||
}
|
||||
impl Transform for InstanceMut<'_, TextureFrame> {
|
||||
impl Transform for InstanceMut<'_, ImageTexture> {
|
||||
fn transform(&self) -> DAffine2 {
|
||||
*self.transform
|
||||
}
|
||||
}
|
||||
impl TransformMut for InstanceMut<'_, TextureFrame> {
|
||||
impl TransformMut for InstanceMut<'_, ImageTexture> {
|
||||
fn transform_mut(&mut self) -> &mut DAffine2 {
|
||||
self.transform
|
||||
}
|
||||
|
|
@ -209,8 +209,8 @@ impl TransformMut for TextureFrameTable {
|
|||
}
|
||||
}
|
||||
|
||||
// IMAGE FRAME
|
||||
impl<P: Pixel> Transform for Instance<'_, ImageFrame<P>> {
|
||||
// IMAGE
|
||||
impl<P: Pixel> Transform for Instance<'_, Image<P>> {
|
||||
fn transform(&self) -> DAffine2 {
|
||||
*self.transform
|
||||
}
|
||||
|
|
@ -218,7 +218,7 @@ impl<P: Pixel> Transform for Instance<'_, ImageFrame<P>> {
|
|||
self.transform.transform_point2(pivot)
|
||||
}
|
||||
}
|
||||
impl<P: Pixel> Transform for InstanceMut<'_, ImageFrame<P>> {
|
||||
impl<P: Pixel> Transform for InstanceMut<'_, Image<P>> {
|
||||
fn transform(&self) -> DAffine2 {
|
||||
*self.transform
|
||||
}
|
||||
|
|
@ -226,7 +226,7 @@ impl<P: Pixel> Transform for InstanceMut<'_, ImageFrame<P>> {
|
|||
self.transform.transform_point2(pivot)
|
||||
}
|
||||
}
|
||||
impl<P: Pixel> TransformMut for InstanceMut<'_, ImageFrame<P>> {
|
||||
impl<P: Pixel> TransformMut for InstanceMut<'_, Image<P>> {
|
||||
fn transform_mut(&mut self) -> &mut DAffine2 {
|
||||
self.transform
|
||||
}
|
||||
|
|
@ -237,7 +237,7 @@ impl<P: Pixel> Transform for ImageFrameTable<P>
|
|||
where
|
||||
P: dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<ImageFrame<P>>,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn transform(&self) -> DAffine2 {
|
||||
self.one_instance().transform()
|
||||
|
|
@ -247,7 +247,7 @@ impl<P: Pixel> TransformMut for ImageFrameTable<P>
|
|||
where
|
||||
P: dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<ImageFrame<P>>,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn transform_mut(&mut self) -> &mut DAffine2 {
|
||||
self.transform.first_mut().unwrap_or_else(|| panic!("ONE INSTANCE EXPECTED"))
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#[cfg(feature = "alloc")]
|
||||
use crate::raster::curve::{Curve, CurveManipulatorGroup, ValueMapperNode};
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use crate::raster::image::{Image, ImageFrameTable};
|
||||
use crate::raster::{Channel, Color, Pixel};
|
||||
use crate::registry::types::{Angle, Percentage, SignedPercentage};
|
||||
use crate::vector::style::GradientStops;
|
||||
|
|
@ -605,15 +605,13 @@ impl Blend<Color> for ImageFrameTable<Color> {
|
|||
let mut result = self.clone();
|
||||
|
||||
for (over, under) in result.instances_mut().zip(under.instances()) {
|
||||
let data = over.instance.image.data.iter().zip(under.instance.image.data.iter()).map(|(a, b)| blend_fn(*a, *b)).collect();
|
||||
let data = over.instance.data.iter().zip(under.instance.data.iter()).map(|(a, b)| blend_fn(*a, *b)).collect();
|
||||
|
||||
*over.instance = ImageFrame {
|
||||
image: super::Image {
|
||||
data,
|
||||
width: over.instance.image.width,
|
||||
height: over.instance.image.height,
|
||||
base64_string: None,
|
||||
},
|
||||
*over.instance = Image {
|
||||
data,
|
||||
width: over.instance.width,
|
||||
height: over.instance.height,
|
||||
base64_string: None,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -738,11 +736,11 @@ impl<P: Pixel> Adjust<P> for ImageFrameTable<P>
|
|||
where
|
||||
P: dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<ImageFrame<P>>,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn adjust(&mut self, map_fn: impl Fn(&P) -> P) {
|
||||
for instance in self.instances_mut() {
|
||||
for c in instance.instance.image.data.iter_mut() {
|
||||
for c in instance.instance.data.iter_mut() {
|
||||
*c = map_fn(c);
|
||||
}
|
||||
}
|
||||
|
|
@ -1386,7 +1384,7 @@ impl<P: Pixel> MultiplyAlpha for ImageFrameTable<P>
|
|||
where
|
||||
P: dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<ImageFrame<P>>,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn multiply_alpha(&mut self, factor: f64) {
|
||||
for instance in self.instances_mut() {
|
||||
|
|
@ -1539,13 +1537,13 @@ fn color_overlay<T: Adjust<Color>>(
|
|||
|
||||
// #[cfg(feature = "alloc")]
|
||||
// mod index_node {
|
||||
// use crate::raster::{Color, ImageFrame};
|
||||
// use crate::raster::{Color, Image};
|
||||
// use crate::Ctx;
|
||||
|
||||
// #[node_macro::node(category(""))]
|
||||
// pub fn index<T: Default + Clone>(
|
||||
// _: impl Ctx,
|
||||
// #[implementations(Vec<ImageFrame<Color>>, Vec<Color>)]
|
||||
// #[implementations(Vec<Image<Color>>, Vec<Color>)]
|
||||
// #[widget(ParsedWidgetOverride::Hidden)]
|
||||
// input: Vec<T>,
|
||||
// index: u32,
|
||||
|
|
@ -1561,8 +1559,8 @@ fn color_overlay<T: Adjust<Color>>(
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use crate::raster::{BlendMode, Image};
|
||||
use crate::raster::adjustments::BlendMode;
|
||||
use crate::raster::image::{Image, ImageFrameTable};
|
||||
use crate::{Color, Node};
|
||||
use std::pin::Pin;
|
||||
|
||||
|
|
@ -1580,7 +1578,7 @@ mod test {
|
|||
#[tokio::test]
|
||||
async fn color_overlay_multiply() {
|
||||
let image_color = Color::from_rgbaf32_unchecked(0.7, 0.6, 0.5, 0.4);
|
||||
let image = ImageFrame { image: Image::new(1, 1, image_color) };
|
||||
let image = Image::new(1, 1, image_color);
|
||||
|
||||
// Color { red: 0., green: 1., blue: 0., alpha: 1. }
|
||||
let overlay_color = Color::GREEN;
|
||||
|
|
@ -1592,6 +1590,6 @@ mod test {
|
|||
let result = result.one_instance().instance;
|
||||
|
||||
// The output should just be the original green and alpha channels (as we multiply them by 1 and other channels by 0)
|
||||
assert_eq!(result.image.data[0], Color::from_rgbaf32_unchecked(0., image_color.g(), 0., image_color.a()));
|
||||
assert_eq!(result.data[0], Color::from_rgbaf32_unchecked(0., image_color.g(), 0., image_color.a()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ struct BrushCacheImpl {
|
|||
impl BrushCacheImpl {
|
||||
fn compute_brush_plan(&mut self, mut background: ImageFrameTable<Color>, input: &[BrushStroke]) -> BrushPlan {
|
||||
// Do background invalidation.
|
||||
if background.one_instance().instance.image != self.background.one_instance().instance.image {
|
||||
if background.one_instance().instance != self.background.one_instance().instance {
|
||||
self.background = background.clone();
|
||||
return BrushPlan {
|
||||
strokes: input.to_vec(),
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ pub struct Image<P: Pixel> {
|
|||
/// to an svg string. This is used as a cache in order to not have to encode the data on every graph evaluation.
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub base64_string: Option<String>,
|
||||
// TODO: Add an `origin` field to store where in the local space the image is anchored.
|
||||
// TODO: Currently it is always anchored at the top left corner at (0, 0). The bottom right corner of the new origin field would correspond to (1, 1).
|
||||
}
|
||||
|
||||
impl<P: Pixel + Debug> Debug for Image<P> {
|
||||
|
|
@ -66,8 +68,9 @@ impl<P: Pixel + Debug> Debug for Image<P> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<P: dyn_any::StaticTypeSized + Pixel> StaticType for Image<P>
|
||||
unsafe impl<P> StaticType for Image<P>
|
||||
where
|
||||
P: dyn_any::StaticTypeSized + Pixel,
|
||||
P::Static: Pixel,
|
||||
{
|
||||
type Static = Image<P::Static>;
|
||||
|
|
@ -212,6 +215,34 @@ impl<P: Pixel> IntoIterator for Image<P> {
|
|||
pub fn migrate_image_frame<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<ImageFrameTable<Color>, D::Error> {
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Default, Debug, PartialEq, specta::Type)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ImageFrame<P: Pixel> {
|
||||
pub image: Image<P>,
|
||||
}
|
||||
impl From<ImageFrame<Color>> for GraphicElement {
|
||||
fn from(image_frame: ImageFrame<Color>) -> Self {
|
||||
GraphicElement::RasterFrame(crate::RasterFrame::ImageFrame(ImageFrameTable::new(image_frame.image)))
|
||||
}
|
||||
}
|
||||
impl From<GraphicElement> for ImageFrame<Color> {
|
||||
fn from(element: GraphicElement) -> Self {
|
||||
match element {
|
||||
GraphicElement::RasterFrame(crate::RasterFrame::ImageFrame(image)) => Self {
|
||||
image: image.one_instance().instance.clone(),
|
||||
},
|
||||
_ => panic!("Expected Image, found {:?}", element),
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe impl<P> StaticType for ImageFrame<P>
|
||||
where
|
||||
P: dyn_any::StaticTypeSized + Pixel,
|
||||
P::Static: Pixel,
|
||||
{
|
||||
type Static = ImageFrame<P::Static>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug, PartialEq, specta::Type)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct OldImageFrame<P: Pixel> {
|
||||
|
|
@ -222,60 +253,58 @@ pub fn migrate_image_frame<'de, D: serde::Deserializer<'de>>(deserializer: D) ->
|
|||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum EitherFormat {
|
||||
ImageFrame(ImageFrame<Color>),
|
||||
enum FormatVersions {
|
||||
Image(Image<Color>),
|
||||
OldImageFrame(OldImageFrame<Color>),
|
||||
ImageFrame(Instances<ImageFrame<Color>>),
|
||||
ImageFrameTable(ImageFrameTable<Color>),
|
||||
}
|
||||
|
||||
Ok(match EitherFormat::deserialize(deserializer)? {
|
||||
EitherFormat::ImageFrame(image_frame) => ImageFrameTable::<Color>::new(image_frame),
|
||||
EitherFormat::OldImageFrame(image_frame_with_transform_and_blending) => {
|
||||
Ok(match FormatVersions::deserialize(deserializer)? {
|
||||
FormatVersions::Image(image) => ImageFrameTable::new(image),
|
||||
FormatVersions::OldImageFrame(image_frame_with_transform_and_blending) => {
|
||||
let OldImageFrame { image, transform, alpha_blending } = image_frame_with_transform_and_blending;
|
||||
let mut image_frame_table = ImageFrameTable::new(ImageFrame { image });
|
||||
let mut image_frame_table = ImageFrameTable::new(image);
|
||||
*image_frame_table.one_instance_mut().transform = transform;
|
||||
*image_frame_table.one_instance_mut().alpha_blending = alpha_blending;
|
||||
image_frame_table
|
||||
}
|
||||
EitherFormat::ImageFrameTable(image_frame_table) => image_frame_table,
|
||||
FormatVersions::ImageFrame(image_frame) => ImageFrameTable::new(image_frame.one_instance().instance.image.clone()),
|
||||
FormatVersions::ImageFrameTable(image_frame_table) => image_frame_table,
|
||||
})
|
||||
}
|
||||
|
||||
pub type ImageFrameTable<P> = Instances<ImageFrame<P>>;
|
||||
// TODO: Rename to ImageTable
|
||||
pub type ImageFrameTable<P> = Instances<Image<P>>;
|
||||
|
||||
/// Construct a 0x0 image frame table. This is useful because ImageFrameTable::default() will return a 1x1 image frame table.
|
||||
impl ImageFrameTable<Color> {
|
||||
pub fn empty() -> Self {
|
||||
let mut result = Self::new(ImageFrame::default());
|
||||
let mut result = Self::new(Image::default());
|
||||
*result.transform_mut() = DAffine2::ZERO;
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug, PartialEq, specta::Type)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ImageFrame<P: Pixel> {
|
||||
pub image: Image<P>,
|
||||
}
|
||||
|
||||
impl<P: Debug + Copy + Pixel> Sample for ImageFrame<P> {
|
||||
impl<P: Debug + Copy + Pixel> Sample for Image<P> {
|
||||
type Pixel = P;
|
||||
|
||||
// TODO: Improve sampling logic
|
||||
#[inline(always)]
|
||||
fn sample(&self, pos: DVec2, _area: DVec2) -> Option<Self::Pixel> {
|
||||
let image_size = DVec2::new(self.image.width() as f64, self.image.height() as f64);
|
||||
let image_size = DVec2::new(self.width() as f64, self.height() as f64);
|
||||
if pos.x < 0. || pos.y < 0. || pos.x >= image_size.x || pos.y >= image_size.y {
|
||||
return None;
|
||||
}
|
||||
self.image.get_pixel(pos.x as u32, pos.y as u32)
|
||||
self.get_pixel(pos.x as u32, pos.y as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Debug + Copy + Pixel + dyn_any::StaticType> Sample for ImageFrameTable<P>
|
||||
impl<P> Sample for ImageFrameTable<P>
|
||||
where
|
||||
GraphicElement: From<ImageFrame<P>>,
|
||||
P: Debug + Copy + Pixel + dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
type Pixel = P;
|
||||
|
||||
|
|
@ -292,26 +321,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<P: Copy + Pixel> Bitmap for ImageFrame<P> {
|
||||
type Pixel = P;
|
||||
|
||||
fn width(&self) -> u32 {
|
||||
self.image.width()
|
||||
}
|
||||
|
||||
fn height(&self) -> u32 {
|
||||
self.image.height()
|
||||
}
|
||||
|
||||
fn get_pixel(&self, x: u32, y: u32) -> Option<Self::Pixel> {
|
||||
self.image.get_pixel(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Copy + Pixel + dyn_any::StaticType> Bitmap for ImageFrameTable<P>
|
||||
impl<P> Bitmap for ImageFrameTable<P>
|
||||
where
|
||||
P: Copy + Pixel + dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<ImageFrame<P>>,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
type Pixel = P;
|
||||
|
||||
|
|
@ -334,95 +348,57 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<P: Copy + Pixel> BitmapMut for ImageFrame<P> {
|
||||
impl<P> BitmapMut for ImageFrameTable<P>
|
||||
where
|
||||
P: Copy + Pixel + dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
fn get_pixel_mut(&mut self, x: u32, y: u32) -> Option<&mut Self::Pixel> {
|
||||
self.image.get_pixel_mut(x, y)
|
||||
self.one_instance_mut().instance.get_pixel_mut(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Copy + Pixel + dyn_any::StaticType> BitmapMut for ImageFrameTable<P>
|
||||
where
|
||||
GraphicElement: From<ImageFrame<P>>,
|
||||
P::Static: Pixel,
|
||||
{
|
||||
fn get_pixel_mut(&mut self, x: u32, y: u32) -> Option<&mut Self::Pixel> {
|
||||
let image = self.one_instance_mut().instance;
|
||||
|
||||
BitmapMut::get_pixel_mut(image, x, y)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<P: dyn_any::StaticTypeSized + Pixel> StaticType for ImageFrame<P>
|
||||
where
|
||||
P::Static: Pixel,
|
||||
{
|
||||
type Static = ImageFrame<P::Static>;
|
||||
}
|
||||
|
||||
impl<P: Copy + Pixel> ImageFrame<P> {
|
||||
impl<P: Copy + Pixel> Image<P> {
|
||||
pub fn get_mut(&mut self, x: usize, y: usize) -> &mut P {
|
||||
&mut self.image.data[y * (self.image.width as usize) + x]
|
||||
&mut self.data[y * (self.width as usize) + x]
|
||||
}
|
||||
|
||||
/// Clamps the provided point to ((0, 0), (ImageSize.x, ImageSize.y)) and returns the closest pixel
|
||||
pub fn sample(&self, position: DVec2) -> P {
|
||||
let x = position.x.clamp(0., self.image.width as f64 - 1.) as usize;
|
||||
let y = position.y.clamp(0., self.image.height as f64 - 1.) as usize;
|
||||
let x = position.x.clamp(0., self.width as f64 - 1.) as usize;
|
||||
let y = position.y.clamp(0., self.height as f64 - 1.) as usize;
|
||||
|
||||
self.image.data[x + y * self.image.width as usize]
|
||||
self.data[x + y * self.width as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Pixel> AsRef<ImageFrame<P>> for ImageFrame<P> {
|
||||
fn as_ref(&self) -> &ImageFrame<P> {
|
||||
impl<P: Pixel> AsRef<Image<P>> for Image<P> {
|
||||
fn as_ref(&self) -> &Image<P> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Hash + Pixel> Hash for ImageFrame<P> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
0.hash(state);
|
||||
self.image.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/* This does not work because of missing specialization
|
||||
* so we have to manually implement this for now
|
||||
impl<S: Into<P> + Pixel, P: Pixel> From<Image<S>> for Image<P> {
|
||||
fn from(image: Image<S>) -> Self {
|
||||
impl From<Image<Color>> for Image<SRGBA8> {
|
||||
fn from(image: Image<Color>) -> Self {
|
||||
let data = image.data.into_iter().map(|x| x.into()).collect();
|
||||
Self {
|
||||
data,
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
impl From<ImageFrame<Color>> for ImageFrame<SRGBA8> {
|
||||
fn from(image: ImageFrame<Color>) -> Self {
|
||||
let data = image.image.data.into_iter().map(|x| x.into()).collect();
|
||||
Self {
|
||||
image: Image {
|
||||
data,
|
||||
width: image.image.width,
|
||||
height: image.image.height,
|
||||
base64_string: None,
|
||||
},
|
||||
base64_string: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ImageFrame<SRGBA8>> for ImageFrame<Color> {
|
||||
fn from(image: ImageFrame<SRGBA8>) -> Self {
|
||||
let data = image.image.data.into_iter().map(|x| x.into()).collect();
|
||||
impl From<Image<SRGBA8>> for Image<Color> {
|
||||
fn from(image: Image<SRGBA8>) -> Self {
|
||||
let data = image.data.into_iter().map(|x| x.into()).collect();
|
||||
Self {
|
||||
image: Image {
|
||||
data,
|
||||
width: image.image.width,
|
||||
height: image.image.height,
|
||||
base64_string: None,
|
||||
},
|
||||
data,
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
base64_string: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,9 +150,14 @@ fn migrate_type_descriptor_names<'de, D: serde::Deserializer<'de>>(deserializer:
|
|||
let name = match name.as_str() {
|
||||
"f32" => "f64".to_string(),
|
||||
"graphene_core::transform::Footprint" => "core::option::Option<alloc::sync::Arc<graphene_core::context::OwnedContextImpl>>".to_string(),
|
||||
"graphene_core::graphic_element::GraphicGroup" => "graphene_core::graphic_element::Instances<graphene_core::graphic_element::GraphicGroup>".to_string(),
|
||||
"graphene_core::vector::vector_data::VectorData" => "graphene_core::graphic_element::Instances<graphene_core::vector::vector_data::VectorData>".to_string(),
|
||||
"graphene_core::raster::image::ImageFrame<Color>" => "graphene_core::graphic_element::Instances<graphene_core::raster::image::ImageFrame<Color>>".to_string(),
|
||||
"graphene_core::graphic_element::GraphicGroup" => "graphene_core::instances::Instances<graphene_core::graphic_element::GraphicGroup>".to_string(),
|
||||
"graphene_core::vector::vector_data::VectorData" => "graphene_core::instances::Instances<graphene_core::vector::vector_data::VectorData>".to_string(),
|
||||
"graphene_core::raster::image::ImageFrame<Color>"
|
||||
| "graphene_core::raster::image::ImageFrame<graphene_core::raster::color::Color>"
|
||||
| "graphene_core::instances::Instances<graphene_core::raster::image::ImageFrame<Color>>"
|
||||
| "graphene_core::instances::Instances<graphene_core::raster::image::ImageFrame<graphene_core::raster::color::Color>>" => {
|
||||
"graphene_core::instances::Instances<graphene_core::raster::image::Image<graphene_core::raster::color::Color>>".to_string()
|
||||
}
|
||||
_ => name,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use graph_craft::proto::FutureWrapperNode;
|
|||
use graphene_core::raster::adjustments::blend_colors;
|
||||
use graphene_core::raster::bbox::{AxisAlignedBbox, Bbox};
|
||||
use graphene_core::raster::brush_cache::BrushCache;
|
||||
use graphene_core::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use graphene_core::raster::{Alpha, Bitmap, BlendMode, Color, Image, Pixel, Sample};
|
||||
use graphene_core::raster::image::{Image, ImageFrameTable};
|
||||
use graphene_core::raster::{Alpha, Bitmap, BlendMode, Color, Pixel, Sample};
|
||||
use graphene_core::transform::{Transform, TransformMut};
|
||||
use graphene_core::value::{ClonedNode, CopiedNode, ValueNode};
|
||||
use graphene_core::vector::brush_stroke::{BrushStroke, BrushStyle};
|
||||
|
|
@ -93,14 +93,14 @@ where
|
|||
P: Pixel + Alpha + std::fmt::Debug + dyn_any::StaticType,
|
||||
P::Static: Pixel,
|
||||
BlendFn: for<'any_input> Node<'any_input, (P, P), Output = P>,
|
||||
GraphicElement: From<ImageFrame<P>>,
|
||||
GraphicElement: From<Image<P>>,
|
||||
{
|
||||
if positions.is_empty() {
|
||||
return target;
|
||||
}
|
||||
|
||||
let target_width = target.one_instance().instance.image.width;
|
||||
let target_height = target.one_instance().instance.image.height;
|
||||
let target_width = target.one_instance().instance.width;
|
||||
let target_height = target.one_instance().instance.height;
|
||||
let target_size = DVec2::new(target_width as f64, target_height as f64);
|
||||
|
||||
let texture_size = DVec2::new(texture.width as f64, texture.height as f64);
|
||||
|
|
@ -125,12 +125,12 @@ where
|
|||
let max_y = (blit_area_offset.y + blit_area_dimensions.y).saturating_sub(1);
|
||||
let max_x = (blit_area_offset.x + blit_area_dimensions.x).saturating_sub(1);
|
||||
assert!(texture_index(max_x, max_y) < texture.data.len());
|
||||
assert!(target_index(max_x, max_y) < target.one_instance().instance.image.data.len());
|
||||
assert!(target_index(max_x, max_y) < target.one_instance().instance.data.len());
|
||||
|
||||
for y in blit_area_offset.y..blit_area_offset.y + blit_area_dimensions.y {
|
||||
for x in blit_area_offset.x..blit_area_offset.x + blit_area_dimensions.x {
|
||||
let src_pixel = texture.data[texture_index(x, y)];
|
||||
let dst_pixel = &mut target.one_instance_mut().instance.image.data[target_index(x + clamp_start.x, y + clamp_start.y)];
|
||||
let dst_pixel = &mut target.one_instance_mut().instance.data[target_index(x + clamp_start.x, y + clamp_start.y)];
|
||||
*dst_pixel = blend_mode.eval((src_pixel, *dst_pixel));
|
||||
}
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@ pub async fn create_brush_texture(brush_style: &BrushStyle) -> Image<Color> {
|
|||
let blank_texture = empty_image((), transform, Color::TRANSPARENT);
|
||||
let image = crate::raster::blend_image_closure(stamp, blank_texture, |a, b| blend_colors(a, b, BlendMode::Normal, 1.));
|
||||
|
||||
image.one_instance().instance.image.clone()
|
||||
image.one_instance().instance.clone()
|
||||
}
|
||||
|
||||
macro_rules! inline_blend_funcs {
|
||||
|
|
@ -286,9 +286,7 @@ async fn brush(_: impl Ctx, image_frame_table: ImageFrameTable<Color>, bounds: I
|
|||
|
||||
let has_erase_strokes = strokes.iter().any(|s| s.style.blend_mode == BlendMode::Erase);
|
||||
if has_erase_strokes {
|
||||
let opaque_image = ImageFrame {
|
||||
image: Image::new(bbox.size().x as u32, bbox.size().y as u32, Color::WHITE),
|
||||
};
|
||||
let opaque_image = Image::new(bbox.size().x as u32, bbox.size().y as u32, Color::WHITE);
|
||||
let mut erase_restore_mask = ImageFrameTable::new(opaque_image);
|
||||
*erase_restore_mask.transform_mut() = background_bounds;
|
||||
*erase_restore_mask.one_instance_mut().alpha_blending = Default::default();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use graph_craft::proto::types::Percentage;
|
||||
use graphene_core::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use graphene_core::raster::Image;
|
||||
use graphene_core::raster::image::{Image, ImageFrameTable};
|
||||
use graphene_core::transform::{Transform, TransformMut};
|
||||
use graphene_core::{Color, Ctx};
|
||||
|
||||
|
|
@ -13,10 +12,9 @@ async fn dehaze(_: impl Ctx, image_frame: ImageFrameTable<Color>, strength: Perc
|
|||
let image_frame_transform = image_frame.transform();
|
||||
let image_frame_alpha_blending = image_frame.one_instance().alpha_blending;
|
||||
|
||||
let image_frame = image_frame.one_instance().instance;
|
||||
let image = image_frame.one_instance().instance;
|
||||
|
||||
// Prepare the image data for processing
|
||||
let image = &image_frame.image;
|
||||
let image_data = bytemuck::cast_vec(image.data.clone());
|
||||
let image_buffer = image::Rgba32FImage::from_raw(image.width, image.height, image_data).expect("Failed to convert internal image format into image-rs data type.");
|
||||
let dynamic_image: image::DynamicImage = image_buffer.into();
|
||||
|
|
@ -34,7 +32,7 @@ async fn dehaze(_: impl Ctx, image_frame: ImageFrameTable<Color>, strength: Perc
|
|||
base64_string: None,
|
||||
};
|
||||
|
||||
let mut result = ImageFrameTable::new(ImageFrame { image: dehazed_image });
|
||||
let mut result = ImageFrameTable::new(dehazed_image);
|
||||
*result.transform_mut() = image_frame_transform;
|
||||
*result.one_instance_mut().alpha_blending = *image_frame_alpha_blending;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ use graph_craft::document::value::TaggedValue;
|
|||
use graph_craft::document::*;
|
||||
use graph_craft::proto::*;
|
||||
use graphene_core::application_io::ApplicationIo;
|
||||
use graphene_core::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use graphene_core::raster::{BlendMode, Image, Pixel};
|
||||
use graphene_core::raster::image::{Image, ImageFrameTable};
|
||||
use graphene_core::raster::{BlendMode, Pixel};
|
||||
use graphene_core::transform::Transform;
|
||||
use graphene_core::transform::TransformMut;
|
||||
use graphene_core::*;
|
||||
|
|
@ -72,9 +72,7 @@ async fn map_gpu<'a: 'input>(image: ImageFrameTable<Color>, node: DocumentNode,
|
|||
let executor = &editor_api.application_io.as_ref().and_then(|io| io.gpu_executor()).unwrap();
|
||||
|
||||
#[cfg(feature = "image-compare")]
|
||||
let img: image::DynamicImage = image::Rgba32FImage::from_raw(image.image.width, image.image.height, bytemuck::cast_vec(image.image.data.clone()))
|
||||
.unwrap()
|
||||
.into();
|
||||
let img: image::DynamicImage = image::Rgba32FImage::from_raw(image.width, image.height, bytemuck::cast_vec(image.data.clone())).unwrap().into();
|
||||
|
||||
// TODO: The cache should be based on the network topology not the node name
|
||||
let compute_pass_descriptor = if self.cache.lock().as_ref().unwrap().contains_key("placeholder") {
|
||||
|
|
@ -94,7 +92,7 @@ async fn map_gpu<'a: 'input>(image: ImageFrameTable<Color>, node: DocumentNode,
|
|||
.create_compute_pass(
|
||||
&compute_pass_descriptor.pipeline_layout,
|
||||
compute_pass_descriptor.readback_buffer.clone(),
|
||||
ComputePassDimensions::XY(image.image.width / 12 + 1, image.image.height / 8 + 1),
|
||||
ComputePassDimensions::XY(image.width / 12 + 1, image.height / 8 + 1),
|
||||
)
|
||||
.unwrap();
|
||||
executor.execute_compute_pipeline(compute_pass).unwrap();
|
||||
|
|
@ -105,7 +103,7 @@ async fn map_gpu<'a: 'input>(image: ImageFrameTable<Color>, node: DocumentNode,
|
|||
log::debug!("first color: {:?}", colors[0]);
|
||||
|
||||
#[cfg(feature = "image-compare")]
|
||||
let img2: image::DynamicImage = image::Rgba32FImage::from_raw(image.image.width, image.image.height, bytemuck::cast_vec(colors.clone())).unwrap().into();
|
||||
let img2: image::DynamicImage = image::Rgba32FImage::from_raw(image.width, image.height, bytemuck::cast_vec(colors.clone())).unwrap().into();
|
||||
#[cfg(feature = "image-compare")]
|
||||
let score = image_compare::rgb_hybrid_compare(&img.into_rgb8(), &img2.into_rgb8()).unwrap();
|
||||
#[cfg(feature = "image-compare")]
|
||||
|
|
@ -113,11 +111,11 @@ async fn map_gpu<'a: 'input>(image: ImageFrameTable<Color>, node: DocumentNode,
|
|||
|
||||
let new_image = Image {
|
||||
data: colors,
|
||||
width: image.image.width,
|
||||
height: image.image.height,
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
..Default::default()
|
||||
};
|
||||
let mut result = ImageFrameTable::new(ImageFrame { image: new_image });
|
||||
let mut result = ImageFrameTable::new(new_image);
|
||||
*result.transform_mut() = image_frame_table.transform();
|
||||
*result.one_instance_mut().alpha_blending = *image_frame_table.one_instance().alpha_blending;
|
||||
|
||||
|
|
@ -136,7 +134,7 @@ impl<Node, EditorApi> MapGpuNode<Node, EditorApi> {
|
|||
|
||||
async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(node: DocumentNode, image: &ImageFrameTable<T>, executor: &&WgpuExecutor) -> Result<ComputePass, String>
|
||||
where
|
||||
GraphicElement: From<ImageFrame<T>>,
|
||||
GraphicElement: From<Image<T>>,
|
||||
T::Static: Pixel,
|
||||
{
|
||||
let image = image.one_instance().instance;
|
||||
|
|
@ -215,11 +213,11 @@ where
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let len: usize = image.image.data.len();
|
||||
let len: usize = image.data.len();
|
||||
|
||||
let storage_buffer = executor
|
||||
.create_storage_buffer(
|
||||
image.image.data.clone(),
|
||||
image.data.clone(),
|
||||
StorageBufferOptions {
|
||||
cpu_writable: false,
|
||||
gpu_writable: true,
|
||||
|
|
@ -234,7 +232,7 @@ where
|
|||
// let surface = unsafe { executor.create_surface(canvas) }.unwrap();
|
||||
// let surface_id = surface.surface_id;
|
||||
|
||||
// let texture = executor.create_texture_buffer(image.image.clone(), TextureBufferOptions::Texture).unwrap();
|
||||
// let texture = executor.create_texture_buffer(image.clone(), TextureBufferOptions::Texture).unwrap();
|
||||
|
||||
// // executor.create_render_pass(texture, surface).unwrap();
|
||||
|
||||
|
|
@ -245,7 +243,7 @@ where
|
|||
// return frame;
|
||||
|
||||
log::debug!("creating buffer");
|
||||
let width_uniform = executor.create_uniform_buffer(image.image.width).unwrap();
|
||||
let width_uniform = executor.create_uniform_buffer(image.width).unwrap();
|
||||
|
||||
let storage_buffer = Arc::new(storage_buffer);
|
||||
let output_buffer = executor.create_output_buffer(len, concrete!(Color), false).unwrap();
|
||||
|
|
@ -289,8 +287,8 @@ async fn blend_gpu_image(_: impl Ctx, foreground: ImageFrameTable<Color>, backgr
|
|||
let foreground = foreground.one_instance().instance;
|
||||
let background = background.one_instance().instance;
|
||||
|
||||
let foreground_size = DVec2::new(foreground.image.width as f64, foreground.image.height as f64);
|
||||
let background_size = DVec2::new(background.image.width as f64, background.image.height as f64);
|
||||
let foreground_size = DVec2::new(foreground.width as f64, foreground.height as f64);
|
||||
let background_size = DVec2::new(background.width as f64, background.height as f64);
|
||||
|
||||
// Transforms a point from the background image to the foreground image
|
||||
let bg_to_fg = DAffine2::from_scale(foreground_size) * foreground_transform.inverse() * background_transform * DAffine2::from_scale(1. / background_size);
|
||||
|
|
@ -371,16 +369,16 @@ async fn blend_gpu_image(_: impl Ctx, foreground: ImageFrameTable<Color>, backgr
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let len = background.image.data.len();
|
||||
let len = background.data.len();
|
||||
|
||||
let executor = WgpuExecutor::new()
|
||||
.await
|
||||
.expect("Failed to create wgpu executor. Please make sure that webgpu is enabled for your browser.");
|
||||
log::debug!("creating buffer");
|
||||
let width_uniform = executor.create_uniform_buffer(background.image.width).unwrap();
|
||||
let width_uniform = executor.create_uniform_buffer(background.width).unwrap();
|
||||
let bg_storage_buffer = executor
|
||||
.create_storage_buffer(
|
||||
background.image.data.clone(),
|
||||
background.data.clone(),
|
||||
StorageBufferOptions {
|
||||
cpu_writable: false,
|
||||
gpu_writable: true,
|
||||
|
|
@ -391,7 +389,7 @@ async fn blend_gpu_image(_: impl Ctx, foreground: ImageFrameTable<Color>, backgr
|
|||
.unwrap();
|
||||
let fg_storage_buffer = executor
|
||||
.create_storage_buffer(
|
||||
foreground.image.data.clone(),
|
||||
foreground.data.clone(),
|
||||
StorageBufferOptions {
|
||||
cpu_writable: false,
|
||||
gpu_writable: true,
|
||||
|
|
@ -400,7 +398,7 @@ async fn blend_gpu_image(_: impl Ctx, foreground: ImageFrameTable<Color>, backgr
|
|||
},
|
||||
)
|
||||
.unwrap();
|
||||
let fg_width_uniform = executor.create_uniform_buffer(foreground.image.width).unwrap();
|
||||
let fg_width_uniform = executor.create_uniform_buffer(foreground.width).unwrap();
|
||||
let transform_uniform = executor.create_uniform_buffer(transform_matrix).unwrap();
|
||||
let translation_uniform = executor.create_uniform_buffer(translation).unwrap();
|
||||
let width_uniform = Arc::new(width_uniform);
|
||||
|
|
@ -442,7 +440,7 @@ async fn blend_gpu_image(_: impl Ctx, foreground: ImageFrameTable<Color>, backgr
|
|||
};
|
||||
log::debug!("created pipeline");
|
||||
let compute_pass = executor
|
||||
.create_compute_pass(&pipeline, Some(readback_buffer.clone()), ComputePassDimensions::XY(background.image.width, background.image.height))
|
||||
.create_compute_pass(&pipeline, Some(readback_buffer.clone()), ComputePassDimensions::XY(background.width, background.height))
|
||||
.unwrap();
|
||||
executor.execute_compute_pipeline(compute_pass).unwrap();
|
||||
log::debug!("executed pipeline");
|
||||
|
|
@ -452,12 +450,12 @@ async fn blend_gpu_image(_: impl Ctx, foreground: ImageFrameTable<Color>, backgr
|
|||
|
||||
let created_image = Image {
|
||||
data: colors,
|
||||
width: background.image.width,
|
||||
height: background.image.height,
|
||||
width: background.width,
|
||||
height: background.height,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut result = ImageFrameTable::new(ImageFrame { image: created_image });
|
||||
let mut result = ImageFrameTable::new(created_image);
|
||||
*result.transform_mut() = background_transform;
|
||||
*result.one_instance_mut().alpha_blending = *background_alpha_blending;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ async fn image_color_palette(
|
|||
|
||||
let image = image.one_instance().instance;
|
||||
|
||||
for pixel in image.image.data.iter() {
|
||||
for pixel in image.data.iter() {
|
||||
let r = pixel.r() * GRID;
|
||||
let g = pixel.g() * GRID;
|
||||
let b = pixel.b() * GRID;
|
||||
|
|
@ -65,20 +65,17 @@ async fn image_color_palette(
|
|||
mod test {
|
||||
use super::*;
|
||||
|
||||
use graphene_core::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use graphene_core::raster::Image;
|
||||
use graphene_core::raster::image::{Image, ImageFrameTable};
|
||||
|
||||
#[test]
|
||||
fn test_image_color_palette() {
|
||||
let result = image_color_palette(
|
||||
(),
|
||||
ImageFrameTable::new(ImageFrame {
|
||||
image: Image {
|
||||
width: 100,
|
||||
height: 100,
|
||||
data: vec![Color::from_rgbaf32(0., 0., 0., 1.).unwrap(); 10000],
|
||||
base64_string: None,
|
||||
},
|
||||
ImageFrameTable::new(Image {
|
||||
width: 100,
|
||||
height: 100,
|
||||
data: vec![Color::from_rgbaf32(0., 0., 0., 1.).unwrap(); 10000],
|
||||
base64_string: None,
|
||||
}),
|
||||
1,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use dyn_any::DynAny;
|
||||
use graphene_core::raster::bbox::Bbox;
|
||||
use graphene_core::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use graphene_core::raster::image::{Image, ImageFrameTable};
|
||||
use graphene_core::raster::{
|
||||
Alpha, AlphaMut, Bitmap, BitmapMut, CellularDistanceFunction, CellularReturnType, DomainWarpType, FractalType, Image, Linear, LinearChannel, Luminance, NoiseType, Pixel, RGBMut, RedGreenBlue,
|
||||
Sample,
|
||||
Alpha, AlphaMut, Bitmap, BitmapMut, CellularDistanceFunction, CellularReturnType, DomainWarpType, FractalType, Linear, LinearChannel, Luminance, NoiseType, Pixel, RGBMut, RedGreenBlue, Sample,
|
||||
};
|
||||
use graphene_core::transform::{Transform, TransformMut};
|
||||
use graphene_core::{AlphaBlending, Color, Ctx, ExtractFootprint, GraphicElement, Node};
|
||||
|
|
@ -33,10 +32,9 @@ fn sample_image(ctx: impl ExtractFootprint + Clone + Send, image_frame: ImageFra
|
|||
let image_frame_transform = image_frame.transform();
|
||||
let image_frame_alpha_blending = image_frame.one_instance().alpha_blending;
|
||||
|
||||
let image_frame = image_frame.one_instance().instance;
|
||||
let image = image_frame.one_instance().instance;
|
||||
|
||||
// Resize the image using the image crate
|
||||
let image = &image_frame.image;
|
||||
let data = bytemuck::cast_vec(image.data.clone());
|
||||
|
||||
let footprint = ctx.footprint();
|
||||
|
|
@ -86,7 +84,7 @@ fn sample_image(ctx: impl ExtractFootprint + Clone + Send, image_frame: ImageFra
|
|||
|
||||
let new_transform = image_frame_transform * DAffine2::from_translation(offset) * DAffine2::from_scale(size);
|
||||
|
||||
let mut result = ImageFrameTable::new(ImageFrame { image });
|
||||
let mut result = ImageFrameTable::new(image);
|
||||
*result.transform_mut() = new_transform;
|
||||
*result.one_instance_mut().alpha_blending = *image_frame_alpha_blending;
|
||||
|
||||
|
|
@ -263,7 +261,7 @@ where
|
|||
_P::Static: Pixel,
|
||||
MapFn: for<'any_input> Node<'any_input, (_P, _P), Output = _P> + 'n + Clone,
|
||||
_Fg: Sample<Pixel = _P> + Transform + Clone + Send + 'n,
|
||||
GraphicElement: From<ImageFrame<_P>>,
|
||||
GraphicElement: From<Image<_P>>,
|
||||
{
|
||||
let (background, foreground) = images;
|
||||
|
||||
|
|
@ -330,11 +328,11 @@ fn extend_image_to_bounds(image: ImageFrameTable<Color>, bounds: DAffine2) -> Im
|
|||
}
|
||||
|
||||
let image_instance = image.one_instance().instance;
|
||||
if image_instance.image.width == 0 || image_instance.image.height == 0 {
|
||||
if image_instance.width == 0 || image_instance.height == 0 {
|
||||
return empty_image((), bounds, Color::TRANSPARENT);
|
||||
}
|
||||
|
||||
let orig_image_scale = DVec2::new(image_instance.image.width as f64, image_instance.image.height as f64);
|
||||
let orig_image_scale = DVec2::new(image_instance.width as f64, image_instance.height as f64);
|
||||
let layer_to_image_space = DAffine2::from_scale(orig_image_scale) * image.transform().inverse();
|
||||
let bounds_in_image_space = Bbox::unit().affine_transform(layer_to_image_space * bounds).to_axis_aligned_bbox();
|
||||
|
||||
|
|
@ -345,11 +343,11 @@ fn extend_image_to_bounds(image: ImageFrameTable<Color>, bounds: DAffine2) -> Im
|
|||
// Copy over original image into enlarged image.
|
||||
let mut new_img = Image::new(new_scale.x as u32, new_scale.y as u32, Color::TRANSPARENT);
|
||||
let offset_in_new_image = (-new_start).as_uvec2();
|
||||
for y in 0..image_instance.image.height {
|
||||
let old_start = y * image_instance.image.width;
|
||||
for y in 0..image_instance.height {
|
||||
let old_start = y * image_instance.width;
|
||||
let new_start = (y + offset_in_new_image.y) * new_img.width + offset_in_new_image.x;
|
||||
let old_row = &image_instance.image.data[old_start as usize..(old_start + image_instance.image.width) as usize];
|
||||
let new_row = &mut new_img.data[new_start as usize..(new_start + image_instance.image.width) as usize];
|
||||
let old_row = &image_instance.data[old_start as usize..(old_start + image_instance.width) as usize];
|
||||
let new_row = &mut new_img.data[new_start as usize..(new_start + image_instance.width) as usize];
|
||||
new_row.copy_from_slice(old_row);
|
||||
}
|
||||
|
||||
|
|
@ -357,7 +355,7 @@ fn extend_image_to_bounds(image: ImageFrameTable<Color>, bounds: DAffine2) -> Im
|
|||
// let layer_to_new_texture_space = (DAffine2::from_scale(1. / new_scale) * DAffine2::from_translation(new_start) * layer_to_image_space).inverse();
|
||||
let new_texture_to_layer_space = image.transform() * DAffine2::from_scale(1. / orig_image_scale) * DAffine2::from_translation(new_start) * DAffine2::from_scale(new_scale);
|
||||
|
||||
let mut result = ImageFrameTable::new(ImageFrame { image: new_img });
|
||||
let mut result = ImageFrameTable::new(new_img);
|
||||
*result.transform_mut() = new_texture_to_layer_space;
|
||||
*result.one_instance_mut().alpha_blending = *image.one_instance().alpha_blending;
|
||||
|
||||
|
|
@ -371,7 +369,7 @@ fn empty_image(_: impl Ctx, transform: DAffine2, color: Color) -> ImageFrameTabl
|
|||
|
||||
let image = Image::new(width, height, color);
|
||||
|
||||
let mut result = ImageFrameTable::new(ImageFrame { image });
|
||||
let mut result = ImageFrameTable::new(image);
|
||||
*result.transform_mut() = transform;
|
||||
*result.one_instance_mut().alpha_blending = AlphaBlending::default();
|
||||
|
||||
|
|
@ -559,7 +557,7 @@ fn noise_pattern(
|
|||
}
|
||||
}
|
||||
|
||||
let mut result = ImageFrameTable::new(ImageFrame { image });
|
||||
let mut result = ImageFrameTable::new(image);
|
||||
*result.transform_mut() = DAffine2::from_translation(offset) * DAffine2::from_scale(size);
|
||||
*result.one_instance_mut().alpha_blending = AlphaBlending::default();
|
||||
|
||||
|
|
@ -621,7 +619,7 @@ fn noise_pattern(
|
|||
}
|
||||
}
|
||||
|
||||
let mut result = ImageFrameTable::new(ImageFrame { image });
|
||||
let mut result = ImageFrameTable::new(image);
|
||||
*result.transform_mut() = DAffine2::from_translation(offset) * DAffine2::from_scale(size);
|
||||
*result.one_instance_mut().alpha_blending = AlphaBlending::default();
|
||||
|
||||
|
|
@ -669,7 +667,7 @@ fn mandelbrot(ctx: impl ExtractFootprint + Send) -> ImageFrameTable<Color> {
|
|||
data,
|
||||
..Default::default()
|
||||
};
|
||||
let mut result = ImageFrameTable::new(ImageFrame { image });
|
||||
let mut result = ImageFrameTable::new(image);
|
||||
*result.transform_mut() = DAffine2::from_translation(offset) * DAffine2::from_scale(size);
|
||||
*result.one_instance_mut().alpha_blending = Default::default();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ use graphene_core::application_io::SurfaceHandle;
|
|||
use graphene_core::application_io::{ApplicationIo, ExportFormat, RenderConfig};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use graphene_core::raster::bbox::Bbox;
|
||||
use graphene_core::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use graphene_core::raster::Image;
|
||||
use graphene_core::raster::image::{Image, ImageFrameTable};
|
||||
use graphene_core::renderer::RenderMetadata;
|
||||
use graphene_core::renderer::{format_transform_matrix, GraphicElementRendered, ImageRenderMode, RenderParams, RenderSvgSegmentList, SvgRender};
|
||||
use graphene_core::transform::Footprint;
|
||||
|
|
@ -81,13 +80,11 @@ fn decode_image(_: impl Ctx, data: Arc<[u8]>) -> ImageFrameTable<Color> {
|
|||
return ImageFrameTable::empty();
|
||||
};
|
||||
let image = image.to_rgba32f();
|
||||
let image = ImageFrame {
|
||||
image: Image {
|
||||
data: image.chunks(4).map(|pixel| Color::from_unassociated_alpha(pixel[0], pixel[1], pixel[2], pixel[3])).collect(),
|
||||
width: image.width(),
|
||||
height: image.height(),
|
||||
..Default::default()
|
||||
},
|
||||
let image = Image {
|
||||
data: image.chunks(4).map(|pixel| Color::from_unassociated_alpha(pixel[0], pixel[1], pixel[2], pixel[3])).collect(),
|
||||
width: image.width(),
|
||||
height: image.height(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
ImageFrameTable::new(image)
|
||||
|
|
@ -204,9 +201,7 @@ async fn rasterize<T: GraphicElementRendered + graphene_core::transform::Transfo
|
|||
|
||||
let rasterized = context.get_image_data(0., 0., resolution.x as f64, resolution.y as f64).unwrap();
|
||||
|
||||
let mut result = ImageFrameTable::new(ImageFrame {
|
||||
image: Image::from_image_data(&rasterized.data().0, resolution.x as u32, resolution.y as u32),
|
||||
});
|
||||
let mut result = ImageFrameTable::new(Image::from_image_data(&rasterized.data().0, resolution.x as u32, resolution.y as u32));
|
||||
*result.transform_mut() = footprint.transform;
|
||||
|
||||
result
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use graphene_core::{fn_type_fut, future};
|
|||
use graphene_core::{Cow, ProtoNodeIdentifier, Type};
|
||||
use graphene_core::{Node, NodeIO, NodeIOTypes};
|
||||
use graphene_std::any::{ComposeTypeErased, DowncastBothNode, DynAnyNode, FutureWrapperNode, IntoTypeErasedNode};
|
||||
use graphene_std::application_io::TextureFrame;
|
||||
use graphene_std::application_io::ImageTexture;
|
||||
use graphene_std::wasm_application_io::*;
|
||||
use graphene_std::Context;
|
||||
use graphene_std::GraphicElement;
|
||||
|
|
@ -79,7 +79,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||
async_node!(graphene_core::ops::IntoNode<GraphicGroupTable>, input: VectorDataTable, params: []),
|
||||
async_node!(graphene_core::ops::IntoNode<GraphicGroupTable>, input: ImageFrameTable<Color>, params: []),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => ImageFrameTable<Color>]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => TextureFrame]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => ImageTexture]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => VectorDataTable]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => GraphicGroupTable]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => GraphicElement]),
|
||||
|
|
@ -268,7 +268,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => ShaderInputFrame]),
|
||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => WgpuSurface]),
|
||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => Option<WgpuSurface>]),
|
||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => TextureFrame]),
|
||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Context, fn_params: [Context => ImageTexture]),
|
||||
];
|
||||
let mut map: HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeConstructor>> = HashMap::new();
|
||||
for (id, entry) in graphene_core::registry::NODE_REGISTRY.lock().unwrap().iter() {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ pub use executor::GpuExecutor;
|
|||
|
||||
use dyn_any::{DynAny, StaticType};
|
||||
use gpu_executor::{ComputePassDimensions, GPUConstant, StorageBufferOptions, TextureBufferOptions, TextureBufferType, ToStorageBuffer, ToUniformBuffer};
|
||||
use graphene_core::application_io::{ApplicationIo, EditorApi, SurfaceHandle, TextureFrame};
|
||||
use graphene_core::application_io::{ApplicationIo, EditorApi, ImageTexture, SurfaceHandle};
|
||||
use graphene_core::raster::image::ImageFrameTable;
|
||||
use graphene_core::raster::{Image, SRGBA8};
|
||||
use graphene_core::transform::{Footprint, Transform};
|
||||
|
|
@ -913,14 +913,14 @@ async fn render_texture<'a: 'n>(
|
|||
}
|
||||
|
||||
#[node_macro::node(category(""))]
|
||||
async fn upload_texture<'a: 'n>(_: impl ExtractFootprint + Ctx, input: ImageFrameTable<Color>, executor: &'a WgpuExecutor) -> TextureFrame {
|
||||
async fn upload_texture<'a: 'n>(_: impl ExtractFootprint + Ctx, input: ImageFrameTable<Color>, executor: &'a WgpuExecutor) -> ImageTexture {
|
||||
// let new_data: Vec<RGBA16F> = input.image.data.into_iter().map(|c| c.into()).collect();
|
||||
|
||||
let input = input.one_instance().instance;
|
||||
let new_data: Vec<SRGBA8> = input.image.data.iter().map(|x| (*x).into()).collect();
|
||||
let new_data: Vec<SRGBA8> = input.data.iter().map(|x| (*x).into()).collect();
|
||||
let new_image = Image {
|
||||
width: input.image.width,
|
||||
height: input.image.height,
|
||||
width: input.width,
|
||||
height: input.height,
|
||||
data: new_data,
|
||||
base64_string: None,
|
||||
};
|
||||
|
|
@ -932,9 +932,9 @@ async fn upload_texture<'a: 'n>(_: impl ExtractFootprint + Ctx, input: ImageFram
|
|||
_ => unreachable!("Unsupported ShaderInput type"),
|
||||
};
|
||||
|
||||
TextureFrame {
|
||||
ImageTexture {
|
||||
texture: texture.into(),
|
||||
// TODO: Find an alternate way to encode the transform and alpha_blend now that these fields have been moved up out of TextureFrame
|
||||
// TODO: Find an alternate way to encode the transform and alpha_blend now that these fields have been moved up out of ImageTexture
|
||||
// transform: input.transform,
|
||||
// alpha_blend: Default::default(),
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue