diff --git a/packages/frontend/src/components/MkImageFrameEditorDialog.vue b/packages/frontend/src/components/MkImageFrameEditorDialog.vue index dc4944db43..388a29d4e3 100644 --- a/packages/frontend/src/components/MkImageFrameEditorDialog.vue +++ b/packages/frontend/src/components/MkImageFrameEditorDialog.vue @@ -39,6 +39,10 @@ SPDX-License-Identifier: AGPL-3.0-only
+ + + + @@ -69,6 +73,10 @@ SPDX-License-Identifier: AGPL-3.0-only
+ + + + @@ -155,6 +163,7 @@ const props = defineProps<{ const frame = reactive(deepClone(props.frame) ?? { borderThickness: 0.05, labelTop: { + enabled: false, scale: 1.0, padding: 0.2, textBig: '', @@ -163,6 +172,7 @@ const frame = reactive(deepClone(props.frame) ?? { withQrCode: false, }, labelBottom: { + enabled: true, scale: 1.0, padding: 0.2, textBig: '{year}/{0month}/{0day}', diff --git a/packages/frontend/src/utility/image-effector/fxs/frame.glsl b/packages/frontend/src/utility/image-effector/fxs/frame.glsl index 9030781151..3a9189545b 100644 --- a/packages/frontend/src/utility/image-effector/fxs/frame.glsl +++ b/packages/frontend/src/utility/image-effector/fxs/frame.glsl @@ -12,6 +12,8 @@ uniform vec2 in_resolution; uniform sampler2D u_image; uniform sampler2D u_topLabel; uniform sampler2D u_bottomLabel; +uniform bool u_topLabelEnabled; +uniform bool u_bottomLabelEnabled; uniform float u_paddingTop; uniform float u_paddingBottom; uniform float u_paddingLeft; @@ -23,20 +25,22 @@ float remap(float value, float inputMin, float inputMax, float outputMin, float } void main() { + vec4 bg = vec4(1.0, 1.0, 1.0, 1.0); + vec4 image_color = texture(u_image, vec2( remap(in_uv.x, u_paddingLeft, 1.0 - u_paddingRight, 0.0, 1.0), remap(in_uv.y, u_paddingTop, 1.0 - u_paddingBottom, 0.0, 1.0) )); - vec4 topLabel_color = texture(u_topLabel, vec2( + vec4 topLabel_color = u_topLabelEnabled ? texture(u_topLabel, vec2( in_uv.x, remap(in_uv.y, 0.0, u_paddingTop, 0.0, 1.0) - )); + )) : bg; - vec4 bottomLabel_color = texture(u_bottomLabel, vec2( + vec4 bottomLabel_color = u_bottomLabelEnabled ? texture(u_bottomLabel, vec2( in_uv.x, remap(in_uv.y, 1.0 - u_paddingBottom, 1.0, 0.0, 1.0) - )); + )) : bg; if (in_uv.y < u_paddingTop) { out_color = topLabel_color; @@ -46,7 +50,7 @@ void main() { if (in_uv.y > u_paddingTop && in_uv.x > u_paddingLeft && in_uv.x < (1.0 - u_paddingRight)) { out_color = image_color; } else { - out_color = vec4(1.0, 1.0, 1.0, 1.0); + out_color = bg; } } } diff --git a/packages/frontend/src/utility/image-effector/fxs/frame.ts b/packages/frontend/src/utility/image-effector/fxs/frame.ts index 89e9631517..695a276f56 100644 --- a/packages/frontend/src/utility/image-effector/fxs/frame.ts +++ b/packages/frontend/src/utility/image-effector/fxs/frame.ts @@ -10,7 +10,7 @@ export const FX_frame = defineImageEffectorFx({ id: 'frame', name: '(internal)', shader, - uniforms: ['image', 'topLabel', 'bottomLabel', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'] as const, + uniforms: ['image', 'topLabel', 'bottomLabel', 'topLabelEnabled', 'bottomLabelEnabled', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'] as const, params: { image: { type: 'textureRef', @@ -24,6 +24,14 @@ export const FX_frame = defineImageEffectorFx({ type: 'textureRef', default: null, }, + topLabelEnabled: { + type: 'boolean', + default: false, + }, + bottomLabelEnabled: { + type: 'boolean', + default: false, + }, paddingTop: { type: 'number', default: 0, @@ -57,23 +65,29 @@ export const FX_frame = defineImageEffectorFx({ gl.bindTexture(gl.TEXTURE_2D, image.texture); gl.uniform1i(u.image, 1); + gl.uniform1i(u.topLabelEnabled, params.topLabelEnabled ? 1 : 0); + gl.uniform1i(u.bottomLabelEnabled, params.bottomLabelEnabled ? 1 : 0); gl.uniform1f(u.paddingTop, params.paddingTop); gl.uniform1f(u.paddingBottom, params.paddingBottom); gl.uniform1f(u.paddingLeft, params.paddingLeft); gl.uniform1f(u.paddingRight, params.paddingRight); - const topLabel = textures.topLabel; - if (topLabel) { - gl.activeTexture(gl.TEXTURE2); - gl.bindTexture(gl.TEXTURE_2D, topLabel.texture); - gl.uniform1i(u.topLabel, 2); + if (params.topLabelEnabled) { + const topLabel = textures.topLabel; + if (topLabel) { + gl.activeTexture(gl.TEXTURE2); + gl.bindTexture(gl.TEXTURE_2D, topLabel.texture); + gl.uniform1i(u.topLabel, 2); + } } - const bottomLabel = textures.bottomLabel; - if (bottomLabel) { - gl.activeTexture(gl.TEXTURE3); - gl.bindTexture(gl.TEXTURE_2D, bottomLabel.texture); - gl.uniform1i(u.bottomLabel, 3); + if (params.bottomLabelEnabled) { + const bottomLabel = textures.bottomLabel; + if (bottomLabel) { + gl.activeTexture(gl.TEXTURE3); + gl.bindTexture(gl.TEXTURE_2D, bottomLabel.texture); + gl.uniform1i(u.bottomLabel, 3); + } } }, }); diff --git a/packages/frontend/src/utility/image-frame-renderer.ts b/packages/frontend/src/utility/image-frame-renderer.ts index 85b0080f6e..87e22a2ec9 100644 --- a/packages/frontend/src/utility/image-frame-renderer.ts +++ b/packages/frontend/src/utility/image-frame-renderer.ts @@ -20,6 +20,7 @@ const FXS = [ // TODO: 上部にもラベルを配置できるようにする type LabelParams = { + enabled: boolean; scale: number; padding: number; textBig: string; @@ -190,7 +191,7 @@ export class ImageFrameRenderer { } } - return labelCanvasCtx; + return labelCanvasCtx.getImageData(0, 0, labelCanvasCtx.canvas.width, labelCanvasCtx.canvas.height); ; } public async updateAndRender(params: ImageFrameParams): Promise { @@ -210,18 +211,20 @@ export class ImageFrameRenderer { const paddingLeft = Math.floor(imageAreaH * params.borderThickness); const paddingRight = Math.floor(imageAreaH * params.borderThickness); - const paddingTop = Math.floor(imageAreaH * params.labelTop.padding); - const paddingBottom = Math.floor(imageAreaH * params.labelBottom.padding); + const paddingTop = params.labelTop.enabled ? Math.floor(imageAreaH * params.labelTop.padding) : Math.floor(imageAreaH * params.borderThickness); + const paddingBottom = params.labelBottom.enabled ? Math.floor(imageAreaH * params.labelBottom.padding) : Math.floor(imageAreaH * params.borderThickness); const renderWidth = imageAreaW + paddingLeft + paddingRight; const renderHeight = imageAreaH + paddingTop + paddingBottom; - const topLabelCanvasCtx = await this.renderLabel(renderWidth, paddingTop, paddingLeft, paddingRight, imageAreaH, params.labelTop); - const topLabelImage = topLabelCanvasCtx.getImageData(0, 0, topLabelCanvasCtx.canvas.width, topLabelCanvasCtx.canvas.height); - this.effector.registerTexture('topLabel', topLabelImage); + if (params.labelTop.enabled) { + const topLabelImage = await this.renderLabel(renderWidth, paddingTop, paddingLeft, paddingRight, imageAreaH, params.labelTop); + this.effector.registerTexture('topLabel', topLabelImage); + } - const bottomLabelCanvasCtx = await this.renderLabel(renderWidth, paddingBottom, paddingLeft, paddingRight, imageAreaH, params.labelBottom); - const bottomLabelImage = bottomLabelCanvasCtx.getImageData(0, 0, bottomLabelCanvasCtx.canvas.width, bottomLabelCanvasCtx.canvas.height); - this.effector.registerTexture('bottomLabel', bottomLabelImage); + if (params.labelBottom.enabled) { + const bottomLabelImage = await this.renderLabel(renderWidth, paddingBottom, paddingLeft, paddingRight, imageAreaH, params.labelBottom); + this.effector.registerTexture('bottomLabel', bottomLabelImage); + } this.effector.changeResolution(renderWidth, renderHeight); @@ -232,6 +235,8 @@ export class ImageFrameRenderer { image: 'image', topLabel: 'topLabel', bottomLabel: 'bottomLabel', + topLabelEnabled: params.labelTop.enabled, + bottomLabelEnabled: params.labelBottom.enabled, paddingLeft: paddingLeft / renderWidth, paddingRight: paddingRight / renderWidth, paddingTop: paddingTop / renderHeight,