diff --git a/locales/index.d.ts b/locales/index.d.ts index 07513ba644..1ae19617c7 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -12112,6 +12112,14 @@ export interface Locale extends ILocale { * 歪み */ "distort": string; + /** + * 二値化 + */ + "threshold": string; + /** + * 集中線 + */ + "zoomLines": string; }; }; } diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 966378be73..7119f90c85 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -3246,3 +3246,5 @@ _imageEffector: colorClamp: "色の圧縮" colorClampAdvanced: "色の圧縮(高度)" distort: "歪み" + threshold: "二値化" + zoomLines: "集中線" diff --git a/packages/frontend/src/utility/image-effector/fxs.ts b/packages/frontend/src/utility/image-effector/fxs.ts index 1927e0c8d8..f95ad9eff9 100644 --- a/packages/frontend/src/utility/image-effector/fxs.ts +++ b/packages/frontend/src/utility/image-effector/fxs.ts @@ -11,7 +11,9 @@ import { FX_glitch } from './fxs/glitch.js'; import { FX_grayscale } from './fxs/grayscale.js'; import { FX_invert } from './fxs/invert.js'; import { FX_mirror } from './fxs/mirror.js'; +import { FX_threshold } from './fxs/threshold.js'; import { FX_watermarkPlacement } from './fxs/watermarkPlacement.js'; +import { FX_zoomLines } from './fxs/zoomLines.js'; import type { ImageEffectorFx } from './ImageEffector.js'; export const FXS = [ @@ -24,4 +26,6 @@ export const FXS = [ FX_colorClamp, FX_colorClampAdvanced, FX_distort, + FX_threshold, + FX_zoomLines, ] as const satisfies ImageEffectorFx[]; diff --git a/packages/frontend/src/utility/image-effector/fxs/threshold.ts b/packages/frontend/src/utility/image-effector/fxs/threshold.ts new file mode 100644 index 0000000000..5702538689 --- /dev/null +++ b/packages/frontend/src/utility/image-effector/fxs/threshold.ts @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineImageEffectorFx } from '../ImageEffector.js'; +import { i18n } from '@/i18n.js'; + +const shader = `#version 300 es +precision mediump float; + +in vec2 in_uv; +uniform sampler2D u_texture; +uniform vec2 u_resolution; +uniform float u_r; +uniform float u_g; +uniform float u_b; +out vec4 out_color; + +void main() { + vec4 in_color = texture(u_texture, in_uv); + float r = in_color.r < u_r ? 0.0 : 1.0; + float g = in_color.g < u_g ? 0.0 : 1.0; + float b = in_color.b < u_b ? 0.0 : 1.0; + out_color = vec4(r, g, b, in_color.a); +} +`; + +export const FX_threshold = defineImageEffectorFx({ + id: 'threshold' as const, + name: i18n.ts._imageEffector._fxs.threshold, + shader, + params: { + r: { + type: 'number' as const, + default: 0.5, + min: 0.0, + max: 1.0, + step: 0.01, + }, + g: { + type: 'number' as const, + default: 0.5, + min: 0.0, + max: 1.0, + step: 0.01, + }, + b: { + type: 'number' as const, + default: 0.5, + min: 0.0, + max: 1.0, + step: 0.01, + }, + }, + main: ({ gl, program, params, preTexture }) => { + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, preTexture); + const u_texture = gl.getUniformLocation(program, 'u_texture'); + gl.uniform1i(u_texture, 0); + + const u_r = gl.getUniformLocation(program, 'u_r'); + gl.uniform1f(u_r, params.r); + + const u_g = gl.getUniformLocation(program, 'u_g'); + gl.uniform1f(u_g, params.g); + + const u_b = gl.getUniformLocation(program, 'u_b'); + gl.uniform1f(u_b, params.b); + }, +}); diff --git a/packages/frontend/src/utility/image-effector/fxs/zoomLines.ts b/packages/frontend/src/utility/image-effector/fxs/zoomLines.ts new file mode 100644 index 0000000000..6bcd17e573 --- /dev/null +++ b/packages/frontend/src/utility/image-effector/fxs/zoomLines.ts @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineImageEffectorFx } from '../ImageEffector.js'; +import { i18n } from '@/i18n.js'; + +const shader = `#version 300 es +precision mediump float; + +in vec2 in_uv; +uniform sampler2D u_texture; +uniform vec2 u_resolution; +uniform vec2 u_pos; +uniform float frequency; +out vec4 out_color; + +void main() { + vec4 in_color = texture(u_texture, in_uv); + float t = atan(u_pos.y + (in_uv.y - 0.5), u_pos.x + (in_uv.x - 0.5)); + t = sin(t * frequency); + out_color = vec4( + mix(in_color.r, 1.0, t), + mix(in_color.g, 1.0, t), + mix(in_color.b, 1.0, t), + in_color.a + ); +} +`; + +export const FX_zoomLines = defineImageEffectorFx({ + id: 'zoomLines' as const, + name: i18n.ts._imageEffector._fxs.zoomLines, + shader, + params: { + x: { + type: 'number' as const, + default: 0.0, + min: -1.0, + max: 1.0, + step: 0.01, + }, + y: { + type: 'number' as const, + default: 0.0, + min: -1.0, + max: 1.0, + step: 0.01, + }, + frequency: { + type: 'number' as const, + default: 30.0, + min: 1.0, + max: 200.0, + step: 0.1, + }, + }, + main: ({ gl, program, params, preTexture }) => { + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, preTexture); + const u_texture = gl.getUniformLocation(program, 'u_texture'); + gl.uniform1i(u_texture, 0); + + const u_pos = gl.getUniformLocation(program, 'u_pos'); + gl.uniform2f(u_pos, -(params.x / 2.0), -(params.y / 2.0)); + + const u_frequency = gl.getUniformLocation(program, 'frequency'); + gl.uniform1f(u_frequency, params.frequency); + }, +});