Skip to content

Commit 3d32333

Browse files
committed
Import ARW files as Images
1 parent d649052 commit 3d32333

File tree

10 files changed

+143
-58
lines changed

10 files changed

+143
-58
lines changed

Cargo.lock

+78-47
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ syn = { version = "2.0", default-features = false, features = [
9393
"derive",
9494
] }
9595
kurbo = { version = "0.11.0", features = ["serde"] }
96+
rawkit = "0.1.0"
9697

9798
[patch.crates-io]
9899
meval = { git = "https://github.com/Titaniumtown/meval-rs" }

frontend/src/components/panels/Document.svelte

+7-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import type { DocumentState } from "@graphite/state-providers/document";
55
import { textInputCleanup } from "@graphite/utility-functions/keyboard-entry";
66
import { extractPixelData, rasterizeSVGCanvas } from "@graphite/utility-functions/rasterization";
7+
import { extractContent } from "@graphite/utility-functions/files";
78
import { updateBoundsOfViewports } from "@graphite/utility-functions/viewports";
89
import type { Editor } from "@graphite/wasm-communication/editor";
910
import {
@@ -136,8 +137,12 @@
136137
}
137138
138139
if (file.type.startsWith("image")) {
139-
const imageData = await extractPixelData(file);
140-
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, x, y);
140+
if (file.type === "image/x-sony-arw") {
141+
editor.handle.pasteRawImage(file.name, await extractContent(file), x, y);
142+
} else {
143+
const imageData = await extractPixelData(file);
144+
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, x, y);
145+
}
141146
return;
142147
}
143148

frontend/src/components/panels/Layers.svelte

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import type { NodeGraphState } from "@graphite/state-providers/node-graph";
66
import { platformIsMac } from "@graphite/utility-functions/platform";
77
import { extractPixelData } from "@graphite/utility-functions/rasterization";
8+
import { extractContent } from "@graphite/utility-functions/files";
89
import type { Editor } from "@graphite/wasm-communication/editor";
910
import { defaultWidgetLayout, patchWidgetLayout, UpdateDocumentLayerDetails, UpdateDocumentLayerStructureJs, UpdateLayersPanelOptionsLayout } from "@graphite/wasm-communication/messages";
1011
import type { DataBuffer, LayerPanelEntry } from "@graphite/wasm-communication/messages";
@@ -342,8 +343,12 @@
342343
}
343344
344345
if (file.type.startsWith("image")) {
345-
const imageData = await extractPixelData(file);
346-
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, undefined, undefined, insertParentId, insertIndex);
346+
if (file.type === "image/x-sony-arw") {
347+
editor.handle.pasteRawImage(file.name, await extractContent(file), undefined, undefined, insertParentId, insertIndex);
348+
} else {
349+
const imageData = await extractPixelData(file);
350+
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, undefined, undefined, insertParentId, insertIndex);
351+
}
347352
return;
348353
}
349354

frontend/src/components/window/workspace/Panel.svelte

+7-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import { platformIsMac, isEventSupported } from "@graphite/utility-functions/platform";
1818
1919
import { extractPixelData } from "@graphite/utility-functions/rasterization";
20+
import { extractContent } from "@graphite/utility-functions/files";
2021
import type { Editor } from "@graphite/wasm-communication/editor";
2122
import { type LayoutKeysGroup, type Key } from "@graphite/wasm-communication/messages";
2223
@@ -67,9 +68,12 @@
6768
}
6869
6970
if (file.type.startsWith("image")) {
70-
const imageData = await extractPixelData(file);
71-
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height);
72-
return;
71+
if (file.type === "image/x-sony-arw") {
72+
editor.handle.pasteRawImage(file.name, await extractContent(file));
73+
} else {
74+
const imageData = await extractPixelData(file);
75+
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height);
76+
}
7377
}
7478
7579
if (file.name.endsWith(".graphite")) {

frontend/src/io-managers/input.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { type PortfolioState } from "@graphite/state-providers/portfolio";
77
import { makeKeyboardModifiersBitfield, textInputCleanup, getLocalizedScanCode } from "@graphite/utility-functions/keyboard-entry";
88
import { platformIsMac } from "@graphite/utility-functions/platform";
99
import { extractPixelData } from "@graphite/utility-functions/rasterization";
10+
import { extractContent } from "@graphite/utility-functions/files"
1011
import { stripIndents } from "@graphite/utility-functions/strip-indents";
1112
import { updateBoundsOfViewports } from "@graphite/utility-functions/viewports";
1213
import { type Editor } from "@graphite/wasm-communication/editor";
@@ -293,8 +294,12 @@ export function createInputManager(editor: Editor, dialog: DialogState, portfoli
293294
}
294295

295296
if (file.type.startsWith("image")) {
296-
const imageData = await extractPixelData(file);
297-
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height);
297+
if (file.type === "image/x-sony-arw") {
298+
editor.handle.pasteRawImage(file.name, await extractContent(file));
299+
} else {
300+
const imageData = await extractPixelData(file);
301+
editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height);
302+
}
298303
}
299304

300305
if (file.name.endsWith(".graphite")) {
@@ -359,8 +364,12 @@ export function createInputManager(editor: Editor, dialog: DialogState, portfoli
359364
const reader = new FileReader();
360365
reader.onload = async () => {
361366
if (reader.result instanceof ArrayBuffer) {
362-
const imageData = await extractPixelData(new Blob([reader.result], { type: imageType }));
363-
editor.handle.pasteImage(undefined, new Uint8Array(imageData.data), imageData.width, imageData.height);
367+
if (imageType === "image/x-sony-arw") {
368+
editor.handle.pasteRawImage(undefined, new Uint8Array(reader.result));
369+
} else {
370+
const imageData = await extractPixelData(new Blob([reader.result], { type: imageType }));
371+
editor.handle.pasteImage(undefined, new Uint8Array(imageData.data), imageData.width, imageData.height);
372+
}
364373
}
365374
};
366375
reader.readAsArrayBuffer(blob);

frontend/src/state-providers/portfolio.ts

+5
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ export function createPortfolioState(editor: Editor) {
7979
return;
8080
}
8181

82+
if (data.type === "image/x-sony-arw") {
83+
editor.handle.pasteRawImage(data.filename, data.content.data);
84+
return;
85+
}
86+
8287
const imageData = await extractPixelData(new Blob([data.content.data], { type: data.type }));
8388
editor.handle.pasteImage(data.filename, new Uint8Array(imageData.data), imageData.width, imageData.height);
8489
});

frontend/src/utility-functions/files.ts

+10
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,13 @@ export async function replaceBlobURLsWithBase64(svg: string): Promise<string> {
8888
});
8989
return substituted.join("");
9090
}
91+
92+
/// Extract the contents of a file or blob and return an Uint8Array
93+
export async function extractContent(blob: Blob): Promise<Uint8Array> {
94+
return new Promise((resolve, reject) => {
95+
const reader = new FileReader();
96+
reader.onload = () => resolve(new Uint8Array(reader.result));
97+
reader.onerror = () => reject(new Error('Error reading the blob.'));
98+
reader.readAsArrayBuffer(blob);
99+
});
100+
}

frontend/wasm/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ serde-wasm-bindgen = { workspace = true }
3636
js-sys = { workspace = true }
3737
wasm-bindgen-futures = { workspace = true }
3838
bezier-rs = { workspace = true }
39+
rawkit = { workspace = true }
3940
glam = { workspace = true }
4041
meval = { workspace = true }
4142
wgpu = { workspace = true, features = [

frontend/wasm/src/editor_api.rs

+14
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ use editor::messages::tool::tool_messages::tool_prelude::WidgetId;
1919
use graph_craft::document::NodeId;
2020
use graphene_core::raster::color::Color;
2121

22+
use rawkit::RawImage;
2223
use serde::Serialize;
2324
use serde_wasm_bindgen::{self, from_value};
2425
use std::cell::RefCell;
26+
use std::io::Cursor;
2527
use std::sync::atomic::Ordering;
2628
use std::time::Duration;
2729
use wasm_bindgen::prelude::*;
@@ -621,6 +623,18 @@ impl EditorHandle {
621623
self.dispatch(message);
622624
}
623625

626+
/// Pastes a Raw Image
627+
#[wasm_bindgen(js_name = pasteRawImage)]
628+
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>) {
629+
let mut content = Cursor::new(&file_data);
630+
let raw_image = RawImage::decode(&mut content).unwrap();
631+
let image = raw_image.process_8bit();
632+
633+
let data = image.data.chunks(image.channels as usize).flat_map(|pixel| [pixel[0], pixel[1], pixel[2], u8::MAX]).collect();
634+
635+
self.paste_image(name, data, image.width as u32, image.height as u32, mouse_x, mouse_y, insert_parent_id, insert_index)
636+
}
637+
624638
#[wasm_bindgen(js_name = pasteSvg)]
625639
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>) {
626640
let mouse = mouse_x.and_then(|x| mouse_y.map(|y| (x, y)));

0 commit comments

Comments
 (0)