From fad3aed79ec8efb605e355539db9cb4be19032d8 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Wed, 28 May 2025 13:59:08 +0900
Subject: [PATCH] wip
---
locales/index.d.ts | 4 +++
locales/ja-JP.yml | 1 +
.../MkWatermarkEditorDialog.Layer.vue | 4 +++
.../frontend/src/utility/ImageEffector.ts | 25 ++++++++++++++++---
4 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 64a2534789..459733710c 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -12033,6 +12033,10 @@ export interface Locale extends ILocale {
* ウォーターマークの編集
*/
"title": string;
+ /**
+ * 全体に被せる
+ */
+ "cover": string;
/**
* 敷き詰める
*/
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 66a77a0c2c..041c7e22e0 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -3223,6 +3223,7 @@ defaultPreset: "デフォルトのプリセット"
_watermarkEditor:
tip: "画像にクレジット情報などのウォーターマークを追加することができます。"
title: "ウォーターマークの編集"
+ cover: "全体に被せる"
repeat: "敷き詰める"
opacity: "不透明度"
scale: "サイズ"
diff --git a/packages/frontend/src/components/MkWatermarkEditorDialog.Layer.vue b/packages/frontend/src/components/MkWatermarkEditorDialog.Layer.vue
index d1dac42104..06c36063d8 100644
--- a/packages/frontend/src/components/MkWatermarkEditorDialog.Layer.vue
+++ b/packages/frontend/src/components/MkWatermarkEditorDialog.Layer.vue
@@ -80,6 +80,10 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._watermarkEditor.repeat }}
+
+
+ {{ i18n.ts._watermarkEditor.cover }}
+
diff --git a/packages/frontend/src/utility/ImageEffector.ts b/packages/frontend/src/utility/ImageEffector.ts
index 10975bc921..171bece7d7 100644
--- a/packages/frontend/src/utility/ImageEffector.ts
+++ b/packages/frontend/src/utility/ImageEffector.ts
@@ -19,16 +19,29 @@ uniform float u_opacity;
uniform bool u_repeat;
uniform int u_alignX; // 0: left, 1: center, 2: right
uniform int u_alignY; // 0: top, 1: center, 2: bottom
+uniform int u_fitMode; // 0: contain, 1: cover
out vec4 out_color;
void main() {
vec4 pixel = texture(u_texture_src, in_uv);
+ bool contain = u_fitMode == 0;
+
float x_ratio = u_resolution_watermark.x / u_resolution_src.x;
float y_ratio = u_resolution_watermark.y / u_resolution_src.y;
- float aspect_ratio = min(x_ratio, y_ratio) / max(x_ratio, y_ratio);
- float x_scale = x_ratio > y_ratio ? 1.0 * u_scale : aspect_ratio * u_scale;
- float y_scale = y_ratio > x_ratio ? 1.0 * u_scale : aspect_ratio * u_scale;
+
+ float aspect_ratio = contain ?
+ (min(x_ratio, y_ratio) / max(x_ratio, y_ratio)) :
+ (max(x_ratio, y_ratio) / min(x_ratio, y_ratio));
+
+ float x_scale = contain ?
+ (x_ratio > y_ratio ? 1.0 * u_scale : aspect_ratio * u_scale) :
+ (x_ratio > y_ratio ? aspect_ratio * u_scale : 1.0 * u_scale);
+
+ float y_scale = contain ?
+ (y_ratio > x_ratio ? 1.0 * u_scale : aspect_ratio * u_scale) :
+ (y_ratio > x_ratio ? aspect_ratio * u_scale : 1.0 * u_scale);
+
float x_offset = u_alignX == 0 ? x_scale / 2.0 : u_alignX == 2 ? 1.0 - (x_scale / 2.0) : 0.5;
float y_offset = u_alignY == 0 ? y_scale / 2.0 : u_alignY == 2 ? 1.0 - (y_scale / 2.0) : 0.5;
@@ -69,6 +82,7 @@ type ImageEffectorImageLayer = {
type: 'image';
imageUrl: string | null;
imageId: string | null;
+ cover: boolean;
repeat: boolean;
scale: number;
alignX: 'left' | 'center' | 'right';
@@ -226,7 +240,7 @@ export class ImageEffector {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
- img.src = getProxiedImageUrl(layer.imageUrl);
+ img.src = getProxiedImageUrl(layer.imageUrl); // CORS対策
});
const texture = this.createTexture();
@@ -385,6 +399,9 @@ export class ImageEffector {
const u_alignY = gl.getUniformLocation(shaderProgram, 'u_alignY');
gl.uniform1i(u_alignY, layer.alignY === 'top' ? 0 : layer.alignY === 'bottom' ? 2 : 1);
+ const u_fitMode = gl.getUniformLocation(shaderProgram, 'u_fitMode');
+ gl.uniform1i(u_fitMode, layer.cover ? 1 : 0);
+
gl.drawArrays(gl.TRIANGLES, 0, 6);
}