Creates an opsCanvas
Creates an opsCanvas from a png
Creates an opsCanvas from an svg
set target channels to value
sets selected channels to 0
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(100, 46);
const test = createOpsCanvas(96, 20);
test.gradient(
[
{
step: 0,
color: "#e5f392ff",
},
{
step: 1,
color: "#e5f39200",
},
],
"linear",
[0.1, 0],
[0.9, 0],
{ scaleSpace: "relative" },
);
example.blend(test, 2, 2, { mode: "add", showDebugBounds: true });
test.clear();
example.blend(test, 2, 24, { mode: "add", showDebugBounds: true });
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
set channels to 0 or 255, check is >= edge
set target Channels to 255, if src channel value is between min and max, otherwise 0
add value to channels
substract value from channels
multiply values in channels
divide values in channels
raise values in channels to power
clamps the values to be no bigger than value
clamps the values to be no smaller than value
clamps the values to be larger than min and smaller than max
maps values from input to output range in channels values outside input range are clamped
maps values from input to output range in channels
utilizites to render vector graphics
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(126, 60);
example.drawStrokePath(
(ctx, { width, height }) => {
ctx.moveTo(2, 2);
ctx.lineTo(8, 12);
ctx.lineTo(2, 58);
ctx.lineTo(8, 58);
ctx.lineTo(8, 40);
ctx.addCircle(40, 30, 24);
ctx.addRect(74, 4, 20, 50);
ctx.addOval(102, 4, 20, 50);
},
{ color: "#e5f392", lineWeight: 4 }
);
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
// undefined
antiAlias?:booleanimport { createOpsCanvas, type Mask } from "@ops/canvas";
const channels: Mask[] = ["r", "g", "b", "a", "rgb", "rgba"];
const example = createOpsCanvas(4 + channels.length * 32, 34);
// draw base grey
// since we're changing single channels later,
// we need to put something into the al[ha channel for them to show up
example.drawFillPath(
(ctx, { width, height }) => {
ctx.addRect(0, 0, width, Math.floor(height * 0.5));
},
{ color: "black" },
);
for (const [index, mask] of Object.entries(channels)) {
example.drawFillPath(
(ctx) => {
ctx.addRect(2 + 32 * parseInt(index, 10), 2, 30, 30);
},
{ color: "white" },
mask as Mask,
);
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(130, 60);
example.drawFillPath(
(ctx, { width, height }) => {
ctx.moveTo(2, 2);
ctx.lineTo(8, 12);
ctx.lineTo(2, 58);
ctx.lineTo(8, 58);
ctx.lineTo(8, 40);
ctx.close();
ctx.addCircle(45, 30, 28);
ctx.addRect(80, 2, 20, 56);
ctx.addOval(104, 2, 20, 56);
},
{ color: "#e5f392" }
);
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(60, 60);
example.drawSvg(
`
<svg
viewBox="0 0 300, 300"
xmlns="http://www.w3.org/2000/svg"
>
<rect width="100%" height="100%" fill="#d45f97" />
<circle cx="150" cy="100" r="80" fill="#e5f392" />
</svg>
`,
2,
2,
{ width: 56 }
);
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Mask out parts of the opsCanvas
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(104, 54);
const test = createOpsCanvas(50, 50);
test.setColor("#e5f392", "rgba");
example.blend(test, 2, 2);
test.mask({
fill: (ctx, { width, height }) => {
ctx.moveTo(width * 0.2, height * 0.2);
ctx.lineTo(width * 0.8, height * 0.5);
ctx.lineTo(width * 0.2, height * 0.8);
ctx.close();
},
});
example.blend(test, 54, 2);
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Apply a simple blur to the opsCanvas
Apply a blur with custom weights and offsets to the opsCanvas
Apply a gaussion blur to the opsCanvas
// undefined
radius?:number// undefined
sigma?:numberimport { createOpsCanvas, LineFillAngleValues } from "@ops/canvas";
const sizes = [
{ lineWidth: 1, spacing: 20 },
{ lineWidth: 2, spacing: 4 },
{ lineWidth: 20, spacing: 1 },
];
const example = createOpsCanvas(
2 + LineFillAngleValues.length * 102,
2 + sizes.length * 102,
);
for (const [i, angle] of Object.entries(LineFillAngleValues)) {
for (const [y, { lineWidth, spacing }] of Object.entries(sizes)) {
const test = createOpsCanvas(100, 100);
test.fills.lines({
lineWidth,
angle,
spacing,
invertAlpha: false,
color: "#d45f97",
});
example.blend(test, 2 + parseInt(i, 10) * 102, 2 + parseFloat(y) * 102);
}
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
import { createOpsCanvas } from "@ops/canvas";
const diagonals = [false, true];
const sizes = [
{ lineWidth: 1, spacing: 20 },
{ lineWidth: 2, spacing: 4 },
{ lineWidth: 10, spacing: 1 },
];
const example = createOpsCanvas(
2 + diagonals.length * 102,
2 + sizes.length * 102
);
for (const [i, diagonal] of Object.entries(diagonals)) {
for (const [y, { lineWidth, spacing }] of Object.entries(sizes)) {
const test = createOpsCanvas(100, 100);
test.fills.linesGrid({
lineWidth,
diagonal,
spacing,
invertAlpha: false,
color: "#d45f97",
});
example.blend(test, 2 + parseInt(i, 10) * 102, 2 + parseInt(y, 10) * 102);
}
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
import {
createOpsCanvas,
FillShapesGridLayoutValues,
FillShapesGridShapeValues,
} from "@ops/canvas";
const sizes = [
{ shapeSize: 6, spacing: 3 },
{ shapeSize: 20, spacing: 2 },
{ shapeSize: 40, spacing: -2 },
];
const groupWidth = 8 + FillShapesGridShapeValues.length * 102;
const example = createOpsCanvas(
2 + FillShapesGridLayoutValues.length * groupWidth,
2 + sizes.length * 102,
);
for (const [layoutsId, layout] of Object.entries(FillShapesGridLayoutValues)) {
for (const [i, shape] of Object.entries(FillShapesGridShapeValues)) {
for (const [y, { shapeSize, spacing }] of Object.entries(sizes)) {
const test = createOpsCanvas(100, 100);
test.fills.shapesGrid({
shape,
shapeSize,
spacing,
invertAlpha: false,
layout,
color: "#d45f97",
});
example.blend(
test,
2 + parseInt(layoutsId, 10) * groupWidth + parseInt(i, 10) * 102,
2 + parseInt(y, 10) * 102,
);
}
}
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
generates an sdf with threshold based on single channel you can manipulate the sdf with the callback and its helpers after the callback is run, the values are clamped to [0, 255] and alpha is set to 255
// run mod on the sdf
mod:(v:number) => void// set sdf to remainder with value
rem:(v:number) => void// set all value signs to positive
abs:() => void// map range [inMin, inMax] to [outMin, outMax]
map:(inMin:numberinMax:numberoutMin:numberoutMax:number) => void// map range [inMin, inMax] to [outMin, outMax] remapped values are clamped to range [outMin, outMax]
mapClamped:(inMin:numberinMax:numberoutMin:numberoutMax:number) => void// clamp larger values to min
min:(v:number) => void// clamp smaller values to max
max:(v:number) => void// remap range [inMin, inMax] the values at both inMin and inMax will be outMin the center will be outMax you can shape the parabola with parameter k
parabola:(inMin:numberinMax:numberoutMin:numberoutMax:numberk:number) => void// at center map value to outMax smoothly blend to outMin at center +- width
cubicPulse:(center:numberwidth:numberoutMin:numberoutMax:number) => void// edit values with callback
applyCustom:(func:(v:number) => number) => voidimport { AlignValues, BaselineValues, createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(
2 + AlignValues.length * 102,
2 + BaselineValues.length * 42,
);
for (const [x, align] of Object.entries(AlignValues)) {
for (const [y, baseline] of Object.entries(BaselineValues)) {
const test = createOpsCanvas(100, 40);
const center = [50, 20];
test.drawFillPath(
(ctx, { width, height }) => {
ctx.addRect(0, center[1], width, height);
},
{ color: "rgba(255, 255, 255, 0.3)" },
);
test.drawFillPath(
(ctx) => {
ctx.addRect(center[0] - 1, center[1] - 1, 2, 2);
},
{ color: "white" },
);
test.drawText("MOPS", {
size: 18,
x: center[0],
y: center[1],
color: "#d45f97",
align,
baseline,
mask: "rgba",
});
example.blend(test, 2 + parseFloat(x) * 102, 2 + parseFloat(y) * 42);
}
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
// undefined
monochrome?:boolean// undefined
mask?:"rgba""rgb""r""g""b""a"// undefined
monochrome?:boolean// undefined
mask?:"rgba""rgb""r""g""b""a"// undefined
mask?:"rgba""rgb""r""g""b""a"draw into the opsCanvas with a provided `CanvasRenderingContext2D`
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(2 + 4 * 52, 54);
const test = createOpsCanvas(50, 50);
test.setColor("#fff392", "rgba");
test.mask({
fill: (ctx, { width, height }) => {
ctx.moveTo(0, 0);
ctx.lineTo(width, height);
ctx.lineTo(0, height);
},
});
example.blend(test, 2, 2);
test.swizzle("agbr");
example.blend(test, 54, 2);
test.swizzle("brga");
example.blend(test, 106, 2);
test.swizzle("ggga");
example.blend(test, 158, 2);
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Change opsCanvas size
import { createOpsCanvas, ResampleModeValues } from "@ops/canvas";
const example = createOpsCanvas(ResampleModeValues.length * 104 + 2, 246);
for (const [i, mode] of Object.entries(ResampleModeValues)) {
const index = parseInt(i, 10);
const test = createOpsCanvas(18, 38);
test.set(255, "a");
test.addNoise(
{ min: 0, max: 255 },
{ value: 5.0, space: "relativeMin" },
"perlin",
{ seed: "a", mask: "rgb" },
);
test.gradientRemap(
[
{ step: 0, color: "#e5f392" },
{ step: 0.5, color: "#e49e71" },
{ step: 1, color: "#d45f97" },
],
"r",
);
test.drawStrokePath(
(ctx, { width, height }) => {
ctx.addRect(0, 0, width, height);
},
{ color: "white", lineWeight: 2 },
);
example.blend(test, 2 + index * 104, 2);
test.resize(100, 200, mode);
example.blend(test, 2 + index * 104, 42);
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
import { createOpsCanvas, ResampleModeValues } from "@ops/canvas";
const example = createOpsCanvas(ResampleModeValues.length * 104 + 2, 286);
for (const [i, mode] of Object.entries(ResampleModeValues)) {
const index = parseInt(i, 10);
const test = createOpsCanvas(100, 200);
test.set(255, "a");
test.addNoise(
{ min: 0, max: 255 },
{ value: 5.0, space: "relativeMin" },
"perlin",
{ seed: "a", mask: "rgb" },
);
test.gradientRemap(
[
{ step: 0, color: "#e5f392" },
{ step: 0.5, color: "#e49e71" },
{ step: 1, color: "#d45f97" },
],
"r",
);
test.drawStrokePath(
(ctx, { width, height }) => {
ctx.addRect(0, 0, width, height);
},
{ color: "white", lineWeight: 2 },
);
example.blend(test, 2 + index * 104, 2);
test.resize(40, 80, mode);
example.blend(test, 2 + index * 104, 203);
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Grow opsCanvas size
import { createOpsCanvas, GrowModeValues } from "@ops/canvas";
const gradientSteps = [
{ step: 0, color: "#e5f392" },
{ step: 0.5, color: "#e49e71" },
{ step: 1, color: "#d45f97" },
];
const example = createOpsCanvas(GrowModeValues.length * 150 + 2, 206);
for (const [i, mode] of Object.entries(GrowModeValues)) {
const growExample = createOpsCanvas(50, 50);
growExample.gradient(gradientSteps, "linear", [0, 0], [1, 1]);
const x = 2 + parseInt(i, 10) * 152;
example.blend(growExample, x, 2);
growExample.grow(150, 150, mode, { offsetX: 20, offsetY: -20 });
example.blend(growExample, x, 54);
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
import { createOpsCanvas, GrowModeValues } from "@ops/canvas";
const gradientSteps = [
{ step: 0, color: "#e5f392" },
{ step: 0.5, color: "#e49e71" },
{ step: 1, color: "#d45f97" },
];
const example = createOpsCanvas(GrowModeValues.length * 150 + 2, 206);
for (const [i, mode] of Object.entries(GrowModeValues)) {
const growExample = createOpsCanvas(50, 50);
growExample.gradient(gradientSteps, "linear", [0, 0], [1, 1]);
const x = 2 + parseInt(i, 10) * 152;
example.blend(growExample, x, 2);
growExample.grow(150, 150, mode);
example.blend(growExample, x, 54);
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Crop opsCanvas
import { createOpsCanvas } from "@ops/canvas";
const gradientSteps = [
{ step: 0, color: "#e5f392" },
{ step: 0.5, color: "#e49e71" },
{ step: 1, color: "#d45f97" },
];
const example = createOpsCanvas(200, 166);
const test = createOpsCanvas(50, 80);
test.gradient(gradientSteps, "linear", [0, 0], [1, 1]);
test.fills.linesGrid({
spacing: 10,
lineWidth: 2,
mask: "r",
repeatType: "repeat",
color: "purple",
});
example.blend(test, 2, 2);
let cropped = test.clone();
cropped.crop({ x: 20, y: 40, width: 30, height: 30 });
example.blend(cropped, 2, 90);
cropped = test.clone();
cropped.crop({ top: 10, left: 2, right: 30, bottom: 5 });
example.blend(cropped, 50, 90);
cropped = test.clone();
cropped.crop({ top: 2, sides: 5, bottom: 35 });
example.blend(cropped, 100, 90);
cropped = test.clone();
cropped.crop({ vertical: 5, horizontal: 20 });
example.blend(cropped, 150, 90);
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Pad opsCanvas
import { createOpsCanvas } from "@ops/canvas";
const gradientSteps = [
{ step: 0, color: "#e5f392" },
{ step: 0.5, color: "#e49e71" },
{ step: 1, color: "#d45f97" },
];
const example = createOpsCanvas(302, 102);
const test = createOpsCanvas(50, 60);
test.gradient(gradientSteps, "linear", [0, 0], [1, 1]);
test.fills.linesGrid({
spacing: 10,
lineWidth: 2,
mask: "r",
repeatType: "repeat",
color: "purple",
});
example.blend(test, 2, 2, { showDebugBounds: true });
// default transparend border
{
const padded = test.clone();
padded.pad({ top: 20, sides: 10, bottom: 15 });
example.blend(padded, 60, 2, { showDebugBounds: true });
}
// colored border
{
const padded = test.clone();
padded.pad({ top: 20, sides: 10, bottom: 15, color: "red" });
example.blend(padded, 140, 2, { showDebugBounds: true });
}
// repeat edge colors
{
const padded = test.clone();
padded.pad({
top: 20,
sides: 10,
bottom: 15,
repeatEdges: true,
color: "red",
});
example.blend(padded, 220, 2, { showDebugBounds: true });
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Trim surrounding empty space in opsCanvas
// undefined
channel?:"r""g""b""a"// undefined
threshold?:number// undefined
padding?:number// undefined
trimX?:boolean// undefined
trimY?:booleanimport { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(80, 200);
const test = createOpsCanvas(50, 80);
test.drawFillPath(
(ctx, { width, height }) => {
ctx.addRect(5, 5, width * 0.5, height * 0.5);
},
{ color: "#d45f97" }
);
test.fillBackground("#0f0f");
example.blend(test, 2, 2, { mode: "add", showDebugBounds: true });
const trimmed = test.clone();
trimmed.trim({ padding: 0, channel: "r", trimX: false });
example.blend(trimmed, 2, 90, { mode: "add", showDebugBounds: true });
const trimmedPadded = test.clone();
trimmedPadded.trim({ padding: 8, channel: "r", trimX: false });
example.blend(trimmedPadded, 2, 138, { mode: "add", showDebugBounds: true });
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(80, 264);
const test = createOpsCanvas(50, 80);
test.drawFillPath(
(ctx, { width, height }) => {
ctx.addRect(5, 5, width * 0.5, height * 0.5);
},
{ color: "#d45f97" }
);
test.fillBackground("#0f0f");
example.blend(test, 2, 2, { mode: "add", showDebugBounds: true });
const trimmed = test.clone();
trimmed.trim({ padding: 0, channel: "r", trimY: false });
example.blend(trimmed, 2, 90, { mode: "add", showDebugBounds: true });
const trimmedPadded = test.clone();
trimmedPadded.trim({ padding: 8, channel: "r", trimY: false });
example.blend(trimmedPadded, 2, 178, { mode: "add", showDebugBounds: true });
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(80, 200);
const test = createOpsCanvas(50, 80);
test.drawFillPath(
(ctx, { width, height }) => {
ctx.addRect(5, 5, width * 0.5, height * 0.5);
},
{ color: "#d45f97" }
);
test.fillBackground("#0f0f");
example.blend(test, 2, 2, { mode: "add", showDebugBounds: true });
const trimmed = test.clone();
trimmed.trim({ padding: 0, channel: "r" });
example.blend(trimmed, 2, 90, { mode: "add", showDebugBounds: true });
const trimmedPadded = test.clone();
trimmedPadded.trim({ padding: 8, channel: "r" });
example.blend(trimmedPadded, 2, 138, { mode: "add", showDebugBounds: true });
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Put another opsCanvas data into this one
import { createOpsCanvas } from "@ops/canvas";
const gradientSteps = [
{ step: 0, color: "#e5f392" },
{ step: 0.5, color: "#e49e71" },
{ step: 1, color: "#d45f97" },
];
const example = createOpsCanvas(150, 150);
const otherOpsCanvas = createOpsCanvas(50, 50);
otherOpsCanvas.gradient(gradientSteps, "linear", [0, 0], [1, 1]);
otherOpsCanvas.drawStrokePath(
(ctx, { width, height }) => {
ctx.addRect(0, 0, width, height);
},
{ color: "black", lineWeight: 1 }
);
for (let i = 2; i < 100; i += 8) {
example.blend(otherOpsCanvas, i, i);
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Rotate opsCanvas clockwise
Rotate opsCanvas counter-clockwise
Flip opsCanvas in the x axis
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(170, 84);
const test = createOpsCanvas(80, 80);
test.setColor("#d45f97");
test.drawText(":)", {
x: 2,
y: 2,
size: 40,
color: "white",
align: "left",
baseline: "top",
});
example.blend(test, 0, 2);
test.flipX();
example.blend(test, 82, 2);
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Flip opsCanvas in the y axis
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(170, 84);
const test = createOpsCanvas(80, 80);
test.setColor("#d45f97");
test.drawText(":)", {
x: 2,
y: 2,
size: 40,
color: "white",
align: "left",
baseline: "top",
});
example.blend(test, 0, 2);
test.flipY();
example.blend(test, 82, 2);
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
Invert colors
Returns a clone of the opsCanvas
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(158, 54);
const test = createOpsCanvas(50, 50);
test.setColor("#e5f392", "rgba");
example.blend(test, 2, 2);
const clone = test.clone();
test.setColor("#e49e71", "rgba");
// test now has a different color
example.blend(test, 54, 2);
// clone still has original color
example.blend(clone, 106, 2);
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
change and manipulate colors
set channels to color with css color string or array of numbers `[0-255, 0-255, 0-255, 0-255]`
set channels of transparent pixels to color with css color string or array of numbers `[0-255, 0-255, 0-255, 0-255]`
import { createOpsCanvas } from "@ops/canvas";
const example = createOpsCanvas(200, 112);
example.drawFillPath(
(ctx) => {
ctx.addRect(100, 0, 100, 178);
},
{ color: "white" }
);
const test = createOpsCanvas(96, 20);
test.gradient(
[
{
step: 0,
color: "#e5f392ff",
},
{
step: 1,
color: "#e5f39200",
},
],
"linear",
[0.1, 0],
[0.9, 0],
{ scaleSpace: "relative" }
);
example.blend(test, 2, 2, { mode: "add" });
example.blend(test, 102, 2, { mode: "add" });
for (const [y, data] of Object.entries([
{ color: "#d45f9700" },
{ color: "#d45f9790" },
{ color: "#d45f97cc" },
{ color: "#d45f97" },
])) {
const filled = test.clone();
filled.fillBackground(data.color);
example.blend(filled, 2, 24 + parseInt(y, 10) * 22, {
mode: "add",
});
example.blend(filled, 102, 24 + parseInt(y, 10) * 22, {
mode: "add",
});
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
set channels to gradient
// [0..1]
step:numberimport { createOpsCanvas, GradientTypeValues } from "@ops/canvas";
const points: [[number, number], [number, number]][] = [
[
[0.5, 0.5],
[0.0, 0],
],
[
[0.5, 0.5],
[0.5, 0],
],
[
[0.5, 0.5],
[1, 0],
],
[
[0.5, 0.5],
[1, 0.5],
],
[
[0.5, 0.5],
[1, 1],
],
[
[0.5, 0.5],
[0, 1],
],
[
[0.5, 0.5],
[0, 0.5],
],
[
[0.8, 0.1],
[0.5, 1],
],
];
const gradientSteps = [
{ step: 0, color: "#e5f392" },
{ step: 0.5, color: "#e49e71" },
{ step: 1, color: "#d45f97" },
];
const example = createOpsCanvas(points.length * 52 + 2, 200 + 4);
const gradientTest = createOpsCanvas(50, 50);
for (const [x, point] of Object.entries(points)) {
for (const [y, type] of Object.entries(GradientTypeValues)) {
gradientTest.gradient(gradientSteps, type, point[0], point[1]);
example.blend(
gradientTest,
2 + parseInt(x, 10) * 52,
2 + parseInt(y, 10) * 50,
);
}
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
import { createOpsCanvas, GradientTypeValues } from "@ops/canvas";
const shaperValues = [-1, 0.0, 0.1, 0.5, 1, 2, 4, 8];
const gradientSteps = [
{ step: 0, color: "#e5f392" },
{ step: 0.5, color: "#e49e71" },
{ step: 1, color: "#d45f97" },
];
const example = createOpsCanvas(shaperValues.length * 52 + 2, 200 + 4);
const gradientTest = createOpsCanvas(50, 50);
for (const [x, shaper] of Object.entries(shaperValues)) {
for (const [y, type] of Object.entries(GradientTypeValues)) {
gradientTest.gradient(gradientSteps, type, [0.5, 0.5], [0.8, 0.2], {
shaper,
});
example.blend(
gradientTest,
2 + parseInt(x, 10) * 52,
2 + parseInt(y, 10) * 50,
);
}
}
Deno.writeFileSync(Deno.args[0], example.toPngBuffer());
based on one channel, set the colors with a gradient
// [0..1]
step:numberread and write images
Get png buffer from opsCanvas