Import ARW files as Images

This commit is contained in:
Elbert Ronnie
2024-11-11 02:50:31 +05:30
parent d649052255
commit 3d3233352b
10 changed files with 143 additions and 58 deletions
@@ -4,6 +4,7 @@
import type { DocumentState } from "@graphite/state-providers/document";
import { textInputCleanup } from "@graphite/utility-functions/keyboard-entry";
import { extractPixelData, rasterizeSVGCanvas } from "@graphite/utility-functions/rasterization";
import { extractContent } from "@graphite/utility-functions/files";
import { updateBoundsOfViewports } from "@graphite/utility-functions/viewports";
import type { Editor } from "@graphite/wasm-communication/editor";
import {
@@ -136,8 +137,12 @@
}
if (file.type.startsWith("image")) {
const imageData = await extractPixelData(file);
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, x, y);
if (file.type === "image/x-sony-arw") {
editor.handle.pasteRawImage(file.name, await extractContent(file), x, y);
} else {
const imageData = await extractPixelData(file);
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, x, y);
}
return;
}
+7 -2
View File
@@ -5,6 +5,7 @@
import type { NodeGraphState } from "@graphite/state-providers/node-graph";
import { platformIsMac } from "@graphite/utility-functions/platform";
import { extractPixelData } from "@graphite/utility-functions/rasterization";
import { extractContent } from "@graphite/utility-functions/files";
import type { Editor } from "@graphite/wasm-communication/editor";
import { defaultWidgetLayout, patchWidgetLayout, UpdateDocumentLayerDetails, UpdateDocumentLayerStructureJs, UpdateLayersPanelOptionsLayout } from "@graphite/wasm-communication/messages";
import type { DataBuffer, LayerPanelEntry } from "@graphite/wasm-communication/messages";
@@ -342,8 +343,12 @@
}
if (file.type.startsWith("image")) {
const imageData = await extractPixelData(file);
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, undefined, undefined, insertParentId, insertIndex);
if (file.type === "image/x-sony-arw") {
editor.handle.pasteRawImage(file.name, await extractContent(file), undefined, undefined, insertParentId, insertIndex);
} else {
const imageData = await extractPixelData(file);
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, undefined, undefined, insertParentId, insertIndex);
}
return;
}
@@ -17,6 +17,7 @@
import { platformIsMac, isEventSupported } from "@graphite/utility-functions/platform";
import { extractPixelData } from "@graphite/utility-functions/rasterization";
import { extractContent } from "@graphite/utility-functions/files";
import type { Editor } from "@graphite/wasm-communication/editor";
import { type LayoutKeysGroup, type Key } from "@graphite/wasm-communication/messages";
@@ -67,9 +68,12 @@
}
if (file.type.startsWith("image")) {
const imageData = await extractPixelData(file);
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height);
return;
if (file.type === "image/x-sony-arw") {
editor.handle.pasteRawImage(file.name, await extractContent(file));
} else {
const imageData = await extractPixelData(file);
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height);
}
}
if (file.name.endsWith(".graphite")) {
+13 -4
View File
@@ -7,6 +7,7 @@ import { type PortfolioState } from "@graphite/state-providers/portfolio";
import { makeKeyboardModifiersBitfield, textInputCleanup, getLocalizedScanCode } from "@graphite/utility-functions/keyboard-entry";
import { platformIsMac } from "@graphite/utility-functions/platform";
import { extractPixelData } from "@graphite/utility-functions/rasterization";
import { extractContent } from "@graphite/utility-functions/files"
import { stripIndents } from "@graphite/utility-functions/strip-indents";
import { updateBoundsOfViewports } from "@graphite/utility-functions/viewports";
import { type Editor } from "@graphite/wasm-communication/editor";
@@ -293,8 +294,12 @@ export function createInputManager(editor: Editor, dialog: DialogState, portfoli
}
if (file.type.startsWith("image")) {
const imageData = await extractPixelData(file);
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height);
if (file.type === "image/x-sony-arw") {
editor.handle.pasteRawImage(file.name, await extractContent(file));
} else {
const imageData = await extractPixelData(file);
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height);
}
}
if (file.name.endsWith(".graphite")) {
@@ -359,8 +364,12 @@ export function createInputManager(editor: Editor, dialog: DialogState, portfoli
const reader = new FileReader();
reader.onload = async () => {
if (reader.result instanceof ArrayBuffer) {
const imageData = await extractPixelData(new Blob([reader.result], { type: imageType }));
editor.handle.pasteImage(undefined, new Uint8Array(imageData.data), imageData.width, imageData.height);
if (imageType === "image/x-sony-arw") {
editor.handle.pasteRawImage(undefined, new Uint8Array(reader.result));
} else {
const imageData = await extractPixelData(new Blob([reader.result], { type: imageType }));
editor.handle.pasteImage(undefined, new Uint8Array(imageData.data), imageData.width, imageData.height);
}
}
};
reader.readAsArrayBuffer(blob);
@@ -79,6 +79,11 @@ export function createPortfolioState(editor: Editor) {
return;
}
if (data.type === "image/x-sony-arw") {
editor.handle.pasteRawImage(data.filename, data.content.data);
return;
}
const imageData = await extractPixelData(new Blob([data.content.data], { type: data.type }));
editor.handle.pasteImage(data.filename, new Uint8Array(imageData.data), imageData.width, imageData.height);
});
+10
View File
@@ -88,3 +88,13 @@ export async function replaceBlobURLsWithBase64(svg: string): Promise<string> {
});
return substituted.join("");
}
/// Extract the contents of a file or blob and return an Uint8Array
export async function extractContent(blob: Blob): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(new Uint8Array(reader.result));
reader.onerror = () => reject(new Error('Error reading the blob.'));
reader.readAsArrayBuffer(blob);
});
}
+1
View File
@@ -36,6 +36,7 @@ serde-wasm-bindgen = { workspace = true }
js-sys = { workspace = true }
wasm-bindgen-futures = { workspace = true }
bezier-rs = { workspace = true }
rawkit = { workspace = true }
glam = { workspace = true }
meval = { workspace = true }
wgpu = { workspace = true, features = [
+14
View File
@@ -19,9 +19,11 @@ use editor::messages::tool::tool_messages::tool_prelude::WidgetId;
use graph_craft::document::NodeId;
use graphene_core::raster::color::Color;
use rawkit::RawImage;
use serde::Serialize;
use serde_wasm_bindgen::{self, from_value};
use std::cell::RefCell;
use std::io::Cursor;
use std::sync::atomic::Ordering;
use std::time::Duration;
use wasm_bindgen::prelude::*;
@@ -621,6 +623,18 @@ impl EditorHandle {
self.dispatch(message);
}
/// Pastes a Raw Image
#[wasm_bindgen(js_name = pasteRawImage)]
pub fn paste_raw_image(&self, name: Option<String>, file_data: Vec<u8>, mouse_x: Option<f64>, mouse_y: Option<f64>, insert_parent_id: Option<u64>, insert_index: Option<usize>) {
let mut content = Cursor::new(&file_data);
let raw_image = RawImage::decode(&mut content).unwrap();
let image = raw_image.process_8bit();
let data = image.data.chunks(image.channels as usize).flat_map(|pixel| [pixel[0], pixel[1], pixel[2], u8::MAX]).collect();
self.paste_image(name, data, image.width as u32, image.height as u32, mouse_x, mouse_y, insert_parent_id, insert_index)
}
#[wasm_bindgen(js_name = pasteSvg)]
pub fn paste_svg(&self, name: Option<String>, svg: String, mouse_x: Option<f64>, mouse_y: Option<f64>, insert_parent_id: Option<u64>, insert_index: Option<usize>) {
let mouse = mouse_x.and_then(|x| mouse_y.map(|y| (x, y)));