wip
This commit is contained in:
parent
ec79b3ae37
commit
244f5a2793
|
|
@ -5658,6 +5658,14 @@ export interface Locale extends ILocale {
|
||||||
* 二次元コード
|
* 二次元コード
|
||||||
*/
|
*/
|
||||||
"withQrCode": string;
|
"withQrCode": string;
|
||||||
|
/**
|
||||||
|
* 背景色
|
||||||
|
*/
|
||||||
|
"backgroundColor": string;
|
||||||
|
/**
|
||||||
|
* 文字色
|
||||||
|
*/
|
||||||
|
"textColor": string;
|
||||||
};
|
};
|
||||||
"_compression": {
|
"_compression": {
|
||||||
"_quality": {
|
"_quality": {
|
||||||
|
|
|
||||||
|
|
@ -1411,6 +1411,8 @@ _imageFrameEditor:
|
||||||
captionSub: "キャプション(小)"
|
captionSub: "キャプション(小)"
|
||||||
availableVariables: "利用可能な変数"
|
availableVariables: "利用可能な変数"
|
||||||
withQrCode: "二次元コード"
|
withQrCode: "二次元コード"
|
||||||
|
backgroundColor: "背景色"
|
||||||
|
textColor: "文字色"
|
||||||
|
|
||||||
_compression:
|
_compression:
|
||||||
_quality:
|
_quality:
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template #label>{{ i18n.ts._imageFrameEditor.borderThickness }}</template>
|
<template #label>{{ i18n.ts._imageFrameEditor.borderThickness }}</template>
|
||||||
</MkRange>
|
</MkRange>
|
||||||
|
|
||||||
|
<MkInput :modelValue="getHex(frame.bgColor)" type="color" @update:modelValue="v => { const c = getRgb(v); if (c != null) frame.bgColor = c; }">
|
||||||
|
<template #label>{{ i18n.ts._imageFrameEditor.backgroundColor }}</template>
|
||||||
|
</MkInput>
|
||||||
|
|
||||||
|
<MkInput :modelValue="getHex(frame.fgColor)" type="color" @update:modelValue="v => { const c = getRgb(v); if (c != null) frame.fgColor = c; }">
|
||||||
|
<template #label>{{ i18n.ts._imageFrameEditor.textColor }}</template>
|
||||||
|
</MkInput>
|
||||||
|
|
||||||
<MkFolder :defaultOpen="true">
|
<MkFolder :defaultOpen="true">
|
||||||
<template #label>{{ i18n.ts._imageFrameEditor.header }}</template>
|
<template #label>{{ i18n.ts._imageFrameEditor.header }}</template>
|
||||||
|
|
||||||
|
|
@ -180,7 +188,7 @@ const frame = reactive<ImageFrameParams>(deepClone(props.frame) ?? {
|
||||||
centered: false,
|
centered: false,
|
||||||
withQrCode: true,
|
withQrCode: true,
|
||||||
},
|
},
|
||||||
bgColor: [255, 255, 255],
|
bgColor: [1, 1, 1],
|
||||||
fgColor: [0, 0, 0],
|
fgColor: [0, 0, 0],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -321,6 +329,24 @@ async function save() {
|
||||||
|
|
||||||
emit('ok', preset);
|
emit('ok', preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getHex(c: [number, number, number]) {
|
||||||
|
return `#${c.map(x => (x * 255).toString(16).padStart(2, '0')).join('')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRgb(hex: string | number): [number, number, number] | null {
|
||||||
|
if (
|
||||||
|
typeof hex === 'number' ||
|
||||||
|
typeof hex !== 'string' ||
|
||||||
|
!/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(hex)
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const m = hex.slice(1).match(/[0-9a-fA-F]{2}/g);
|
||||||
|
if (m == null) return [0, 0, 0];
|
||||||
|
return m.map(x => parseInt(x, 16) / 255) as [number, number, number];
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style module>
|
<style module>
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,19 @@ uniform float u_paddingTop;
|
||||||
uniform float u_paddingBottom;
|
uniform float u_paddingBottom;
|
||||||
uniform float u_paddingLeft;
|
uniform float u_paddingLeft;
|
||||||
uniform float u_paddingRight;
|
uniform float u_paddingRight;
|
||||||
|
uniform vec3 u_bg;
|
||||||
out vec4 out_color;
|
out vec4 out_color;
|
||||||
|
|
||||||
float remap(float value, float inputMin, float inputMax, float outputMin, float outputMax) {
|
float remap(float value, float inputMin, float inputMax, float outputMin, float outputMax) {
|
||||||
return outputMin + (outputMax - outputMin) * ((value - inputMin) / (inputMax - inputMin));
|
return outputMin + (outputMax - outputMin) * ((value - inputMin) / (inputMax - inputMin));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec3 blendAlpha(vec3 bg, vec4 fg) {
|
||||||
|
return fg.a * fg.rgb + (1.0 - fg.a) * bg;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 bg = vec4(1.0, 1.0, 1.0, 1.0);
|
vec4 bg = vec4(u_bg, 1.0);
|
||||||
|
|
||||||
vec4 image_color = texture(u_image, vec2(
|
vec4 image_color = texture(u_image, vec2(
|
||||||
remap(in_uv.x, u_paddingLeft, 1.0 - u_paddingRight, 0.0, 1.0),
|
remap(in_uv.x, u_paddingLeft, 1.0 - u_paddingRight, 0.0, 1.0),
|
||||||
|
|
@ -43,9 +48,9 @@ void main() {
|
||||||
)) : bg;
|
)) : bg;
|
||||||
|
|
||||||
if (in_uv.y < u_paddingTop) {
|
if (in_uv.y < u_paddingTop) {
|
||||||
out_color = topLabel_color;
|
out_color = vec4(blendAlpha(bg.rgb, topLabel_color), 1.0);
|
||||||
} else if (in_uv.y > (1.0 - u_paddingBottom)) {
|
} else if (in_uv.y > (1.0 - u_paddingBottom)) {
|
||||||
out_color = bottomLabel_color;
|
out_color = vec4(blendAlpha(bg.rgb, bottomLabel_color), 1.0);
|
||||||
} else {
|
} else {
|
||||||
if (in_uv.y > u_paddingTop && in_uv.x > u_paddingLeft && in_uv.x < (1.0 - u_paddingRight)) {
|
if (in_uv.y > u_paddingTop && in_uv.x > u_paddingLeft && in_uv.x < (1.0 - u_paddingRight)) {
|
||||||
out_color = image_color;
|
out_color = image_color;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ export const FX_frame = defineImageEffectorFx({
|
||||||
id: 'frame',
|
id: 'frame',
|
||||||
name: '(internal)',
|
name: '(internal)',
|
||||||
shader,
|
shader,
|
||||||
uniforms: ['image', 'topLabel', 'bottomLabel', 'topLabelEnabled', 'bottomLabelEnabled', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'] as const,
|
uniforms: ['image', 'topLabel', 'bottomLabel', 'topLabelEnabled', 'bottomLabelEnabled', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', 'bg'] as const,
|
||||||
params: {
|
params: {
|
||||||
image: {
|
image: {
|
||||||
type: 'textureRef',
|
type: 'textureRef',
|
||||||
|
|
@ -56,6 +56,10 @@ export const FX_frame = defineImageEffectorFx({
|
||||||
max: 1,
|
max: 1,
|
||||||
min: 0,
|
min: 0,
|
||||||
},
|
},
|
||||||
|
bg: {
|
||||||
|
type: 'color',
|
||||||
|
default: [1, 1, 1],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
main: ({ gl, u, params, textures }) => {
|
main: ({ gl, u, params, textures }) => {
|
||||||
const image = textures.image;
|
const image = textures.image;
|
||||||
|
|
@ -71,6 +75,7 @@ export const FX_frame = defineImageEffectorFx({
|
||||||
gl.uniform1f(u.paddingBottom, params.paddingBottom);
|
gl.uniform1f(u.paddingBottom, params.paddingBottom);
|
||||||
gl.uniform1f(u.paddingLeft, params.paddingLeft);
|
gl.uniform1f(u.paddingLeft, params.paddingLeft);
|
||||||
gl.uniform1f(u.paddingRight, params.paddingRight);
|
gl.uniform1f(u.paddingRight, params.paddingRight);
|
||||||
|
gl.uniform3f(u.bg, params.bg[0], params.bg[1], params.bg[2]);
|
||||||
|
|
||||||
if (params.topLabelEnabled) {
|
if (params.topLabelEnabled) {
|
||||||
const topLabel = textures.topLabel;
|
const topLabel = textures.topLabel;
|
||||||
|
|
|
||||||
|
|
@ -112,9 +112,6 @@ export class ImageFrameRenderer {
|
||||||
const qrSize = scaleBase * 0.1;
|
const qrSize = scaleBase * 0.1;
|
||||||
const qrMarginRight = Math.max((labelCanvasCtx.canvas.height - qrSize) / 2, paddingRight);
|
const qrMarginRight = Math.max((labelCanvasCtx.canvas.height - qrSize) / 2, paddingRight);
|
||||||
|
|
||||||
labelCanvasCtx.fillStyle = '#ffffff';
|
|
||||||
labelCanvasCtx.fillRect(0, 0, labelCanvasCtx.canvas.width, labelCanvasCtx.canvas.height);
|
|
||||||
|
|
||||||
labelCanvasCtx.fillStyle = '#000000';
|
labelCanvasCtx.fillStyle = '#000000';
|
||||||
labelCanvasCtx.font = `bold ${fontSize}px sans-serif`;
|
labelCanvasCtx.font = `bold ${fontSize}px sans-serif`;
|
||||||
labelCanvasCtx.textBaseline = 'middle';
|
labelCanvasCtx.textBaseline = 'middle';
|
||||||
|
|
@ -241,6 +238,7 @@ export class ImageFrameRenderer {
|
||||||
paddingRight: paddingRight / renderWidth,
|
paddingRight: paddingRight / renderWidth,
|
||||||
paddingTop: paddingTop / renderHeight,
|
paddingTop: paddingTop / renderHeight,
|
||||||
paddingBottom: paddingBottom / renderHeight,
|
paddingBottom: paddingBottom / renderHeight,
|
||||||
|
bg: params.bgColor,
|
||||||
},
|
},
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue