This commit is contained in:
syuilo 2025-10-30 18:14:41 +09:00
parent 98774208a2
commit 8d2bc9b84f
4 changed files with 40 additions and 29 deletions

6
locales/index.d.ts vendored
View File

@ -5611,9 +5611,13 @@ export interface Locale extends ILocale {
*/
"title": string;
/**
*
*
*/
"frameThickness": string;
/**
*
*/
"labelThickness": string;
/**
*
*/

View File

@ -1399,7 +1399,8 @@ deviceInfoDescription: "技術的なお問い合わせの際に、以下の情
_imageLabelEditor:
title: "ラベルの編集"
frameThickness: "フレーム"
frameThickness: "フレームの幅"
labelThickness: "ラベルの幅"
centered: "中央揃え"
captionMain: "キャプション(大)"
captionSub: "キャプション(小)"

View File

@ -34,6 +34,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts._imageLabelEditor.frameThickness }}</template>
</MkRange>
<MkRange v-model="frame.labelThickness" :min="0.1" :max="0.3" :step="0.01" :continuousUpdate="true">
<template #label>{{ i18n.ts._imageLabelEditor.labelThickness }}</template>
</MkRange>
<MkSwitch v-model="frame.centered">
<template #label>{{ i18n.ts._imageLabelEditor.centered }}</template>
</MkSwitch>
@ -109,6 +113,7 @@ const props = defineProps<{
const frame = reactive<ImageLabelParams>(deepClone(props.frame) ?? {
style: 'frame',
frameThickness: 0.05,
labelThickness: 0.2,
title: 'Untitled by @syuilo',
text: '{mm}mm f/{f} {s}s ISO{iso}',
centered: false,

View File

@ -18,6 +18,7 @@ const FXS = [
export type ImageLabelParams = {
style: 'frame' | 'frameLess';
frameThickness: number;
labelThickness: number;
title: string;
text: string;
centered: boolean;
@ -26,11 +27,9 @@ export type ImageLabelParams = {
export class ImageLabelRenderer {
private effector: ImageEffector<typeof FXS>;
private renderWidth: number;
private renderHeight: number;
private image: HTMLImageElement | ImageBitmap;
private paddingBottom = 0;
private exif: ExifReader.Tags;
private renderAsPreview = false;
constructor(options: {
canvas: HTMLCanvasElement,
@ -40,30 +39,13 @@ export class ImageLabelRenderer {
}) {
this.image = options.image;
this.exif = options.exif;
this.renderAsPreview = options.renderAsPreview ?? false;
console.log(this.exif);
let w = this.image.width;
let h = this.image.height;
if (options.renderAsPreview) {
const MAX_W = 1000;
const MAX_H = 1000;
if (w > MAX_W || h > MAX_H) {
const scale = Math.min(MAX_W / w, MAX_H / h);
w = Math.floor(w * scale);
h = Math.floor(h * scale);
}
}
this.paddingBottom = Math.floor(h * 0.2);
this.renderWidth = w;
this.renderHeight = h + this.paddingBottom;
this.effector = new ImageEffector({
canvas: options.canvas,
renderWidth: this.renderWidth,
renderHeight: this.renderHeight,
renderWidth: 1,
renderHeight: 1,
image: null,
fxs: FXS,
});
@ -89,10 +71,28 @@ export class ImageLabelRenderer {
}
public async update(params: ImageLabelParams): Promise<void> {
const aspectRatio = this.renderWidth / this.renderHeight;
let w = this.image.width;
let h = this.image.height;
if (this.renderAsPreview) {
const MAX_W = 1000;
const MAX_H = 1000;
if (w > MAX_W || h > MAX_H) {
const scale = Math.min(MAX_W / w, MAX_H / h);
w = Math.floor(w * scale);
h = Math.floor(h * scale);
}
}
const paddingBottom = Math.floor(h * params.labelThickness);
const renderWidth = w;
const renderHeight = h + paddingBottom;
const aspectRatio = renderWidth / renderHeight;
const ctx = window.document.createElement('canvas').getContext('2d')!;
ctx.canvas.width = this.renderWidth;
ctx.canvas.height = this.paddingBottom;
ctx.canvas.width = renderWidth;
ctx.canvas.height = paddingBottom;
const fontSize = ctx.canvas.height / 6;
const marginX = Math.max(fontSize * 2, (ctx.canvas.width * params.frameThickness) / aspectRatio);
const withQrCode = params.withQrCode;
@ -184,6 +184,8 @@ export class ImageLabelRenderer {
await this.effector.registerTexture('label', data);
this.effector.changeResolution(renderWidth, renderHeight);
await this.effector.setLayers([{
fxId: 'label',
id: 'a',
@ -194,7 +196,6 @@ export class ImageLabelRenderer {
imageMarginY: paddingY,
},
}]);
this.render();
}
public render(): void {