mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-23 14:34:06 +00:00
Improve the HTTP request nodes and add new related nodes (#2896)
* Improve the network request nodes and add new ones to process data * Use Content-Type: application/octet-stream * Add 'Gamma Correction' node
This commit is contained in:
parent
561b671f8d
commit
6f46f21e21
6 changed files with 118 additions and 13 deletions
|
@ -835,6 +835,20 @@ impl Color {
|
||||||
[(gamma.red * 255.) as u8, (gamma.green * 255.) as u8, (gamma.blue * 255.) as u8, (gamma.alpha * 255.) as u8]
|
[(gamma.red * 255.) as u8, (gamma.green * 255.) as u8, (gamma.blue * 255.) as u8, (gamma.alpha * 255.) as u8]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the all RGB components as a u8 slice, first component is red, followed by green, followed by blue. Use this if the [`Color`] is in linear space.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use graphene_core::color::Color;
|
||||||
|
/// let color = Color::from_rgbaf32(0.114, 0.103, 0.98, 0.97).unwrap();
|
||||||
|
/// // TODO: Add test
|
||||||
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn to_rgb8_srgb(&self) -> [u8; 3] {
|
||||||
|
let gamma = self.to_gamma_srgb();
|
||||||
|
[(gamma.red * 255.) as u8, (gamma.green * 255.) as u8, (gamma.blue * 255.) as u8]
|
||||||
|
}
|
||||||
|
|
||||||
// https://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
|
// https://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
|
||||||
/// Convert a [Color] to a hue, saturation, lightness and alpha (all between 0 and 1)
|
/// Convert a [Color] to a hue, saturation, lightness and alpha (all between 0 and 1)
|
||||||
///
|
///
|
||||||
|
|
|
@ -10,10 +10,18 @@ use crate::{Context, Ctx};
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
|
|
||||||
#[node_macro::node(category("Text"))]
|
#[node_macro::node(category("Text"))]
|
||||||
fn to_string<T: std::fmt::Debug>(_: impl Ctx, #[implementations(String, bool, f64, u32, u64, DVec2, VectorDataTable, DAffine2)] value: T) -> String {
|
fn to_string<T: std::fmt::Debug>(_: impl Ctx, #[implementations(String, bool, f64, u32, u64, DVec2, DAffine2, VectorDataTable)] value: T) -> String {
|
||||||
format!("{:?}", value)
|
format!("{:?}", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[node_macro::node(category("Text"))]
|
||||||
|
fn serialize<T: serde::Serialize>(
|
||||||
|
_: impl Ctx,
|
||||||
|
#[implementations(String, bool, f64, u32, u64, DVec2, DAffine2, Color, Option<Color>, GraphicGroupTable, VectorDataTable, RasterDataTable<CPU>)] value: T,
|
||||||
|
) -> String {
|
||||||
|
serde_json::to_string(&value).unwrap_or_else(|_| "Serialization Error".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("Text"))]
|
#[node_macro::node(category("Text"))]
|
||||||
fn string_concatenate(_: impl Ctx, #[implementations(String)] first: String, second: TextArea) -> String {
|
fn string_concatenate(_: impl Ctx, #[implementations(String)] first: String, second: TextArea) -> String {
|
||||||
first.clone() + &second
|
first.clone() + &second
|
||||||
|
|
|
@ -65,6 +65,26 @@ fn luminance<T: Adjust<Color>>(
|
||||||
input
|
input
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[node_macro::node(category("Raster"))]
|
||||||
|
fn gamma_correction<T: Adjust<Color>>(
|
||||||
|
_: impl Ctx,
|
||||||
|
#[implementations(
|
||||||
|
Color,
|
||||||
|
RasterDataTable<CPU>,
|
||||||
|
GradientStops,
|
||||||
|
)]
|
||||||
|
mut input: T,
|
||||||
|
#[default(2.2)]
|
||||||
|
#[range((0.01, 10.))]
|
||||||
|
#[hard_min(0.0001)]
|
||||||
|
gamma: f64,
|
||||||
|
inverse: bool,
|
||||||
|
) -> T {
|
||||||
|
let exponent = if inverse { 1. / gamma } else { gamma };
|
||||||
|
input.adjust(|color| color.gamma(exponent as f32));
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("Raster: Channels"))]
|
#[node_macro::node(category("Raster: Channels"))]
|
||||||
fn extract_channel<T: Adjust<Color>>(
|
fn extract_channel<T: Adjust<Color>>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
use graphene_core::Ctx;
|
|
||||||
|
|
||||||
#[node_macro::node(category("Web Request"))]
|
|
||||||
async fn get_request(_: impl Ctx, url: String) -> reqwest::Response {
|
|
||||||
reqwest::get(url).await.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[node_macro::node(category("Web Request"))]
|
|
||||||
async fn post_request(_: impl Ctx, url: String, body: String) -> reqwest::Response {
|
|
||||||
reqwest::Client::new().post(url).body(body).send().await.unwrap()
|
|
||||||
}
|
|
|
@ -1,5 +1,4 @@
|
||||||
pub mod any;
|
pub mod any;
|
||||||
pub mod http;
|
|
||||||
pub mod text;
|
pub mod text;
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
pub mod wasm_application_io;
|
pub mod wasm_application_io;
|
||||||
|
|
|
@ -59,6 +59,81 @@ async fn create_surface<'a: 'n>(_: impl Ctx, editor: &'a WasmEditorApi) -> Arc<W
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
#[node_macro::node(category("Web Request"))]
|
||||||
|
async fn get_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, discard_result: bool) -> String {
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
if discard_result {
|
||||||
|
wasm_bindgen_futures::spawn_local(async move {
|
||||||
|
let _ = reqwest::get(url).await;
|
||||||
|
});
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
{
|
||||||
|
#[cfg(feature = "tokio")]
|
||||||
|
if discard_result {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let _ = reqwest::get(url).await;
|
||||||
|
});
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "tokio"))]
|
||||||
|
if discard_result {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(response) = reqwest::get(url).await else { return String::new() };
|
||||||
|
response.text().await.ok().unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[node_macro::node(category("Web Request"))]
|
||||||
|
async fn post_request(_: impl Ctx, _primary: (), #[name("URL")] url: String, body: Vec<u8>, discard_result: bool) -> String {
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
if discard_result {
|
||||||
|
wasm_bindgen_futures::spawn_local(async move {
|
||||||
|
let _ = reqwest::Client::new().post(url).body(body).header("Content-Type", "application/octet-stream").send().await;
|
||||||
|
});
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
{
|
||||||
|
#[cfg(feature = "tokio")]
|
||||||
|
if discard_result {
|
||||||
|
let url = url.clone();
|
||||||
|
let body = body.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let _ = reqwest::Client::new().post(url).body(body).header("Content-Type", "application/octet-stream").send().await;
|
||||||
|
});
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "tokio"))]
|
||||||
|
if discard_result {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(response) = reqwest::Client::new().post(url).body(body).header("Content-Type", "application/octet-stream").send().await else {
|
||||||
|
return String::new();
|
||||||
|
};
|
||||||
|
response.text().await.ok().unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[node_macro::node(category("Web Request"), name("String to Bytes"))]
|
||||||
|
fn string_to_bytes(_: impl Ctx, string: String) -> Vec<u8> {
|
||||||
|
string.into_bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[node_macro::node(category("Web Request"), name("Image to Bytes"))]
|
||||||
|
fn image_to_bytes(_: impl Ctx, image: RasterDataTable<CPU>) -> Vec<u8> {
|
||||||
|
let Some(image) = image.instance_ref_iter().next() else { return vec![] };
|
||||||
|
image.instance.data.iter().flat_map(|color| color.to_rgb8_srgb().into_iter()).collect::<Vec<u8>>()
|
||||||
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("Web Request"))]
|
#[node_macro::node(category("Web Request"))]
|
||||||
async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")] editor: &'a WasmEditorApi, #[name("URL")] url: String) -> Arc<[u8]> {
|
async fn load_resource<'a: 'n>(_: impl Ctx, _primary: (), #[scope("editor-api")] editor: &'a WasmEditorApi, #[name("URL")] url: String) -> Arc<[u8]> {
|
||||||
let Some(api) = editor.application_io.as_ref() else {
|
let Some(api) = editor.application_io.as_ref() else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue