Skip to content

textmode.js / conversion / TextmodeConversionManager

Class: TextmodeConversionManager

Registers image-to-textmode conversion strategies for a Textmodifier instance.

Access via Textmodifier.conversions.

Example

ts
// Register a custom conversion strategy
t.conversions.register({
    id: 'custom',
    createShader: (ctx) => shader,
    createUniforms: (ctx) => ({ u_image: ctx.source.texture })
});

// Use the conversion mode on an image
img.conversionMode('custom');

Methods

has()

ts
has(id): boolean;

Check if a conversion strategy with the given ID is registered.

Parameters

ParameterTypeDescription
idstringThe conversion strategy ID to check

Returns

boolean

true if the strategy exists

Example

javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight });

const labelLayer = t.layers.add();
let hasCustom = false;
let pulseShader = null;

t.setup(async () => {
	const vert = `#version 300 es
		in vec4 a_position;
		in vec2 a_uv;
		out vec2 v_uv;
		void main() {
			gl_Position = a_position;
			v_uv = a_uv;
		}
	`;

	const frag = `#version 300 es
		precision highp float;
		in vec2 v_uv;
		uniform sampler2D u_image;
		layout(location = 0) out vec4 o_character;
		layout(location = 1) out vec4 o_primaryColor;
		layout(location = 2) out vec4 o_secondaryColor;
		void main() {
			vec4 col = texture(u_image, v_uv);
			o_character = vec4(col.r, 0.0, 0.0, 0.0);
			o_primaryColor = vec4(col.rgb, 1.0);
			o_secondaryColor = vec4(0.0, 0.0, 0.0, 1.0);
		}
	`;

	pulseShader = await t.createShader(vert, frag);
});

t.draw(() => {
	t.background(6, 8, 20);
	hasCustom = t.conversions.has('custom-mode');
});

t.mouseClicked(() => {
	if (hasCustom) {
		t.conversions.unregister('custom-mode');
	} else {
		t.conversions.register({
			id: 'custom-mode',
			createShader: () => pulseShader,
			createUniforms: (ctx) => ({ u_image: ctx.source.texture }),
		});
	}
});

function drawText(text, x, y, r = 220, g = 230, b = 255) {
	t.push();
	t.translate(x, y);
	t.charColor(r, g, b);
	for (let i = 0; i < text.length; i++) {
		t.char(text[i]);
		t.point();
		t.translate(1, 0);
	}
	t.pop();
}

labelLayer.draw(() => {
	t.clear();
	const left = -Math.floor(t.grid.cols / 2);
	const top = -Math.floor(t.grid.rows / 2);
	let y = top + 3;
	const x = left + 3;

	const isDefault = t.conversions.has('brightness');

	drawText('CONVERSION.HAS', x, y++, 100, 255, 140);
	drawText('------------------------------------', x, y++, 80, 100, 150);
	drawText('CONCEPT: CHECK REGISTERED STRATEGY', x, y++, 100, 220, 255);
	drawText('Performs a key lookup in conversions.', x, y++, 140, 160, 190);
	drawText('------------------------------------', x, y++, 80, 100, 150);
	drawText(`has('brightness') : ${isDefault}`, x, y++, 180, 255, 180);
	drawText(
		`has('custom-mode'): ${hasCustom}`,
		x,
		y++,
		hasCustom ? 180 : 255,
		hasCustom ? 255 : 120,
		hasCustom ? 180 : 120
	);
	drawText('------------------------------------', x, y++, 80, 100, 150);
	drawText(hasCustom ? 'Click to unregister.' : 'Click to register custom-mode.', x, y++, 120, 205, 255);
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});

register()

ts
register(strategy): void;

Register a custom conversion strategy.

Parameters

ParameterTypeDescription
strategyTextmodeConversionStrategyThe conversion strategy to register

Returns

void

Example

ts
t.conversions.register({
    id: 'custom',
    createShader: (ctx) => shader,
    createUniforms: (ctx) => ({ u_image: ctx.source.texture })
});

unregister()

ts
unregister(id): boolean;

Unregister a conversion strategy by its ID.

Parameters

ParameterTypeDescription
idstringThe conversion strategy ID to unregister

Returns

boolean

true if the strategy was unregistered, false if it wasn't found

Example

javascript
const IMAGE_URL = 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=900&q=80';
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight });

const labelLayer = t.layers.add();
let img = null;
let registered = false;
let customShader = null;

t.setup(async () => {
	const vert = `#version 300 es\nin vec4 a_position; in vec2 a_uv; out vec2 v_uv; void main() { gl_Position = a_position; v_uv = a_uv; }`;
	const frag = `#version 300 es\nprecision highp float; in vec2 v_uv; uniform sampler2D u_image; layout(location = 0) out vec4 o_character; layout(location = 1) out vec4 o_primaryColor; layout(location = 2) out vec4 o_secondaryColor; void main() { vec4 col = texture(u_image, v_uv); float greenLuma = col.g; o_character = vec4(greenLuma * 0.8, 0.0, 0.0, 0.0); o_primaryColor = vec4(0.1, 0.9, 0.3, 1.0); o_secondaryColor = vec4(0.01, 0.05, 0.02, 1.0); }`;

	customShader = await t.createShader(vert, frag);

	t.conversions.register({
		id: 'green-custom',
		createShader: () => customShader,
		createUniforms: (ctx) => ({ u_image: ctx.source.texture }),
	});

	img = await t.loadImage(IMAGE_URL);
	img.characters(' .:-=+*#%@');
	img.conversionMode('green-custom');
	registered = true;
});

t.draw(() => {
	t.background(6, 8, 20);
	if (img) {
		t.image(img, t.grid.cols - 8, t.grid.rows - 10);
	}
});

t.mouseClicked(() => {
	if (!registered || !img) return;
	img.conversionMode('brightness');
	t.conversions.unregister('green-custom');
	registered = false;
});

function drawText(text, x, y, r = 220, g = 230, b = 255) {
	t.push();
	t.translate(x, y);
	t.charColor(r, g, b);
	for (let i = 0; i < text.length; i++) {
		t.char(text[i]);
		t.point();
		t.translate(1, 0);
	}
	t.pop();
}

labelLayer.draw(() => {
	t.clear();
	const left = -Math.floor(t.grid.cols / 2);
	const top = -Math.floor(t.grid.rows / 2);
	let y = top + 3;
	const x = left + 3;

	const mode = registered ? 'green-custom' : 'brightness';

	drawText('CONVERSION.UNREGISTER', x, y++, 100, 255, 140);
	drawText('------------------------------------', x, y++, 80, 100, 150);
	drawText('CONCEPT: DISPOSE CONVERSION STRATEGY', x, y++, 100, 220, 255);
	drawText('Removes registered custom logic.', x, y++, 140, 160, 190);
	drawText('------------------------------------', x, y++, 80, 100, 150);
	drawText(`ACTIVE MODE: ${mode}`, x, y++, 140, 190, 255);
	drawText(
		registered ? 'Click to unregister green-custom.' : 'Strategy unregistered successfully.',
		x,
		y++,
		180,
		255,
		180
	);
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});