wip
This commit is contained in:
parent
e3ef2c43cc
commit
d1b4456845
|
@ -61,7 +61,7 @@ import { deepClone } from '@/utility/clone.js';
|
||||||
import { FXS } from '@/utility/image-effector/fxs.js';
|
import { FXS } from '@/utility/image-effector/fxs.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
image: HTMLImageElement;
|
image: ImageBitmap;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|
|
@ -297,9 +297,9 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
|
||||||
icon: 'ti ti-sparkles',
|
icon: 'ti ti-sparkles',
|
||||||
text: i18n.ts._imageEffector.title,
|
text: i18n.ts._imageEffector.title,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
const imgElementCtx = await getImageElement(item.file);
|
const imageBitmap = await window.createImageBitmap(item.file);
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkImageEffectorDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkImageEffectorDialog.vue')), {
|
||||||
image: imgElementCtx.img,
|
image: imageBitmap,
|
||||||
}, {
|
}, {
|
||||||
ok: (file) => {
|
ok: (file) => {
|
||||||
URL.revokeObjectURL(item.thumbnail);
|
URL.revokeObjectURL(item.thumbnail);
|
||||||
|
@ -314,7 +314,7 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
imgElementCtx.dispose();
|
imageBitmap.close();
|
||||||
dispose();
|
dispose();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -353,16 +353,16 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
|
||||||
icon: 'ti ti-plus',
|
icon: 'ti ti-plus',
|
||||||
text: i18n.ts.add,
|
text: i18n.ts.add,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
const imgElementCtx = await getImageElement(item.file);
|
const imageBitmap = await window.createImageBitmap(item.file);
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkWatermarkEditorDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkWatermarkEditorDialog.vue')), {
|
||||||
image: imgElementCtx.img,
|
image: imageBitmap,
|
||||||
}, {
|
}, {
|
||||||
ok: (preset) => {
|
ok: (preset) => {
|
||||||
prefer.commit('watermarkPresets', [...prefer.s.watermarkPresets, preset]);
|
prefer.commit('watermarkPresets', [...prefer.s.watermarkPresets, preset]);
|
||||||
changeWatermarkPreset(preset.id);
|
changeWatermarkPreset(preset.id);
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
imgElementCtx.dispose();
|
imageBitmap.close();
|
||||||
dispose();
|
dispose();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -515,35 +515,11 @@ async function chooseFile(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用後は dispose() でメモリの解放を忘れないように!!!
|
|
||||||
*/
|
|
||||||
function getImageElement(file: Blob | File): Promise<{ img: HTMLImageElement, dispose: () => void }> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const img = new Image();
|
|
||||||
|
|
||||||
img.onload = () => {
|
|
||||||
resolve({
|
|
||||||
img: markRaw(img),
|
|
||||||
dispose: () => {
|
|
||||||
URL.revokeObjectURL(img.src);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
img.onerror = (error) => {
|
|
||||||
reject(error);
|
|
||||||
};
|
|
||||||
|
|
||||||
img.src = URL.createObjectURL(file);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function preprocess(item: (typeof items)['value'][number]): Promise<void> {
|
async function preprocess(item: (typeof items)['value'][number]): Promise<void> {
|
||||||
item.preprocessing = true;
|
item.preprocessing = true;
|
||||||
|
|
||||||
let file: Blob | File = item.file;
|
let file: Blob | File = item.file;
|
||||||
const imgElementCtx = await getImageElement(file);
|
const imageBitmap = await window.createImageBitmap(file);
|
||||||
|
|
||||||
const needsWatermark = item.watermarkPresetId != null && WATERMARK_SUPPORTED_TYPES.includes(file.type);
|
const needsWatermark = item.watermarkPresetId != null && WATERMARK_SUPPORTED_TYPES.includes(file.type);
|
||||||
const preset = prefer.s.watermarkPresets.find(p => p.id === item.watermarkPresetId);
|
const preset = prefer.s.watermarkPresets.find(p => p.id === item.watermarkPresetId);
|
||||||
|
@ -551,9 +527,9 @@ async function preprocess(item: (typeof items)['value'][number]): Promise<void>
|
||||||
const canvas = window.document.createElement('canvas');
|
const canvas = window.document.createElement('canvas');
|
||||||
const renderer = new WatermarkRenderer({
|
const renderer = new WatermarkRenderer({
|
||||||
canvas: canvas,
|
canvas: canvas,
|
||||||
renderWidth: imgElementCtx.img.width,
|
renderWidth: imageBitmap.width,
|
||||||
renderHeight: imgElementCtx.img.height,
|
renderHeight: imageBitmap.height,
|
||||||
image: imgElementCtx.img,
|
image: imageBitmap,
|
||||||
});
|
});
|
||||||
|
|
||||||
await renderer.setLayers(preset.layers);
|
await renderer.setLayers(preset.layers);
|
||||||
|
@ -604,7 +580,7 @@ async function preprocess(item: (typeof items)['value'][number]): Promise<void>
|
||||||
item.preprocessedFile = markRaw(file);
|
item.preprocessedFile = markRaw(file);
|
||||||
item.preprocessing = false;
|
item.preprocessing = false;
|
||||||
|
|
||||||
imgElementCtx.dispose();
|
imageBitmap.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeFile(file: File) {
|
function initializeFile(file: File) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ const $i = ensureSignin();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
preset?: WatermarkPreset | null;
|
preset?: WatermarkPreset | null;
|
||||||
image?: HTMLImageElement | null;
|
image?: ImageBitmap | null;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const preset = reactive(deepClone(props.preset) ?? {
|
const preset = reactive(deepClone(props.preset) ?? {
|
||||||
|
@ -168,10 +168,21 @@ async function initRenderer() {
|
||||||
image: sampleImage_2_3,
|
image: sampleImage_2_3,
|
||||||
});
|
});
|
||||||
} else if (props.image != null) {
|
} else if (props.image != null) {
|
||||||
|
const MAX_W = 1000;
|
||||||
|
const MAX_H = 1000;
|
||||||
|
let w = props.image.width;
|
||||||
|
let h = props.image.height;
|
||||||
|
|
||||||
|
if (w > MAX_W || h > MAX_H) {
|
||||||
|
const scale = Math.min(MAX_W / w, MAX_H / h);
|
||||||
|
w *= scale;
|
||||||
|
h *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
renderer = new WatermarkRenderer({
|
renderer = new WatermarkRenderer({
|
||||||
canvas: canvasEl.value,
|
canvas: canvasEl.value,
|
||||||
renderWidth: props.image.width,
|
renderWidth: w,
|
||||||
renderHeight: props.image.height,
|
renderHeight: h,
|
||||||
image: props.image,
|
image: props.image,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ export class WatermarkRenderer {
|
||||||
canvas: HTMLCanvasElement,
|
canvas: HTMLCanvasElement,
|
||||||
renderWidth: number,
|
renderWidth: number,
|
||||||
renderHeight: number,
|
renderHeight: number,
|
||||||
image: HTMLImageElement,
|
image: HTMLImageElement | ImageBitmap,
|
||||||
}) {
|
}) {
|
||||||
this.effector = new ImageEffector({
|
this.effector = new ImageEffector({
|
||||||
canvas: options.canvas,
|
canvas: options.canvas,
|
||||||
|
|
Loading…
Reference in New Issue