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;
+77 -56
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,65 +472,84 @@ 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
const etn = ex.ex.toLowerCase(); .filter(e => images.some(r => e.name.toLowerCase().endsWith(r)));
const name = ex.text;
if (TEXT_FORMATS.includes(etn)) {
const content = await readAsString(fileData);
const mural = JSON.parse(content) as MuralOld;
if (!mural.name) {
mural.name = await Popup
.prompt("Missing name for this mural. Please enter it manually", name) || "";
}
return { if (imagesFiles.length > 1) {
type: "mural", throw new Error("Only one image files allowed to be imported at the time");
data: mural, }
};
} else if (BIN_FORMATS.includes(etn)) { const output: ({
const buffer = await readAsArrayBuffer(fileData); type: "mural",
const mural = await Mural.from(new Uint8Array(buffer)); data: MuralOld
const pixelBuffer = mural.pixelBuffer; } | {
const pixels = Array.from({ length: mural.h }, () => Array(mural.w).fill(0)); type: "image",
let i = 0; data: HTMLImageElement
let yy = -1; }) [] = [];
leg: for (const file of filteredFiles) {
for (;;) { const ex = getExtension(file.name);
yy++; const etn = ex.ex.toLowerCase();
if (pixelBuffer[i] === undefined) { const name = ex.text;
break; if (TEXT_FORMATS.includes(etn)) {
const content = await readAsString(file);
const mural = JSON.parse(content) as MuralOld;
if (!mural.name) {
mural.name = await Popup
.prompt("Missing name for this mural. Please enter it manually", name) || "";
} }
// const ref = [];
// pixels.push(ref); output.push({
for (let xx = 0; xx < mural.w; xx++) { type: "mural",
const item = pixelBuffer[i++]; data: mural,
if (item != undefined) { });
pixels[yy][xx] = item; } else if (BIN_FORMATS.includes(etn)) {
//ref.push(item); const buffer = await readAsArrayBuffer(file);
} else { const mural = await Mural.from(new Uint8Array(buffer));
break leg; const pixelBuffer = mural.pixelBuffer;
const pixels = Array.from({ length: mural.h }, () => Array(mural.w).fill(0));
let i = 0;
let yy = -1;
leg:
for (;;) {
yy++;
if (pixelBuffer[i] === undefined) {
break;
}
// const ref = [];
// pixels.push(ref);
for (let xx = 0; xx < mural.w; xx++) {
const item = pixelBuffer[i++];
if (item != undefined) {
pixels[yy][xx] = item;
//ref.push(item);
} else {
break leg;
}
} }
} }
output.push({
type: "mural",
data: {
name, x: mural.x, y: mural.y, pixels,
},
});
} else {
const readData = await readAsDataUrl(file);
output.push({
type: "image",
data: await loadImageSource(`${ex.text}.${ex.ex}`, readData),
});
} }
return {
type: "mural",
data: {
name, x: mural.x, y: mural.y, pixels,
},
};
} else {
const readData = await readAsDataUrl(fileData);
return {
type: "image",
data: await loadImageSource(`${ex.text}.${ex.ex}`, readData),
};
} }
return output;
} }