Add ability to import multiple mural

This commit is contained in:
2025-02-11 22:40:17 +01:00
parent 909188ba7a
commit 49f1cf008b
3 changed files with 80 additions and 60 deletions
+3 -3
View File
@@ -7,7 +7,7 @@ import { Store } from "../../lib/store";
import { MuralList } from "./muralList"; import { MuralList } from "./muralList";
import { Coordinates, CordType } from "../../lib/coordinates"; import { Coordinates, CordType } from "../../lib/coordinates";
import { Palette } from "../../lib/palette"; import { Palette } from "../../lib/palette";
import { importArtWork } from "../importMural"; import { importArtWorks } from "../importMural";
import { Popup } from "./Popup"; import { Popup } from "./Popup";
import { Storage } from "../../lib/storage"; import { Storage } from "../../lib/storage";
import { takeCanvasShot } from "../../lib/canvashot"; import { takeCanvasShot } from "../../lib/canvashot";
@@ -106,8 +106,8 @@ export class Menu extends React.Component<Props, State> {
import = async () => { import = async () => {
try { try {
const mural = await importArtWork(this.props.store, this.props.cords, this.props.palette); const murals = await importArtWorks(this.props.store, this.props.cords, this.props.palette);
if (mural) { for (const mural of murals) {
this.props.store.add(mural); this.props.store.add(mural);
} }
} catch (error) { } catch (error) {
-1
View File
@@ -14,7 +14,6 @@ import { BIN_FORMATS } from "../importMural";
import saveAs from "file-saver"; import saveAs from "file-saver";
import { Popup } from "./Popup"; import { Popup } from "./Popup";
import { Palette } from "../../lib/palette"; import { Palette } from "../../lib/palette";
import { Mural } from "../../lib/mural";
const Margin = styled.div` const Margin = styled.div`
margin: 2px; margin: 2px;
+40 -19
View File
@@ -85,11 +85,12 @@ export interface ImageToMuralOptions {
quantizerSetting: DitherSetting; quantizerSetting: DitherSetting;
} }
export async function importArtWork(store: Store, cords: Coordinates, palette: Palette) { export async function importArtWorks(store: Store, cords: Coordinates, palette: Palette) {
const file = await importFile(); const files = await importFiles();
if (file) { const output: MuralOld[] = [];
for (const file of files) {
if (file.type === "mural") { if (file.type === "mural") {
return file.data as MuralOld; output.push(file.data);
} else { } else {
const img = file.data as HTMLImageElement; const img = file.data as HTMLImageElement;
const pixels = await imageToMural(img, palette); const pixels = await imageToMural(img, palette);
@@ -111,9 +112,10 @@ export async function importArtWork(store: Store, cords: Coordinates, palette: P
}); });
}); });
validateMural(mural); validateMural(mural);
return mural; output.push(mural);
} }
} }
return output;
} }
export function getQuantizedObjFromUser(quantized: QuantResult[]) { export function getQuantizedObjFromUser(quantized: QuantResult[]) {
@@ -470,31 +472,48 @@ export function imageDataToCanvas(imageData: ImageData) {
return canvas; return canvas;
} }
async function importFile() { async function importFiles() {
const fileInput = new FileInput(); const fileInput = new FileInput();
fileInput.setAcceptType(["png", "jpg", "jpeg", ...TEXT_FORMATS, ...BIN_FORMATS]); const images = ["png", "jpg", "jpeg"];
fileInput.setAcceptType([...images, ...TEXT_FORMATS, ...BIN_FORMATS]);
fileInput.allowMultiple(true);
const files = await fileInput.show(); const files = await fileInput.show();
const fileData = files[0]; const filteredFiles = [...files].filter(e => e);
if (!fileData) { if (!filteredFiles.length) {
throw new Error("Empty file"); throw new Error("Empty file");
} }
const ex = getExtension(fileData.name); const imagesFiles = filteredFiles
.filter(e => images.some(r => e.name.toLowerCase().endsWith(r)));
if (imagesFiles.length > 1) {
throw new Error("Only one image files allowed to be imported at the time");
}
const output: ({
type: "mural",
data: MuralOld
} | {
type: "image",
data: HTMLImageElement
}) [] = [];
for (const file of filteredFiles) {
const ex = getExtension(file.name);
const etn = ex.ex.toLowerCase(); const etn = ex.ex.toLowerCase();
const name = ex.text; const name = ex.text;
if (TEXT_FORMATS.includes(etn)) { if (TEXT_FORMATS.includes(etn)) {
const content = await readAsString(fileData); const content = await readAsString(file);
const mural = JSON.parse(content) as MuralOld; const mural = JSON.parse(content) as MuralOld;
if (!mural.name) { if (!mural.name) {
mural.name = await Popup mural.name = await Popup
.prompt("Missing name for this mural. Please enter it manually", name) || ""; .prompt("Missing name for this mural. Please enter it manually", name) || "";
} }
return { output.push({
type: "mural", type: "mural",
data: mural, data: mural,
}; });
} else if (BIN_FORMATS.includes(etn)) { } else if (BIN_FORMATS.includes(etn)) {
const buffer = await readAsArrayBuffer(fileData); const buffer = await readAsArrayBuffer(file);
const mural = await Mural.from(new Uint8Array(buffer)); const mural = await Mural.from(new Uint8Array(buffer));
const pixelBuffer = mural.pixelBuffer; const pixelBuffer = mural.pixelBuffer;
const pixels = Array.from({ length: mural.h }, () => Array(mural.w).fill(0)); const pixels = Array.from({ length: mural.h }, () => Array(mural.w).fill(0));
@@ -518,17 +537,19 @@ async function importFile() {
} }
} }
} }
return { output.push({
type: "mural", type: "mural",
data: { data: {
name, x: mural.x, y: mural.y, pixels, name, x: mural.x, y: mural.y, pixels,
}, },
}; });
} else { } else {
const readData = await readAsDataUrl(fileData); const readData = await readAsDataUrl(file);
return { output.push({
type: "image", type: "image",
data: await loadImageSource(`${ex.text}.${ex.ex}`, readData), data: await loadImageSource(`${ex.text}.${ex.ex}`, readData),
}; });
} }
} }
return output;
}