Initial commit

This commit is contained in:
robert committed 2025-05-30 18:13:30 +08:00
commit e49726988c
5445 files changed
+1089914

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"rootDir": "../src",
"module": "nodenext",
"moduleResolution": "nodenext"
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"extends": "./build.json",
"include": [
"../src/**/*.ts",
"../src/**/*.cts",
"../src/**/*.tsx",
"../src/**/*.json"
],
"exclude": [
"../**/*.test.ts",
"../src/**/*.mts",
"../src/package.json"
],
"compilerOptions": {
"outDir": "../.tshy-build/commonjs"
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"extends": "./build.json",
"include": [
"../src/**/*.ts",
"../src/**/*.mts",
"../src/**/*.tsx",
"../src/**/*.json"
],
"exclude": [
"../**/*.test.ts",
"../src/package.json"
],
"compilerOptions": {
"outDir": "../.tshy-build/esm"
}
}
+5
View File
@@ -0,0 +1,5 @@

> @jimp/plugin-color@1.5.0 build /Users/andrewlisowski/Documents/jimp/plugins/plugin-color
> tshy
+5
View File
@@ -0,0 +1,5 @@

> @jimp/plugin-color@1.1.2 lint /Users/andrewlisowski/Documents/jimp/plugins/plugin-color
> eslint .
+26
View File
@@ -0,0 +1,26 @@
> @jimp/plugin-color@1.1.1 test:browser /Users/andrewlisowski/Documents/jimp/plugins/plugin-color
> vitest --config vitest.config.browser.mjs "--watch=false" "--u"
 RUN  v1.4.0 /Users/andrewlisowski/Documents/jimp/plugins/plugin-color
 Browser runner started at http://localhost:5173/
[?25l · src/normalize.test.ts (2)
· src/convolution.test.ts (3)
[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l[?25l · src/normalize.test.ts (2)
· src/convolution.test.ts (3)
· src/index.test.ts (7)
[?25l ✓ src/normalize.test.ts (2)
· src/convolution.test.ts (3)
· src/index.test.ts (7)
 ✓ src/normalize.test.ts (2)
✓ src/convolution.test.ts (3)
✓ src/index.test.ts (7)
 Test Files  3 passed (3)
 Tests  12 passed (12)
 Start at  00:40:22
 Duration  3.94s (transform 0ms, setup 0ms, collect 1.07s, tests 13ms, environment 0ms, prepare 0ms)
[?25h[?25h
File diff suppressed because it is too large. Load diff
+74
View File
@@ -0,0 +1,74 @@
# v1.1.3 (Mon Sep 02 2024)
#### 🐛 Bug Fix
- Update deps [#1319](https://github.com/jimp-dev/jimp/pull/1319) ([@hipstersmoothie](https://github.com/hipstersmoothie))
#### Authors: 1
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
---
# v1.1.2 (Mon Sep 02 2024)
### Release Notes
#### Make brightness function behave like other implementations ([#1312](https://github.com/jimp-dev/jimp/pull/1312))
This PR changes the `brightness` function to behave like the css brightness function and other implementations. Previously it was doing something odd. Instead of multiplying the color channel by the multiplier value, it multiplied against the inversion of the current color.
In the current version a value of `1` won't change the colors at all. Values above 1 will brighten the colors, values below 1 will darken the colors.
---
#### 🐛 Bug Fix
- Fix pixelate not working well with alpha channel [#1314](https://github.com/jimp-dev/jimp/pull/1314) ([@hipstersmoothie](https://github.com/hipstersmoothie))
- Make brightness function behave like other implementations [#1312](https://github.com/jimp-dev/jimp/pull/1312) ([@hipstersmoothie](https://github.com/hipstersmoothie))
#### Authors: 1
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
---
# v1.1.0 (Sun Sep 01 2024)
#### ⚠️ Pushed to `main`
- update more docs ([@hipstersmoothie](https://github.com/hipstersmoothie))
#### Authors: 1
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
---
# v1.0.3 (Sat Aug 31 2024)
#### 🐛 Bug Fix
- Fix build [#1303](https://github.com/jimp-dev/jimp/pull/1303) ([@hipstersmoothie](https://github.com/hipstersmoothie))
#### ⚠️ Pushed to `main`
- add clean script ([@hipstersmoothie](https://github.com/hipstersmoothie))
#### Authors: 1
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
---
# v1.0.2 (Sat Aug 31 2024)
#### ⚠️ Pushed to `main`
- set side effects ([@hipstersmoothie](https://github.com/hipstersmoothie))
- fix versions ([@hipstersmoothie](https://github.com/hipstersmoothie))
- add publish config ([@hipstersmoothie](https://github.com/hipstersmoothie))
#### Authors: 1
- Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie))
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Oliver Moran
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+20
View File
@@ -0,0 +1,20 @@
<div align="center">
<img width="200" height="200"
src="https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-11/256/crayon.png">
<h1>@jimp/utils</h1>
<p>Utils for jimp extensions.</p>
</div>
- [color](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#color)
- [brightness](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#brightness)
- [contrast](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#contrast)
- [posterize](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#posterize)
- [opacity](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#opacity)
- [sepia](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#sepia)
- [fade](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#fade)
- [convolution](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#convolution)
- [opaque](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#opaque)
- [pixelate](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#pixelate)
- [convolute](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#convolute)
- [normalize](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#normalize)
- [invert](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#invert)
+706
View File
@@ -0,0 +1,706 @@
import { Edge, JimpClass } from "@jimp/types";
import { z } from "zod";
declare const ConvolutionOptionsSchema: z.ZodUnion<[z.ZodArray<z.ZodArray<z.ZodNumber, "many">, "many">, z.ZodObject<{
/** a matrix to weight the neighbors sum */
kernel: z.ZodArray<z.ZodArray<z.ZodNumber, "many">, "many">;
/**define how to sum pixels from outside the border */
edgeHandling: z.ZodOptional<z.ZodNativeEnum<typeof Edge>>;
}, "strip", z.ZodTypeAny, {
kernel: number[][];
edgeHandling?: Edge | undefined;
}, {
kernel: number[][];
edgeHandling?: Edge | undefined;
}>]>;
type ConvolutionOptions = z.infer<typeof ConvolutionOptionsSchema>;
declare const ConvoluteOptionsSchema: z.ZodUnion<[z.ZodArray<z.ZodArray<z.ZodNumber, "many">, "many">, z.ZodObject<{
/** the convolution kernel */
kernel: z.ZodArray<z.ZodArray<z.ZodNumber, "many">, "many">;
/** the x position of the region to apply convolution to */
x: z.ZodOptional<z.ZodNumber>;
/** the y position of the region to apply convolution to */
y: z.ZodOptional<z.ZodNumber>;
/** the width of the region to apply convolution to */
w: z.ZodOptional<z.ZodNumber>;
/** the height of the region to apply convolution to */
h: z.ZodOptional<z.ZodNumber>;
}, "strip", z.ZodTypeAny, {
kernel: number[][];
x?: number | undefined;
y?: number | undefined;
w?: number | undefined;
h?: number | undefined;
}, {
kernel: number[][];
x?: number | undefined;
y?: number | undefined;
w?: number | undefined;
h?: number | undefined;
}>]>;
type ConvoluteOptions = z.infer<typeof ConvoluteOptionsSchema>;
declare const PixelateOptionsSchema: z.ZodUnion<[z.ZodNumber, z.ZodObject<{
/** the size of the pixels */
size: z.ZodNumber;
/** the x position of the region to pixelate */
x: z.ZodOptional<z.ZodNumber>;
/** the y position of the region to pixelate */
y: z.ZodOptional<z.ZodNumber>;
/** the width of the region to pixelate */
w: z.ZodOptional<z.ZodNumber>;
/** the height of the region to pixelate */
h: z.ZodOptional<z.ZodNumber>;
}, "strip", z.ZodTypeAny, {
size: number;
x?: number | undefined;
y?: number | undefined;
w?: number | undefined;
h?: number | undefined;
}, {
size: number;
x?: number | undefined;
y?: number | undefined;
w?: number | undefined;
h?: number | undefined;
}>]>;
type PixelateOptions = z.infer<typeof PixelateOptionsSchema>;
declare const HueActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"hue">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "hue";
}, {
params: [number];
apply: "hue";
}>;
export type HueAction = z.infer<typeof HueActionSchema>;
declare const SpinActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"spin">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "spin";
}, {
params: [number];
apply: "spin";
}>;
export type SpinAction = z.infer<typeof SpinActionSchema>;
declare const LightenActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"lighten">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "lighten";
params?: [number] | undefined;
}, {
apply: "lighten";
params?: [number] | undefined;
}>;
export type LightenAction = z.infer<typeof LightenActionSchema>;
declare const MixActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"mix">;
params: z.ZodUnion<[z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>], null>, z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>, z.ZodNumber], null>]>;
}, "strip", z.ZodTypeAny, {
params: [{
r: number;
g: number;
b: number;
}] | [{
r: number;
g: number;
b: number;
}, number];
apply: "mix";
}, {
params: [{
r: number;
g: number;
b: number;
}] | [{
r: number;
g: number;
b: number;
}, number];
apply: "mix";
}>;
export type MixAction = z.infer<typeof MixActionSchema>;
declare const TintActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"tint">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "tint";
params?: [number] | undefined;
}, {
apply: "tint";
params?: [number] | undefined;
}>;
export type TintAction = z.infer<typeof TintActionSchema>;
declare const ShadeActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"shade">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "shade";
params?: [number] | undefined;
}, {
apply: "shade";
params?: [number] | undefined;
}>;
export type ShadeAction = z.infer<typeof ShadeActionSchema>;
declare const XorActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"xor">;
params: z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>], null>;
}, "strip", z.ZodTypeAny, {
params: [{
r: number;
g: number;
b: number;
}];
apply: "xor";
}, {
params: [{
r: number;
g: number;
b: number;
}];
apply: "xor";
}>;
export type XorAction = z.infer<typeof XorActionSchema>;
declare const RedActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"red">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "red";
}, {
params: [number];
apply: "red";
}>;
export type RedAction = z.infer<typeof RedActionSchema>;
declare const GreenActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"green">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "green";
}, {
params: [number];
apply: "green";
}>;
export type GreenAction = z.infer<typeof GreenActionSchema>;
declare const BlueActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"blue">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "blue";
}, {
params: [number];
apply: "blue";
}>;
export type BlueAction = z.infer<typeof BlueActionSchema>;
declare const BrightenActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"brighten">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "brighten";
params?: [number] | undefined;
}, {
apply: "brighten";
params?: [number] | undefined;
}>;
export type BrightenAction = z.infer<typeof BrightenActionSchema>;
declare const DarkenActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"darken">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "darken";
params?: [number] | undefined;
}, {
apply: "darken";
params?: [number] | undefined;
}>;
export type DarkenAction = z.infer<typeof DarkenActionSchema>;
declare const DesaturateActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"desaturate">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "desaturate";
params?: [number] | undefined;
}, {
apply: "desaturate";
params?: [number] | undefined;
}>;
export type DesaturateAction = z.infer<typeof DesaturateActionSchema>;
declare const SaturateActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"saturate">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "saturate";
params?: [number] | undefined;
}, {
apply: "saturate";
params?: [number] | undefined;
}>;
export type SaturateAction = z.infer<typeof SaturateActionSchema>;
declare const GrayscaleActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"greyscale">;
params: z.ZodOptional<z.ZodTuple<[], null>>;
}, "strip", z.ZodTypeAny, {
apply: "greyscale";
params?: [] | undefined;
}, {
apply: "greyscale";
params?: [] | undefined;
}>;
export type GrayscaleAction = z.infer<typeof GrayscaleActionSchema>;
declare const ColorActionNameSchema: z.ZodUnion<[z.ZodObject<{
apply: z.ZodLiteral<"hue">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "hue";
}, {
params: [number];
apply: "hue";
}>, z.ZodObject<{
apply: z.ZodLiteral<"spin">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "spin";
}, {
params: [number];
apply: "spin";
}>, z.ZodObject<{
apply: z.ZodLiteral<"lighten">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "lighten";
params?: [number] | undefined;
}, {
apply: "lighten";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"mix">;
params: z.ZodUnion<[z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>], null>, z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>, z.ZodNumber], null>]>;
}, "strip", z.ZodTypeAny, {
params: [{
r: number;
g: number;
b: number;
}] | [{
r: number;
g: number;
b: number;
}, number];
apply: "mix";
}, {
params: [{
r: number;
g: number;
b: number;
}] | [{
r: number;
g: number;
b: number;
}, number];
apply: "mix";
}>, z.ZodObject<{
apply: z.ZodLiteral<"tint">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "tint";
params?: [number] | undefined;
}, {
apply: "tint";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"shade">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "shade";
params?: [number] | undefined;
}, {
apply: "shade";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"xor">;
params: z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>], null>;
}, "strip", z.ZodTypeAny, {
params: [{
r: number;
g: number;
b: number;
}];
apply: "xor";
}, {
params: [{
r: number;
g: number;
b: number;
}];
apply: "xor";
}>, z.ZodObject<{
apply: z.ZodLiteral<"red">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "red";
}, {
params: [number];
apply: "red";
}>, z.ZodObject<{
apply: z.ZodLiteral<"green">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "green";
}, {
params: [number];
apply: "green";
}>, z.ZodObject<{
apply: z.ZodLiteral<"blue">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "blue";
}, {
params: [number];
apply: "blue";
}>, z.ZodObject<{
apply: z.ZodLiteral<"brighten">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "brighten";
params?: [number] | undefined;
}, {
apply: "brighten";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"darken">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "darken";
params?: [number] | undefined;
}, {
apply: "darken";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"desaturate">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "desaturate";
params?: [number] | undefined;
}, {
apply: "desaturate";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"saturate">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "saturate";
params?: [number] | undefined;
}, {
apply: "saturate";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"greyscale">;
params: z.ZodOptional<z.ZodTuple<[], null>>;
}, "strip", z.ZodTypeAny, {
apply: "greyscale";
params?: [] | undefined;
}, {
apply: "greyscale";
params?: [] | undefined;
}>]>;
export type ColorAction = z.infer<typeof ColorActionNameSchema>;
export declare const ColorActionName: Readonly<{
LIGHTEN: "lighten";
BRIGHTEN: "brighten";
DARKEN: "darken";
DESATURATE: "desaturate";
SATURATE: "saturate";
GREYSCALE: "greyscale";
SPIN: "spin";
HUE: "hue";
MIX: "mix";
TINT: "tint";
SHADE: "shade";
XOR: "xor";
RED: "red";
GREEN: "green";
BLUE: "blue";
}>;
export declare const methods: {
/**
* Normalizes the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.normalize();
* ```
*/
normalize<I extends JimpClass>(image: I): I;
/**
* Inverts the colors in the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.invert();
* ```
*/
invert<I extends JimpClass>(image: I): I;
/**
* Adjusts the brightness of the image
* @param val the amount to adjust the brightness.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.brightness(0.5);
* ```
*/
brightness<I extends JimpClass>(image: I, val: number): I;
/**
* Adjusts the contrast of the image
* @param val the amount to adjust the contrast, a number between -1 and +1
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.contrast(0.75);
* ```
*/
contrast<I extends JimpClass>(image: I, val: number): I;
/**
* Apply a posterize effect
* @param n the amount to adjust the contrast, minimum threshold is two
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.posterize(5);
* ```
*/
posterize<I extends JimpClass>(image: I, n: number): I;
/**
* Removes colour from the image using ITU Rec 709 luminance values
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.greyscale();
* ```
*/
greyscale<I extends JimpClass>(image: I): I;
/**
* Multiplies the opacity of each pixel by a factor between 0 and 1
* @param f A number, the factor by which to multiply the opacity of each pixel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opacity(0.5);
* ```
*/
opacity<I extends JimpClass>(image: I, f: number): I;
/**
* Applies a sepia tone to the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.sepia();
* ```
*/
sepia<I extends JimpClass>(image: I): I;
/**
* Fades each pixel by a factor between 0 and 1
* @param f A number from 0 to 1. 0 will haven no effect. 1 will turn the image completely transparent.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.fade(0.7);
* ```
*/
fade<I extends JimpClass>(image: I, f: number): I;
/**
* Adds each element of the image to its local neighbors, weighted by the kernel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.convolute([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
* ```
*/
convolution<I extends JimpClass>(image: I, options: ConvolutionOptions): I;
/**
* Set the alpha channel on every pixel to fully opaque.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opaque();
* ```
*/
opaque<I extends JimpClass>(image: I): I;
/**
* Pixelates the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // pixelate the whole image
* image.pixelate(10);
*
* // pixelate a region
* image.pixelate(10, 10, 10, 20, 20);
* ```
*/
pixelate<I extends JimpClass>(image: I, options: PixelateOptions): I;
/**
* Applies a convolution kernel to the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // apply a convolution kernel to the whole image
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
*
* // apply a convolution kernel to a region
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ], 10, 10, 10, 20);
* ```
*/
convolute<I extends JimpClass>(image: I, options: ConvoluteOptions): I;
/**
* Apply multiple color modification rules
* @param actions list of color modification rules, in following format: { apply: '<rule-name>', params: [ <rule-parameters> ] }
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.color([
* { apply: "hue", params: [-90] },
* { apply: "lighten", params: [50] },
* { apply: "xor", params: ["#06D"] },
* ]);
* ```
*/
color<I extends JimpClass>(image: I, actions: ColorAction[]): I;
};
export {};
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
+713
View File
@@ -0,0 +1,713 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.methods = exports.ColorActionName = void 0;
const tinycolor2_1 = __importDefault(require("tinycolor2"));
const utils_1 = require("@jimp/utils");
const types_1 = require("@jimp/types");
const zod_1 = require("zod");
const ConvolutionMatrixSchema = zod_1.z.array(zod_1.z.number()).min(1).array();
const ConvolutionComplexOptionsSchema = zod_1.z.object({
/** a matrix to weight the neighbors sum */
kernel: ConvolutionMatrixSchema,
/**define how to sum pixels from outside the border */
edgeHandling: zod_1.z.nativeEnum(types_1.Edge).optional(),
});
const ConvolutionOptionsSchema = zod_1.z.union([
ConvolutionMatrixSchema,
ConvolutionComplexOptionsSchema,
]);
const ConvoluteComplexOptionsSchema = zod_1.z.object({
/** the convolution kernel */
kernel: ConvolutionMatrixSchema,
/** the x position of the region to apply convolution to */
x: zod_1.z.number().optional(),
/** the y position of the region to apply convolution to */
y: zod_1.z.number().optional(),
/** the width of the region to apply convolution to */
w: zod_1.z.number().optional(),
/** the height of the region to apply convolution to */
h: zod_1.z.number().optional(),
});
const ConvoluteOptionsSchema = zod_1.z.union([
ConvolutionMatrixSchema,
ConvoluteComplexOptionsSchema,
]);
const PixelateSize = zod_1.z.number().min(1).max(Infinity);
const PixelateComplexOptionsSchema = zod_1.z.object({
/** the size of the pixels */
size: PixelateSize,
/** the x position of the region to pixelate */
x: zod_1.z.number().optional(),
/** the y position of the region to pixelate */
y: zod_1.z.number().optional(),
/** the width of the region to pixelate */
w: zod_1.z.number().optional(),
/** the height of the region to pixelate */
h: zod_1.z.number().optional(),
});
const PixelateOptionsSchema = zod_1.z.union([
PixelateSize,
PixelateComplexOptionsSchema,
]);
function applyKernel(image, kernel, x, y) {
const value = [0, 0, 0, 0];
const size = (kernel.length - 1) / 2;
for (let kx = 0; kx < kernel.length; kx += 1) {
for (let ky = 0; ky < kernel[kx].length; ky += 1) {
const idx = image.getPixelIndex(x + kx - size, y + ky - size);
value[0] += image.bitmap.data[idx] * kernel[kx][ky];
value[1] += image.bitmap.data[idx + 1] * kernel[kx][ky];
value[2] += image.bitmap.data[idx + 2] * kernel[kx][ky];
value[3] += image.bitmap.data[idx + 3] * kernel[kx][ky];
}
}
return value;
}
function mix(clr, clr2, p = 50) {
return {
r: (clr2.r - clr.r) * (p / 100) + clr.r,
g: (clr2.g - clr.g) * (p / 100) + clr.g,
b: (clr2.b - clr.b) * (p / 100) + clr.b,
};
}
const HueActionSchema = zod_1.z.object({
apply: zod_1.z.literal("hue"),
params: zod_1.z.tuple([zod_1.z.number().min(-360).max(360)]),
});
const SpinActionSchema = zod_1.z.object({
apply: zod_1.z.literal("spin"),
params: zod_1.z.tuple([zod_1.z.number().min(-360).max(360)]),
});
const LightenActionSchema = zod_1.z.object({
apply: zod_1.z.literal("lighten"),
params: zod_1.z.tuple([zod_1.z.number().min(0).max(100)]).optional(),
});
const RGBColorSchema = zod_1.z.object({
r: zod_1.z.number().min(0).max(255),
g: zod_1.z.number().min(0).max(255),
b: zod_1.z.number().min(0).max(255),
});
const MixActionSchema = zod_1.z.object({
apply: zod_1.z.literal("mix"),
params: zod_1.z.union([
zod_1.z.tuple([RGBColorSchema]),
zod_1.z.tuple([RGBColorSchema, zod_1.z.number().min(0).max(100)]),
]),
});
const TintActionSchema = zod_1.z.object({
apply: zod_1.z.literal("tint"),
params: zod_1.z.tuple([zod_1.z.number().min(0).max(100)]).optional(),
});
const ShadeActionSchema = zod_1.z.object({
apply: zod_1.z.literal("shade"),
params: zod_1.z.tuple([zod_1.z.number().min(0).max(100)]).optional(),
});
const XorActionSchema = zod_1.z.object({
apply: zod_1.z.literal("xor"),
params: zod_1.z.tuple([RGBColorSchema]),
});
const RedActionSchema = zod_1.z.object({
apply: zod_1.z.literal("red"),
params: zod_1.z.tuple([zod_1.z.number().min(-255).max(255)]),
});
const GreenActionSchema = zod_1.z.object({
apply: zod_1.z.literal("green"),
params: zod_1.z.tuple([zod_1.z.number().min(-255).max(255)]),
});
const BlueActionSchema = zod_1.z.object({
apply: zod_1.z.literal("blue"),
params: zod_1.z.tuple([zod_1.z.number().min(-255).max(255)]),
});
const BrightenActionSchema = zod_1.z.object({
apply: zod_1.z.literal("brighten"),
params: zod_1.z.tuple([zod_1.z.number().min(0).max(100)]).optional(),
});
const DarkenActionSchema = zod_1.z.object({
apply: zod_1.z.literal("darken"),
params: zod_1.z.tuple([zod_1.z.number().min(0).max(100)]).optional(),
});
const DesaturateActionSchema = zod_1.z.object({
apply: zod_1.z.literal("desaturate"),
params: zod_1.z.tuple([zod_1.z.number().min(0).max(100)]).optional(),
});
const SaturateActionSchema = zod_1.z.object({
apply: zod_1.z.literal("saturate"),
params: zod_1.z.tuple([zod_1.z.number().min(0).max(100)]).optional(),
});
const GrayscaleActionSchema = zod_1.z.object({
apply: zod_1.z.literal("greyscale"),
params: zod_1.z.tuple([]).optional(),
});
const ColorActionNameSchema = zod_1.z.union([
HueActionSchema,
SpinActionSchema,
LightenActionSchema,
MixActionSchema,
TintActionSchema,
ShadeActionSchema,
XorActionSchema,
RedActionSchema,
GreenActionSchema,
BlueActionSchema,
BrightenActionSchema,
DarkenActionSchema,
DesaturateActionSchema,
SaturateActionSchema,
GrayscaleActionSchema,
]);
exports.ColorActionName = Object.freeze({
LIGHTEN: "lighten",
BRIGHTEN: "brighten",
DARKEN: "darken",
DESATURATE: "desaturate",
SATURATE: "saturate",
GREYSCALE: "greyscale",
SPIN: "spin",
HUE: "hue",
MIX: "mix",
TINT: "tint",
SHADE: "shade",
XOR: "xor",
RED: "red",
GREEN: "green",
BLUE: "blue",
});
/**
* Get an image's histogram
* @return An object with an array of color occurrence counts for each channel (r,g,b)
*/
function histogram(image) {
const histogram = {
r: new Array(256).fill(0),
g: new Array(256).fill(0),
b: new Array(256).fill(0),
};
image.scan((_, __, index) => {
histogram.r[image.bitmap.data[index + 0]]++;
histogram.g[image.bitmap.data[index + 1]]++;
histogram.b[image.bitmap.data[index + 2]]++;
});
return histogram;
}
/**
* Normalize values
* @param value Pixel channel value.
* @param min Minimum value for channel
* @param max Maximum value for channel
*/
const normalizeValue = function (value, min, max) {
return ((value - min) * 255) / (max - min);
};
const getBounds = function (histogramChannel) {
return [
histogramChannel.findIndex((value) => value > 0),
255 -
histogramChannel
.slice()
.reverse()
.findIndex((value) => value > 0),
];
};
exports.methods = {
/**
* Normalizes the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.normalize();
* ```
*/
normalize(image) {
const h = histogram(image);
// store bounds (minimum and maximum values)
const bounds = {
r: getBounds(h.r),
g: getBounds(h.g),
b: getBounds(h.b),
};
// apply value transformations
image.scan((_, __, idx) => {
const r = image.bitmap.data[idx + 0];
const g = image.bitmap.data[idx + 1];
const b = image.bitmap.data[idx + 2];
image.bitmap.data[idx + 0] = normalizeValue(r, bounds.r[0], bounds.r[1]);
image.bitmap.data[idx + 1] = normalizeValue(g, bounds.g[0], bounds.g[1]);
image.bitmap.data[idx + 2] = normalizeValue(b, bounds.b[0], bounds.b[1]);
});
return image;
},
/**
* Inverts the colors in the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.invert();
* ```
*/
invert(image) {
image.scan((_, __, idx) => {
image.bitmap.data[idx] = 255 - image.bitmap.data[idx];
image.bitmap.data[idx + 1] = 255 - image.bitmap.data[idx + 1];
image.bitmap.data[idx + 2] = 255 - image.bitmap.data[idx + 2];
});
return image;
},
/**
* Adjusts the brightness of the image
* @param val the amount to adjust the brightness.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.brightness(0.5);
* ```
*/
brightness(image, val) {
if (typeof val !== "number") {
throw new Error("val must be numbers");
}
image.scan((_, __, idx) => {
image.bitmap.data[idx] = (0, utils_1.limit255)(image.bitmap.data[idx] * val);
image.bitmap.data[idx + 1] = (0, utils_1.limit255)(image.bitmap.data[idx + 1] * val);
image.bitmap.data[idx + 2] = (0, utils_1.limit255)(image.bitmap.data[idx + 2] * val);
});
return image;
},
/**
* Adjusts the contrast of the image
* @param val the amount to adjust the contrast, a number between -1 and +1
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.contrast(0.75);
* ```
*/
contrast(image, val) {
if (typeof val !== "number") {
throw new Error("val must be numbers");
}
if (val < -1 || val > +1) {
throw new Error("val must be a number between -1 and +1");
}
const factor = (val + 1) / (1 - val);
function adjust(value) {
value = Math.floor(factor * (value - 127) + 127);
return value < 0 ? 0 : value > 255 ? 255 : value;
}
image.scan((_, __, idx) => {
image.bitmap.data[idx] = adjust(image.bitmap.data[idx]);
image.bitmap.data[idx + 1] = adjust(image.bitmap.data[idx + 1]);
image.bitmap.data[idx + 2] = adjust(image.bitmap.data[idx + 2]);
});
return image;
},
/**
* Apply a posterize effect
* @param n the amount to adjust the contrast, minimum threshold is two
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.posterize(5);
* ```
*/
posterize(image, n) {
if (typeof n !== "number") {
throw new Error("n must be numbers");
}
// minimum of 2 levels
if (n < 2) {
n = 2;
}
image.scan((_, __, idx) => {
const r = image.bitmap.data[idx];
const g = image.bitmap.data[idx + 1];
const b = image.bitmap.data[idx + 2];
image.bitmap.data[idx] =
(Math.floor((r / 255) * (n - 1)) / (n - 1)) * 255;
image.bitmap.data[idx + 1] =
(Math.floor((g / 255) * (n - 1)) / (n - 1)) * 255;
image.bitmap.data[idx + 2] =
(Math.floor((b / 255) * (n - 1)) / (n - 1)) * 255;
});
return image;
},
/**
* Removes colour from the image using ITU Rec 709 luminance values
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.greyscale();
* ```
*/
greyscale(image) {
image.scan((_, __, idx) => {
// const grey = parseInt(
// 0.2126 * image.bitmap.data[idx]! +
// 0.7152 * image.bitmap.data[idx + 1]! +
// 0.0722 * image.bitmap.data[idx + 2]!,
// 10
// );
const grey = 0.2126 * image.bitmap.data[idx] +
0.7152 * image.bitmap.data[idx + 1] +
0.0722 * image.bitmap.data[idx + 2];
image.bitmap.data[idx] = grey;
image.bitmap.data[idx + 1] = grey;
image.bitmap.data[idx + 2] = grey;
});
return image;
},
/**
* Multiplies the opacity of each pixel by a factor between 0 and 1
* @param f A number, the factor by which to multiply the opacity of each pixel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opacity(0.5);
* ```
*/
opacity(image, f) {
if (typeof f !== "number") {
throw new Error("f must be a number");
}
if (f < 0 || f > 1) {
throw new Error("f must be a number from 0 to 1");
}
image.scan((_, __, idx) => {
const v = image.bitmap.data[idx + 3] * f;
image.bitmap.data[idx + 3] = v;
});
return image;
},
/**
* Applies a sepia tone to the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.sepia();
* ```
*/
sepia(image) {
image.scan((_, __, idx) => {
let red = image.bitmap.data[idx];
let green = image.bitmap.data[idx + 1];
let blue = image.bitmap.data[idx + 2];
red = red * 0.393 + green * 0.769 + blue * 0.189;
green = red * 0.349 + green * 0.686 + blue * 0.168;
blue = red * 0.272 + green * 0.534 + blue * 0.131;
image.bitmap.data[idx] = red < 255 ? red : 255;
image.bitmap.data[idx + 1] = green < 255 ? green : 255;
image.bitmap.data[idx + 2] = blue < 255 ? blue : 255;
});
return image;
},
/**
* Fades each pixel by a factor between 0 and 1
* @param f A number from 0 to 1. 0 will haven no effect. 1 will turn the image completely transparent.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.fade(0.7);
* ```
*/
fade(image, f) {
if (typeof f !== "number") {
throw new Error("f must be a number");
}
if (f < 0 || f > 1) {
throw new Error("f must be a number from 0 to 1");
}
// this method is an alternative to opacity (which may be deprecated)
return this.opacity(image, 1 - f);
},
/**
* Adds each element of the image to its local neighbors, weighted by the kernel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.convolute([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
* ```
*/
convolution(image, options) {
const parsed = ConvolutionOptionsSchema.parse(options);
const { kernel, edgeHandling = types_1.Edge.EXTEND } = "kernel" in parsed ? parsed : { kernel: parsed, edgeHandling: undefined };
if (!kernel[0]) {
throw new Error("kernel must be a matrix");
}
const newData = Buffer.from(image.bitmap.data);
const kRows = kernel.length;
const kCols = kernel[0].length;
const rowEnd = Math.floor(kRows / 2);
const colEnd = Math.floor(kCols / 2);
const rowIni = -rowEnd;
const colIni = -colEnd;
let weight;
let rSum;
let gSum;
let bSum;
let ri;
let gi;
let bi;
let xi;
let yi;
let idxi;
image.scan((x, y, idx) => {
bSum = 0;
gSum = 0;
rSum = 0;
for (let row = rowIni; row <= rowEnd; row++) {
for (let col = colIni; col <= colEnd; col++) {
xi = x + col;
yi = y + row;
weight = kernel[row + rowEnd][col + colEnd];
idxi = image.getPixelIndex(xi, yi, edgeHandling);
if (idxi === -1) {
bi = 0;
gi = 0;
ri = 0;
}
else {
ri = image.bitmap.data[idxi + 0];
gi = image.bitmap.data[idxi + 1];
bi = image.bitmap.data[idxi + 2];
}
rSum += weight * ri;
gSum += weight * gi;
bSum += weight * bi;
}
}
if (rSum < 0) {
rSum = 0;
}
if (gSum < 0) {
gSum = 0;
}
if (bSum < 0) {
bSum = 0;
}
if (rSum > 255) {
rSum = 255;
}
if (gSum > 255) {
gSum = 255;
}
if (bSum > 255) {
bSum = 255;
}
newData[idx + 0] = rSum;
newData[idx + 1] = gSum;
newData[idx + 2] = bSum;
});
image.bitmap.data = newData;
return image;
},
/**
* Set the alpha channel on every pixel to fully opaque.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opaque();
* ```
*/
opaque(image) {
image.scan((_, __, idx) => {
image.bitmap.data[idx + 3] = 255;
});
return image;
},
/**
* Pixelates the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // pixelate the whole image
* image.pixelate(10);
*
* // pixelate a region
* image.pixelate(10, 10, 10, 20, 20);
* ```
*/
pixelate(image, options) {
const parsed = PixelateOptionsSchema.parse(options);
const { size, x = 0, y = 0, w = image.bitmap.width - x, h = image.bitmap.height - y, } = typeof parsed === "number"
? { size: parsed }
: parsed;
const kernel = [
[1 / 16, 2 / 16, 1 / 16],
[2 / 16, 4 / 16, 2 / 16],
[1 / 16, 2 / 16, 1 / 16],
];
const source = (0, utils_1.clone)(image);
(0, utils_1.scan)(source, x, y, w, h, (xx, yx, idx) => {
xx = size * Math.floor(xx / size);
yx = size * Math.floor(yx / size);
const value = applyKernel(source, kernel, xx, yx);
image.bitmap.data[idx] = value[0];
image.bitmap.data[idx + 1] = value[1];
image.bitmap.data[idx + 2] = value[2];
image.bitmap.data[idx + 3] = value[3];
});
return image;
},
/**
* Applies a convolution kernel to the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // apply a convolution kernel to the whole image
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
*
* // apply a convolution kernel to a region
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ], 10, 10, 10, 20);
* ```
*/
convolute(image, options) {
const parsed = ConvoluteOptionsSchema.parse(options);
const { kernel, x = 0, y = 0, w = image.bitmap.width - x, h = image.bitmap.height - y, } = "kernel" in parsed
? parsed
: { kernel: parsed };
const source = (0, utils_1.clone)(image);
(0, utils_1.scan)(source, x, y, w, h, (xx, yx, idx) => {
const value = applyKernel(source, kernel, xx, yx);
image.bitmap.data[idx] = (0, utils_1.limit255)(value[0]);
image.bitmap.data[idx + 1] = (0, utils_1.limit255)(value[1]);
image.bitmap.data[idx + 2] = (0, utils_1.limit255)(value[2]);
image.bitmap.data[idx + 3] = (0, utils_1.limit255)(value[3]);
});
return image;
},
/**
* Apply multiple color modification rules
* @param actions list of color modification rules, in following format: { apply: '<rule-name>', params: [ <rule-parameters> ] }
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.color([
* { apply: "hue", params: [-90] },
* { apply: "lighten", params: [50] },
* { apply: "xor", params: ["#06D"] },
* ]);
* ```
*/
color(image, actions) {
if (!actions || !Array.isArray(actions)) {
throw new Error("actions must be an array");
}
actions.forEach((action) => ColorActionNameSchema.parse(action));
actions = actions.map((action) => {
if (action.apply === "xor" || action.apply === "mix") {
action.params[0] = (0, tinycolor2_1.default)(action.params[0]).toRgb();
}
return action;
});
image.scan((_, __, idx) => {
let clr = {
r: image.bitmap.data[idx],
g: image.bitmap.data[idx + 1],
b: image.bitmap.data[idx + 2],
};
const colorModifier = (i, amount) => (0, utils_1.limit255)(clr[i] + amount);
actions.forEach((action) => {
if (action.apply === "mix") {
clr = mix(clr, action.params[0], action.params[1]);
}
else if (action.apply === "tint") {
clr = mix(clr, { r: 255, g: 255, b: 255 }, action.params?.[0]);
}
else if (action.apply === "shade") {
clr = mix(clr, { r: 0, g: 0, b: 0 }, action.params?.[0]);
}
else if (action.apply === "xor") {
clr = {
r: clr.r ^ action.params[0].r,
g: clr.g ^ action.params[0].g,
b: clr.b ^ action.params[0].b,
};
}
else if (action.apply === "red") {
clr.r = colorModifier("r", action.params[0]);
}
else if (action.apply === "green") {
clr.g = colorModifier("g", action.params[0]);
}
else if (action.apply === "blue") {
clr.b = colorModifier("b", action.params[0]);
}
else {
if (action.apply === "hue") {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
action.apply = "spin";
}
const tnyClr = (0, tinycolor2_1.default)(clr);
const fn = tnyClr[action.apply].bind(tnyClr);
if (!fn) {
throw new Error("action " + action.apply + " not supported");
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
clr = fn(...(action.params || [])).toRgb();
}
});
image.bitmap.data[idx] = clr.r;
image.bitmap.data[idx + 1] = clr.g;
image.bitmap.data[idx + 2] = clr.b;
});
return image;
},
};
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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 truncated
+3
View File
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
+706
View File
@@ -0,0 +1,706 @@
import { Edge, JimpClass } from "@jimp/types";
import { z } from "zod";
declare const ConvolutionOptionsSchema: z.ZodUnion<[z.ZodArray<z.ZodArray<z.ZodNumber, "many">, "many">, z.ZodObject<{
/** a matrix to weight the neighbors sum */
kernel: z.ZodArray<z.ZodArray<z.ZodNumber, "many">, "many">;
/**define how to sum pixels from outside the border */
edgeHandling: z.ZodOptional<z.ZodNativeEnum<typeof Edge>>;
}, "strip", z.ZodTypeAny, {
kernel: number[][];
edgeHandling?: Edge | undefined;
}, {
kernel: number[][];
edgeHandling?: Edge | undefined;
}>]>;
type ConvolutionOptions = z.infer<typeof ConvolutionOptionsSchema>;
declare const ConvoluteOptionsSchema: z.ZodUnion<[z.ZodArray<z.ZodArray<z.ZodNumber, "many">, "many">, z.ZodObject<{
/** the convolution kernel */
kernel: z.ZodArray<z.ZodArray<z.ZodNumber, "many">, "many">;
/** the x position of the region to apply convolution to */
x: z.ZodOptional<z.ZodNumber>;
/** the y position of the region to apply convolution to */
y: z.ZodOptional<z.ZodNumber>;
/** the width of the region to apply convolution to */
w: z.ZodOptional<z.ZodNumber>;
/** the height of the region to apply convolution to */
h: z.ZodOptional<z.ZodNumber>;
}, "strip", z.ZodTypeAny, {
kernel: number[][];
x?: number | undefined;
y?: number | undefined;
w?: number | undefined;
h?: number | undefined;
}, {
kernel: number[][];
x?: number | undefined;
y?: number | undefined;
w?: number | undefined;
h?: number | undefined;
}>]>;
type ConvoluteOptions = z.infer<typeof ConvoluteOptionsSchema>;
declare const PixelateOptionsSchema: z.ZodUnion<[z.ZodNumber, z.ZodObject<{
/** the size of the pixels */
size: z.ZodNumber;
/** the x position of the region to pixelate */
x: z.ZodOptional<z.ZodNumber>;
/** the y position of the region to pixelate */
y: z.ZodOptional<z.ZodNumber>;
/** the width of the region to pixelate */
w: z.ZodOptional<z.ZodNumber>;
/** the height of the region to pixelate */
h: z.ZodOptional<z.ZodNumber>;
}, "strip", z.ZodTypeAny, {
size: number;
x?: number | undefined;
y?: number | undefined;
w?: number | undefined;
h?: number | undefined;
}, {
size: number;
x?: number | undefined;
y?: number | undefined;
w?: number | undefined;
h?: number | undefined;
}>]>;
type PixelateOptions = z.infer<typeof PixelateOptionsSchema>;
declare const HueActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"hue">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "hue";
}, {
params: [number];
apply: "hue";
}>;
export type HueAction = z.infer<typeof HueActionSchema>;
declare const SpinActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"spin">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "spin";
}, {
params: [number];
apply: "spin";
}>;
export type SpinAction = z.infer<typeof SpinActionSchema>;
declare const LightenActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"lighten">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "lighten";
params?: [number] | undefined;
}, {
apply: "lighten";
params?: [number] | undefined;
}>;
export type LightenAction = z.infer<typeof LightenActionSchema>;
declare const MixActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"mix">;
params: z.ZodUnion<[z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>], null>, z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>, z.ZodNumber], null>]>;
}, "strip", z.ZodTypeAny, {
params: [{
r: number;
g: number;
b: number;
}] | [{
r: number;
g: number;
b: number;
}, number];
apply: "mix";
}, {
params: [{
r: number;
g: number;
b: number;
}] | [{
r: number;
g: number;
b: number;
}, number];
apply: "mix";
}>;
export type MixAction = z.infer<typeof MixActionSchema>;
declare const TintActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"tint">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "tint";
params?: [number] | undefined;
}, {
apply: "tint";
params?: [number] | undefined;
}>;
export type TintAction = z.infer<typeof TintActionSchema>;
declare const ShadeActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"shade">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "shade";
params?: [number] | undefined;
}, {
apply: "shade";
params?: [number] | undefined;
}>;
export type ShadeAction = z.infer<typeof ShadeActionSchema>;
declare const XorActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"xor">;
params: z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>], null>;
}, "strip", z.ZodTypeAny, {
params: [{
r: number;
g: number;
b: number;
}];
apply: "xor";
}, {
params: [{
r: number;
g: number;
b: number;
}];
apply: "xor";
}>;
export type XorAction = z.infer<typeof XorActionSchema>;
declare const RedActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"red">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "red";
}, {
params: [number];
apply: "red";
}>;
export type RedAction = z.infer<typeof RedActionSchema>;
declare const GreenActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"green">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "green";
}, {
params: [number];
apply: "green";
}>;
export type GreenAction = z.infer<typeof GreenActionSchema>;
declare const BlueActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"blue">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "blue";
}, {
params: [number];
apply: "blue";
}>;
export type BlueAction = z.infer<typeof BlueActionSchema>;
declare const BrightenActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"brighten">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "brighten";
params?: [number] | undefined;
}, {
apply: "brighten";
params?: [number] | undefined;
}>;
export type BrightenAction = z.infer<typeof BrightenActionSchema>;
declare const DarkenActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"darken">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "darken";
params?: [number] | undefined;
}, {
apply: "darken";
params?: [number] | undefined;
}>;
export type DarkenAction = z.infer<typeof DarkenActionSchema>;
declare const DesaturateActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"desaturate">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "desaturate";
params?: [number] | undefined;
}, {
apply: "desaturate";
params?: [number] | undefined;
}>;
export type DesaturateAction = z.infer<typeof DesaturateActionSchema>;
declare const SaturateActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"saturate">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "saturate";
params?: [number] | undefined;
}, {
apply: "saturate";
params?: [number] | undefined;
}>;
export type SaturateAction = z.infer<typeof SaturateActionSchema>;
declare const GrayscaleActionSchema: z.ZodObject<{
apply: z.ZodLiteral<"greyscale">;
params: z.ZodOptional<z.ZodTuple<[], null>>;
}, "strip", z.ZodTypeAny, {
apply: "greyscale";
params?: [] | undefined;
}, {
apply: "greyscale";
params?: [] | undefined;
}>;
export type GrayscaleAction = z.infer<typeof GrayscaleActionSchema>;
declare const ColorActionNameSchema: z.ZodUnion<[z.ZodObject<{
apply: z.ZodLiteral<"hue">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "hue";
}, {
params: [number];
apply: "hue";
}>, z.ZodObject<{
apply: z.ZodLiteral<"spin">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "spin";
}, {
params: [number];
apply: "spin";
}>, z.ZodObject<{
apply: z.ZodLiteral<"lighten">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "lighten";
params?: [number] | undefined;
}, {
apply: "lighten";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"mix">;
params: z.ZodUnion<[z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>], null>, z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>, z.ZodNumber], null>]>;
}, "strip", z.ZodTypeAny, {
params: [{
r: number;
g: number;
b: number;
}] | [{
r: number;
g: number;
b: number;
}, number];
apply: "mix";
}, {
params: [{
r: number;
g: number;
b: number;
}] | [{
r: number;
g: number;
b: number;
}, number];
apply: "mix";
}>, z.ZodObject<{
apply: z.ZodLiteral<"tint">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "tint";
params?: [number] | undefined;
}, {
apply: "tint";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"shade">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "shade";
params?: [number] | undefined;
}, {
apply: "shade";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"xor">;
params: z.ZodTuple<[z.ZodObject<{
r: z.ZodNumber;
g: z.ZodNumber;
b: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
r: number;
g: number;
b: number;
}, {
r: number;
g: number;
b: number;
}>], null>;
}, "strip", z.ZodTypeAny, {
params: [{
r: number;
g: number;
b: number;
}];
apply: "xor";
}, {
params: [{
r: number;
g: number;
b: number;
}];
apply: "xor";
}>, z.ZodObject<{
apply: z.ZodLiteral<"red">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "red";
}, {
params: [number];
apply: "red";
}>, z.ZodObject<{
apply: z.ZodLiteral<"green">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "green";
}, {
params: [number];
apply: "green";
}>, z.ZodObject<{
apply: z.ZodLiteral<"blue">;
params: z.ZodTuple<[z.ZodNumber], null>;
}, "strip", z.ZodTypeAny, {
params: [number];
apply: "blue";
}, {
params: [number];
apply: "blue";
}>, z.ZodObject<{
apply: z.ZodLiteral<"brighten">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "brighten";
params?: [number] | undefined;
}, {
apply: "brighten";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"darken">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "darken";
params?: [number] | undefined;
}, {
apply: "darken";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"desaturate">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "desaturate";
params?: [number] | undefined;
}, {
apply: "desaturate";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"saturate">;
params: z.ZodOptional<z.ZodTuple<[z.ZodNumber], null>>;
}, "strip", z.ZodTypeAny, {
apply: "saturate";
params?: [number] | undefined;
}, {
apply: "saturate";
params?: [number] | undefined;
}>, z.ZodObject<{
apply: z.ZodLiteral<"greyscale">;
params: z.ZodOptional<z.ZodTuple<[], null>>;
}, "strip", z.ZodTypeAny, {
apply: "greyscale";
params?: [] | undefined;
}, {
apply: "greyscale";
params?: [] | undefined;
}>]>;
export type ColorAction = z.infer<typeof ColorActionNameSchema>;
export declare const ColorActionName: Readonly<{
LIGHTEN: "lighten";
BRIGHTEN: "brighten";
DARKEN: "darken";
DESATURATE: "desaturate";
SATURATE: "saturate";
GREYSCALE: "greyscale";
SPIN: "spin";
HUE: "hue";
MIX: "mix";
TINT: "tint";
SHADE: "shade";
XOR: "xor";
RED: "red";
GREEN: "green";
BLUE: "blue";
}>;
export declare const methods: {
/**
* Normalizes the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.normalize();
* ```
*/
normalize<I extends JimpClass>(image: I): I;
/**
* Inverts the colors in the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.invert();
* ```
*/
invert<I extends JimpClass>(image: I): I;
/**
* Adjusts the brightness of the image
* @param val the amount to adjust the brightness.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.brightness(0.5);
* ```
*/
brightness<I extends JimpClass>(image: I, val: number): I;
/**
* Adjusts the contrast of the image
* @param val the amount to adjust the contrast, a number between -1 and +1
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.contrast(0.75);
* ```
*/
contrast<I extends JimpClass>(image: I, val: number): I;
/**
* Apply a posterize effect
* @param n the amount to adjust the contrast, minimum threshold is two
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.posterize(5);
* ```
*/
posterize<I extends JimpClass>(image: I, n: number): I;
/**
* Removes colour from the image using ITU Rec 709 luminance values
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.greyscale();
* ```
*/
greyscale<I extends JimpClass>(image: I): I;
/**
* Multiplies the opacity of each pixel by a factor between 0 and 1
* @param f A number, the factor by which to multiply the opacity of each pixel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opacity(0.5);
* ```
*/
opacity<I extends JimpClass>(image: I, f: number): I;
/**
* Applies a sepia tone to the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.sepia();
* ```
*/
sepia<I extends JimpClass>(image: I): I;
/**
* Fades each pixel by a factor between 0 and 1
* @param f A number from 0 to 1. 0 will haven no effect. 1 will turn the image completely transparent.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.fade(0.7);
* ```
*/
fade<I extends JimpClass>(image: I, f: number): I;
/**
* Adds each element of the image to its local neighbors, weighted by the kernel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.convolute([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
* ```
*/
convolution<I extends JimpClass>(image: I, options: ConvolutionOptions): I;
/**
* Set the alpha channel on every pixel to fully opaque.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opaque();
* ```
*/
opaque<I extends JimpClass>(image: I): I;
/**
* Pixelates the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // pixelate the whole image
* image.pixelate(10);
*
* // pixelate a region
* image.pixelate(10, 10, 10, 20, 20);
* ```
*/
pixelate<I extends JimpClass>(image: I, options: PixelateOptions): I;
/**
* Applies a convolution kernel to the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // apply a convolution kernel to the whole image
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
*
* // apply a convolution kernel to a region
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ], 10, 10, 10, 20);
* ```
*/
convolute<I extends JimpClass>(image: I, options: ConvoluteOptions): I;
/**
* Apply multiple color modification rules
* @param actions list of color modification rules, in following format: { apply: '<rule-name>', params: [ <rule-parameters> ] }
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.color([
* { apply: "hue", params: [-90] },
* { apply: "lighten", params: [50] },
* { apply: "xor", params: ["#06D"] },
* ]);
* ```
*/
color<I extends JimpClass>(image: I, actions: ColorAction[]): I;
};
export {};
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
+707
View File
@@ -0,0 +1,707 @@
import tinyColor from "tinycolor2";
import { clone, limit255, scan } from "@jimp/utils";
import { Edge } from "@jimp/types";
import { z } from "zod";
const ConvolutionMatrixSchema = z.array(z.number()).min(1).array();
const ConvolutionComplexOptionsSchema = z.object({
/** a matrix to weight the neighbors sum */
kernel: ConvolutionMatrixSchema,
/**define how to sum pixels from outside the border */
edgeHandling: z.nativeEnum(Edge).optional(),
});
const ConvolutionOptionsSchema = z.union([
ConvolutionMatrixSchema,
ConvolutionComplexOptionsSchema,
]);
const ConvoluteComplexOptionsSchema = z.object({
/** the convolution kernel */
kernel: ConvolutionMatrixSchema,
/** the x position of the region to apply convolution to */
x: z.number().optional(),
/** the y position of the region to apply convolution to */
y: z.number().optional(),
/** the width of the region to apply convolution to */
w: z.number().optional(),
/** the height of the region to apply convolution to */
h: z.number().optional(),
});
const ConvoluteOptionsSchema = z.union([
ConvolutionMatrixSchema,
ConvoluteComplexOptionsSchema,
]);
const PixelateSize = z.number().min(1).max(Infinity);
const PixelateComplexOptionsSchema = z.object({
/** the size of the pixels */
size: PixelateSize,
/** the x position of the region to pixelate */
x: z.number().optional(),
/** the y position of the region to pixelate */
y: z.number().optional(),
/** the width of the region to pixelate */
w: z.number().optional(),
/** the height of the region to pixelate */
h: z.number().optional(),
});
const PixelateOptionsSchema = z.union([
PixelateSize,
PixelateComplexOptionsSchema,
]);
function applyKernel(image, kernel, x, y) {
const value = [0, 0, 0, 0];
const size = (kernel.length - 1) / 2;
for (let kx = 0; kx < kernel.length; kx += 1) {
for (let ky = 0; ky < kernel[kx].length; ky += 1) {
const idx = image.getPixelIndex(x + kx - size, y + ky - size);
value[0] += image.bitmap.data[idx] * kernel[kx][ky];
value[1] += image.bitmap.data[idx + 1] * kernel[kx][ky];
value[2] += image.bitmap.data[idx + 2] * kernel[kx][ky];
value[3] += image.bitmap.data[idx + 3] * kernel[kx][ky];
}
}
return value;
}
function mix(clr, clr2, p = 50) {
return {
r: (clr2.r - clr.r) * (p / 100) + clr.r,
g: (clr2.g - clr.g) * (p / 100) + clr.g,
b: (clr2.b - clr.b) * (p / 100) + clr.b,
};
}
const HueActionSchema = z.object({
apply: z.literal("hue"),
params: z.tuple([z.number().min(-360).max(360)]),
});
const SpinActionSchema = z.object({
apply: z.literal("spin"),
params: z.tuple([z.number().min(-360).max(360)]),
});
const LightenActionSchema = z.object({
apply: z.literal("lighten"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
const RGBColorSchema = z.object({
r: z.number().min(0).max(255),
g: z.number().min(0).max(255),
b: z.number().min(0).max(255),
});
const MixActionSchema = z.object({
apply: z.literal("mix"),
params: z.union([
z.tuple([RGBColorSchema]),
z.tuple([RGBColorSchema, z.number().min(0).max(100)]),
]),
});
const TintActionSchema = z.object({
apply: z.literal("tint"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
const ShadeActionSchema = z.object({
apply: z.literal("shade"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
const XorActionSchema = z.object({
apply: z.literal("xor"),
params: z.tuple([RGBColorSchema]),
});
const RedActionSchema = z.object({
apply: z.literal("red"),
params: z.tuple([z.number().min(-255).max(255)]),
});
const GreenActionSchema = z.object({
apply: z.literal("green"),
params: z.tuple([z.number().min(-255).max(255)]),
});
const BlueActionSchema = z.object({
apply: z.literal("blue"),
params: z.tuple([z.number().min(-255).max(255)]),
});
const BrightenActionSchema = z.object({
apply: z.literal("brighten"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
const DarkenActionSchema = z.object({
apply: z.literal("darken"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
const DesaturateActionSchema = z.object({
apply: z.literal("desaturate"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
const SaturateActionSchema = z.object({
apply: z.literal("saturate"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
const GrayscaleActionSchema = z.object({
apply: z.literal("greyscale"),
params: z.tuple([]).optional(),
});
const ColorActionNameSchema = z.union([
HueActionSchema,
SpinActionSchema,
LightenActionSchema,
MixActionSchema,
TintActionSchema,
ShadeActionSchema,
XorActionSchema,
RedActionSchema,
GreenActionSchema,
BlueActionSchema,
BrightenActionSchema,
DarkenActionSchema,
DesaturateActionSchema,
SaturateActionSchema,
GrayscaleActionSchema,
]);
export const ColorActionName = Object.freeze({
LIGHTEN: "lighten",
BRIGHTEN: "brighten",
DARKEN: "darken",
DESATURATE: "desaturate",
SATURATE: "saturate",
GREYSCALE: "greyscale",
SPIN: "spin",
HUE: "hue",
MIX: "mix",
TINT: "tint",
SHADE: "shade",
XOR: "xor",
RED: "red",
GREEN: "green",
BLUE: "blue",
});
/**
* Get an image's histogram
* @return An object with an array of color occurrence counts for each channel (r,g,b)
*/
function histogram(image) {
const histogram = {
r: new Array(256).fill(0),
g: new Array(256).fill(0),
b: new Array(256).fill(0),
};
image.scan((_, __, index) => {
histogram.r[image.bitmap.data[index + 0]]++;
histogram.g[image.bitmap.data[index + 1]]++;
histogram.b[image.bitmap.data[index + 2]]++;
});
return histogram;
}
/**
* Normalize values
* @param value Pixel channel value.
* @param min Minimum value for channel
* @param max Maximum value for channel
*/
const normalizeValue = function (value, min, max) {
return ((value - min) * 255) / (max - min);
};
const getBounds = function (histogramChannel) {
return [
histogramChannel.findIndex((value) => value > 0),
255 -
histogramChannel
.slice()
.reverse()
.findIndex((value) => value > 0),
];
};
export const methods = {
/**
* Normalizes the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.normalize();
* ```
*/
normalize(image) {
const h = histogram(image);
// store bounds (minimum and maximum values)
const bounds = {
r: getBounds(h.r),
g: getBounds(h.g),
b: getBounds(h.b),
};
// apply value transformations
image.scan((_, __, idx) => {
const r = image.bitmap.data[idx + 0];
const g = image.bitmap.data[idx + 1];
const b = image.bitmap.data[idx + 2];
image.bitmap.data[idx + 0] = normalizeValue(r, bounds.r[0], bounds.r[1]);
image.bitmap.data[idx + 1] = normalizeValue(g, bounds.g[0], bounds.g[1]);
image.bitmap.data[idx + 2] = normalizeValue(b, bounds.b[0], bounds.b[1]);
});
return image;
},
/**
* Inverts the colors in the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.invert();
* ```
*/
invert(image) {
image.scan((_, __, idx) => {
image.bitmap.data[idx] = 255 - image.bitmap.data[idx];
image.bitmap.data[idx + 1] = 255 - image.bitmap.data[idx + 1];
image.bitmap.data[idx + 2] = 255 - image.bitmap.data[idx + 2];
});
return image;
},
/**
* Adjusts the brightness of the image
* @param val the amount to adjust the brightness.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.brightness(0.5);
* ```
*/
brightness(image, val) {
if (typeof val !== "number") {
throw new Error("val must be numbers");
}
image.scan((_, __, idx) => {
image.bitmap.data[idx] = limit255(image.bitmap.data[idx] * val);
image.bitmap.data[idx + 1] = limit255(image.bitmap.data[idx + 1] * val);
image.bitmap.data[idx + 2] = limit255(image.bitmap.data[idx + 2] * val);
});
return image;
},
/**
* Adjusts the contrast of the image
* @param val the amount to adjust the contrast, a number between -1 and +1
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.contrast(0.75);
* ```
*/
contrast(image, val) {
if (typeof val !== "number") {
throw new Error("val must be numbers");
}
if (val < -1 || val > +1) {
throw new Error("val must be a number between -1 and +1");
}
const factor = (val + 1) / (1 - val);
function adjust(value) {
value = Math.floor(factor * (value - 127) + 127);
return value < 0 ? 0 : value > 255 ? 255 : value;
}
image.scan((_, __, idx) => {
image.bitmap.data[idx] = adjust(image.bitmap.data[idx]);
image.bitmap.data[idx + 1] = adjust(image.bitmap.data[idx + 1]);
image.bitmap.data[idx + 2] = adjust(image.bitmap.data[idx + 2]);
});
return image;
},
/**
* Apply a posterize effect
* @param n the amount to adjust the contrast, minimum threshold is two
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.posterize(5);
* ```
*/
posterize(image, n) {
if (typeof n !== "number") {
throw new Error("n must be numbers");
}
// minimum of 2 levels
if (n < 2) {
n = 2;
}
image.scan((_, __, idx) => {
const r = image.bitmap.data[idx];
const g = image.bitmap.data[idx + 1];
const b = image.bitmap.data[idx + 2];
image.bitmap.data[idx] =
(Math.floor((r / 255) * (n - 1)) / (n - 1)) * 255;
image.bitmap.data[idx + 1] =
(Math.floor((g / 255) * (n - 1)) / (n - 1)) * 255;
image.bitmap.data[idx + 2] =
(Math.floor((b / 255) * (n - 1)) / (n - 1)) * 255;
});
return image;
},
/**
* Removes colour from the image using ITU Rec 709 luminance values
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.greyscale();
* ```
*/
greyscale(image) {
image.scan((_, __, idx) => {
// const grey = parseInt(
// 0.2126 * image.bitmap.data[idx]! +
// 0.7152 * image.bitmap.data[idx + 1]! +
// 0.0722 * image.bitmap.data[idx + 2]!,
// 10
// );
const grey = 0.2126 * image.bitmap.data[idx] +
0.7152 * image.bitmap.data[idx + 1] +
0.0722 * image.bitmap.data[idx + 2];
image.bitmap.data[idx] = grey;
image.bitmap.data[idx + 1] = grey;
image.bitmap.data[idx + 2] = grey;
});
return image;
},
/**
* Multiplies the opacity of each pixel by a factor between 0 and 1
* @param f A number, the factor by which to multiply the opacity of each pixel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opacity(0.5);
* ```
*/
opacity(image, f) {
if (typeof f !== "number") {
throw new Error("f must be a number");
}
if (f < 0 || f > 1) {
throw new Error("f must be a number from 0 to 1");
}
image.scan((_, __, idx) => {
const v = image.bitmap.data[idx + 3] * f;
image.bitmap.data[idx + 3] = v;
});
return image;
},
/**
* Applies a sepia tone to the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.sepia();
* ```
*/
sepia(image) {
image.scan((_, __, idx) => {
let red = image.bitmap.data[idx];
let green = image.bitmap.data[idx + 1];
let blue = image.bitmap.data[idx + 2];
red = red * 0.393 + green * 0.769 + blue * 0.189;
green = red * 0.349 + green * 0.686 + blue * 0.168;
blue = red * 0.272 + green * 0.534 + blue * 0.131;
image.bitmap.data[idx] = red < 255 ? red : 255;
image.bitmap.data[idx + 1] = green < 255 ? green : 255;
image.bitmap.data[idx + 2] = blue < 255 ? blue : 255;
});
return image;
},
/**
* Fades each pixel by a factor between 0 and 1
* @param f A number from 0 to 1. 0 will haven no effect. 1 will turn the image completely transparent.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.fade(0.7);
* ```
*/
fade(image, f) {
if (typeof f !== "number") {
throw new Error("f must be a number");
}
if (f < 0 || f > 1) {
throw new Error("f must be a number from 0 to 1");
}
// this method is an alternative to opacity (which may be deprecated)
return this.opacity(image, 1 - f);
},
/**
* Adds each element of the image to its local neighbors, weighted by the kernel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.convolute([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
* ```
*/
convolution(image, options) {
const parsed = ConvolutionOptionsSchema.parse(options);
const { kernel, edgeHandling = Edge.EXTEND } = "kernel" in parsed ? parsed : { kernel: parsed, edgeHandling: undefined };
if (!kernel[0]) {
throw new Error("kernel must be a matrix");
}
const newData = Buffer.from(image.bitmap.data);
const kRows = kernel.length;
const kCols = kernel[0].length;
const rowEnd = Math.floor(kRows / 2);
const colEnd = Math.floor(kCols / 2);
const rowIni = -rowEnd;
const colIni = -colEnd;
let weight;
let rSum;
let gSum;
let bSum;
let ri;
let gi;
let bi;
let xi;
let yi;
let idxi;
image.scan((x, y, idx) => {
bSum = 0;
gSum = 0;
rSum = 0;
for (let row = rowIni; row <= rowEnd; row++) {
for (let col = colIni; col <= colEnd; col++) {
xi = x + col;
yi = y + row;
weight = kernel[row + rowEnd][col + colEnd];
idxi = image.getPixelIndex(xi, yi, edgeHandling);
if (idxi === -1) {
bi = 0;
gi = 0;
ri = 0;
}
else {
ri = image.bitmap.data[idxi + 0];
gi = image.bitmap.data[idxi + 1];
bi = image.bitmap.data[idxi + 2];
}
rSum += weight * ri;
gSum += weight * gi;
bSum += weight * bi;
}
}
if (rSum < 0) {
rSum = 0;
}
if (gSum < 0) {
gSum = 0;
}
if (bSum < 0) {
bSum = 0;
}
if (rSum > 255) {
rSum = 255;
}
if (gSum > 255) {
gSum = 255;
}
if (bSum > 255) {
bSum = 255;
}
newData[idx + 0] = rSum;
newData[idx + 1] = gSum;
newData[idx + 2] = bSum;
});
image.bitmap.data = newData;
return image;
},
/**
* Set the alpha channel on every pixel to fully opaque.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opaque();
* ```
*/
opaque(image) {
image.scan((_, __, idx) => {
image.bitmap.data[idx + 3] = 255;
});
return image;
},
/**
* Pixelates the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // pixelate the whole image
* image.pixelate(10);
*
* // pixelate a region
* image.pixelate(10, 10, 10, 20, 20);
* ```
*/
pixelate(image, options) {
const parsed = PixelateOptionsSchema.parse(options);
const { size, x = 0, y = 0, w = image.bitmap.width - x, h = image.bitmap.height - y, } = typeof parsed === "number"
? { size: parsed }
: parsed;
const kernel = [
[1 / 16, 2 / 16, 1 / 16],
[2 / 16, 4 / 16, 2 / 16],
[1 / 16, 2 / 16, 1 / 16],
];
const source = clone(image);
scan(source, x, y, w, h, (xx, yx, idx) => {
xx = size * Math.floor(xx / size);
yx = size * Math.floor(yx / size);
const value = applyKernel(source, kernel, xx, yx);
image.bitmap.data[idx] = value[0];
image.bitmap.data[idx + 1] = value[1];
image.bitmap.data[idx + 2] = value[2];
image.bitmap.data[idx + 3] = value[3];
});
return image;
},
/**
* Applies a convolution kernel to the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // apply a convolution kernel to the whole image
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
*
* // apply a convolution kernel to a region
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ], 10, 10, 10, 20);
* ```
*/
convolute(image, options) {
const parsed = ConvoluteOptionsSchema.parse(options);
const { kernel, x = 0, y = 0, w = image.bitmap.width - x, h = image.bitmap.height - y, } = "kernel" in parsed
? parsed
: { kernel: parsed };
const source = clone(image);
scan(source, x, y, w, h, (xx, yx, idx) => {
const value = applyKernel(source, kernel, xx, yx);
image.bitmap.data[idx] = limit255(value[0]);
image.bitmap.data[idx + 1] = limit255(value[1]);
image.bitmap.data[idx + 2] = limit255(value[2]);
image.bitmap.data[idx + 3] = limit255(value[3]);
});
return image;
},
/**
* Apply multiple color modification rules
* @param actions list of color modification rules, in following format: { apply: '<rule-name>', params: [ <rule-parameters> ] }
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.color([
* { apply: "hue", params: [-90] },
* { apply: "lighten", params: [50] },
* { apply: "xor", params: ["#06D"] },
* ]);
* ```
*/
color(image, actions) {
if (!actions || !Array.isArray(actions)) {
throw new Error("actions must be an array");
}
actions.forEach((action) => ColorActionNameSchema.parse(action));
actions = actions.map((action) => {
if (action.apply === "xor" || action.apply === "mix") {
action.params[0] = tinyColor(action.params[0]).toRgb();
}
return action;
});
image.scan((_, __, idx) => {
let clr = {
r: image.bitmap.data[idx],
g: image.bitmap.data[idx + 1],
b: image.bitmap.data[idx + 2],
};
const colorModifier = (i, amount) => limit255(clr[i] + amount);
actions.forEach((action) => {
if (action.apply === "mix") {
clr = mix(clr, action.params[0], action.params[1]);
}
else if (action.apply === "tint") {
clr = mix(clr, { r: 255, g: 255, b: 255 }, action.params?.[0]);
}
else if (action.apply === "shade") {
clr = mix(clr, { r: 0, g: 0, b: 0 }, action.params?.[0]);
}
else if (action.apply === "xor") {
clr = {
r: clr.r ^ action.params[0].r,
g: clr.g ^ action.params[0].g,
b: clr.b ^ action.params[0].b,
};
}
else if (action.apply === "red") {
clr.r = colorModifier("r", action.params[0]);
}
else if (action.apply === "green") {
clr.g = colorModifier("g", action.params[0]);
}
else if (action.apply === "blue") {
clr.b = colorModifier("b", action.params[0]);
}
else {
if (action.apply === "hue") {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
action.apply = "spin";
}
const tnyClr = tinyColor(clr);
const fn = tnyClr[action.apply].bind(tnyClr);
if (!fn) {
throw new Error("action " + action.apply + " not supported");
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
clr = fn(...(action.params || [])).toRgb();
}
});
image.bitmap.data[idx] = clr.r;
image.bitmap.data[idx + 1] = clr.g;
image.bitmap.data[idx + 2] = clr.b;
});
return image;
},
};
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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 truncated
+3
View File
@@ -0,0 +1,3 @@
{
"type": "module"
}
+2
View File
@@ -0,0 +1,2 @@
import shared from "@jimp/config-eslint/base.js";
export default [...shared];
+72
View File
@@ -0,0 +1,72 @@
{
"name": "@jimp/plugin-color",
"version": "1.6.0",
"repository": "jimp-dev/jimp",
"engines": {
"node": ">=18"
},
"scripts": {
"lint": "eslint .",
"test": "vitest",
"test:browser": "vitest --config vitest.config.browser.mjs",
"build": "tshy",
"dev": "tshy --watch",
"clean": "rm -rf node_modules .tshy .tshy-build dist .turbo"
},
"author": "Andrew Lisowski <lisowski54@gmail.com>",
"license": "MIT",
"devDependencies": {
"@jimp/config-eslint": "1.6.0",
"@jimp/config-typescript": "1.6.0",
"@jimp/config-vitest": "1.6.0",
"@jimp/js-jpeg": "1.6.0",
"@jimp/js-png": "1.6.0",
"@jimp/test-utils": "1.6.0",
"@types/node": "^18.19.48",
"@types/tinycolor2": "^1.4.6",
"@vitest/browser": "^2.0.5",
"eslint": "^9.9.1",
"tshy": "^3.0.2",
"typescript": "^5.5.4",
"vite-plugin-node-polyfills": "^0.22.0",
"vitest": "^2.0.5"
},
"dependencies": {
"@jimp/core": "1.6.0",
"@jimp/types": "1.6.0",
"@jimp/utils": "1.6.0",
"tinycolor2": "^1.6.0",
"zod": "^3.23.8"
},
"tshy": {
"exclude": [
"**/*.test.ts"
],
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
}
},
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/commonjs/index.d.ts",
"default": "./dist/commonjs/index.js"
}
}
},
"main": "./dist/commonjs/index.js",
"types": "./dist/commonjs/index.d.ts",
"type": "module",
"publishConfig": {
"access": "public"
},
"sideEffects": false,
"module": "./dist/esm/index.js",
"gitHead": "c88abe6046dccbdb6e4f5f00c3dd403c81d83515"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

@@ -0,0 +1,145 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Convolution > 3x3 sharp matrix on EDGE_CROP 1`] = `
Visualization:
86666662
68EEE82■
6E□□□8■■
6E□88■■■
6E□88■■■
688■■■■■
62■■■■■■
2■■■■■■■
Data:
88-88-88ᶠᶠ 66-66-66ᶠᶠ 66-66-66ᶠᶠ 66-66-66ᶠᶠ 66-66-66ᶠᶠ 66-66-66ᶠᶠ 66-66-66ᶠᶠ 22-22-22ᶠᶠ
66-66-66ᶠᶠ 88-88-88ᶠᶠ EE-EE-EEᶠᶠ EE-EE-EEᶠᶠ EE-EE-EEᶠᶠ 88-88-88ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ
66-66-66ᶠᶠ EE-EE-EEᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
66-66-66ᶠᶠ EE-EE-EEᶠᶠ FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
66-66-66ᶠᶠ EE-EE-EEᶠᶠ FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
66-66-66ᶠᶠ 88-88-88ᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
66-66-66ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
22-22-22ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Convolution > 3x3 sharp matrix on EDGE_CROP 2`] = `
Visualization:
□C■66662
C■■2222■
■■■2222■
6222222■
6222222■
6222222■
6222222■
2■■■■■■■
Data:
FF-FF-FFᶠᶠ CC-CC-CCᶠᶠ 00-00-00ᶠᶠ 66-66-66ᶠᶠ 66-66-66ᶠᶠ 66-66-66ᶠᶠ 66-66-66ᶠᶠ 22-22-22ᶠᶠ
CC-CC-CCᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ
66-66-66ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ
66-66-66ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ
66-66-66ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ
66-66-66ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ
22-22-22ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Convolution > 3x3 sharp matrix on EDGE_EXTEND 1`] = `
Visualization:
22222222
28EEE822
2E□□□8■2
2E□88■■2
2E□88■■2
288■■■■2
22■■■■■2
22222222
Data:
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 88-88-88ᶠᶠ EE-EE-EEᶠᶠ EE-EE-EEᶠᶠ EE-EE-EEᶠᶠ 88-88-88ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ EE-EE-EEᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ EE-EE-EEᶠᶠ FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ EE-EE-EEᶠᶠ FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 88-88-88ᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
`;
exports[`Convolution > 3x3 sharp matrix on EDGE_EXTEND 2`] = `
Visualization:
8■■22222
■■■22222
■■■22222
22222222
22222222
22222222
22222222
22222222
Data:
88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
`;
exports[`Convolution > 3x3 sharp matrix on EDGE_WRAP 1`] = `
Visualization:
22222222
28EEE822
2E□□□8■2
2E□88■■2
2E□88■■2
288■■■■2
22■■■■■2
22222222
Data:
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 88-88-88ᶠᶠ EE-EE-EEᶠᶠ EE-EE-EEᶠᶠ EE-EE-EEᶠᶠ 88-88-88ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ EE-EE-EEᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ EE-EE-EEᶠᶠ FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ EE-EE-EEᶠᶠ FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 88-88-88ᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
`;
exports[`Convolution > 3x3 sharp matrix on EDGE_WRAP 2`] = `
Visualization:
□8■2222E
8■■22228
■■■22222
22222222
22222222
22222222
22222222
E8222228
Data:
FF-FF-FFᶠᶠ 88-88-88ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ EE-EE-EEᶠᶠ
88-88-88ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 88-88-88ᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ
EE-EE-EEᶠᶠ 88-88-88ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 22-22-22ᶠᶠ 88-88-88ᶠᶠ
`;
+169
View File
@@ -0,0 +1,169 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`brightness > should be able to brighten 1`] = `
Visualization:
6666666666
6666666666
6666666666
6666666666
6666666666
6666666666
6666666666
6666666666
6666666666
6666666666
Data:
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸ FF-00-00⁸⁸
`;
exports[`brightness > should be able to darken 1`] = `
Visualization:
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
Data:
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸ 22-00-00⁸⁸
`;
exports[`canvas color transformation > brighten 1`] = `
Visualization:
7777777777
777▫FF▫777
77FFFFFF77
7▫FF▫▫FF▫7
7FF▫77▫FF7
7FF▫77▫FF7
7▫FF▫▫FF▫7
77FFFFFF77
777▫FF▫777
7777777777
Data:
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ FF-40-40⁸⁸ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40ᶠᶠ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ FF-40-40⁸⁸ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40⁸⁸ FF-40-40⁸⁸ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40⁸⁸ 40-40-40⁰⁰
40-40-40⁰⁰ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ FF-40-40⁸⁸ FF-40-40ᶠᶠ FF-40-40ᶠᶠ 40-40-40⁰⁰
40-40-40⁰⁰ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ FF-40-40⁸⁸ FF-40-40ᶠᶠ FF-40-40ᶠᶠ 40-40-40⁰⁰
40-40-40⁰⁰ FF-40-40⁸⁸ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40⁸⁸ FF-40-40⁸⁸ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40⁸⁸ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40ᶠᶠ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ FF-40-40⁸⁸ FF-40-40ᶠᶠ FF-40-40ᶠᶠ FF-40-40⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
`;
exports[`canvas color transformation > can apply more than one color transformation 1`] = `
Visualization:
7777777777
7779■■9777
77■■■■■■77
79■■99■■97
7■■9779■■7
7■■9779■■7
79■■99■■97
77■■■■■■77
7779■■9777
7777777777
Data:
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 80-FF-FF⁸⁸ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FF⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 80-FF-FF⁸⁸ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FF⁸⁸ 80-FF-FF⁸⁸ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FF⁸⁸ 40-40-40⁰⁰
40-40-40⁰⁰ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FF⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ 80-FF-FF⁸⁸ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 40-40-40⁰⁰
40-40-40⁰⁰ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FF⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ 80-FF-FF⁸⁸ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 40-40-40⁰⁰
40-40-40⁰⁰ 80-FF-FF⁸⁸ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FF⁸⁸ 80-FF-FF⁸⁸ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FF⁸⁸ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 80-FF-FF⁸⁸ 80-FF-FFᶠᶠ 80-FF-FFᶠᶠ 80-FF-FF⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
`;
exports[`canvas color transformation > lighten 1`] = `
Visualization:
7777777777
777E▵▵E777
77▵▵▵▵▵▵77
7E▵▵EE▵▵E7
7▵▵E77E▵▵7
7▵▵E77E▵▵7
7E▵▵EE▵▵E7
77▵▵▵▵▵▵77
777E▵▵E777
7777777777
Data:
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ FF-80-80⁸⁸ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80ᶠᶠ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ FF-80-80⁸⁸ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80⁸⁸ FF-80-80⁸⁸ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80⁸⁸ 40-40-40⁰⁰
40-40-40⁰⁰ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ FF-80-80⁸⁸ FF-80-80ᶠᶠ FF-80-80ᶠᶠ 40-40-40⁰⁰
40-40-40⁰⁰ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ FF-80-80⁸⁸ FF-80-80ᶠᶠ FF-80-80ᶠᶠ 40-40-40⁰⁰
40-40-40⁰⁰ FF-80-80⁸⁸ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80⁸⁸ FF-80-80⁸⁸ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80⁸⁸ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80ᶠᶠ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ FF-80-80⁸⁸ FF-80-80ᶠᶠ FF-80-80ᶠᶠ FF-80-80⁸⁸ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰ 40-40-40⁰⁰
`;
exports[`canvas color transformation > spin hue 1`] = `
Visualization:
▩33▩
333333
▩33▩▩33▩
33▩ ▩33
33▩ ▩33
▩33▩▩33▩
333333
▩33▩
Data:
00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰
00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-FF-80⁸⁸ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80⁸⁸ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰
00-00-00⁰⁰ 00-00-00⁰⁰ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-00-00⁰⁰ 00-00-00⁰⁰
00-00-00⁰⁰ 00-FF-80⁸⁸ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80⁸⁸ 00-FF-80⁸⁸ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80⁸⁸ 00-00-00⁰⁰
00-00-00⁰⁰ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80⁸⁸ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-FF-80⁸⁸ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-00-00⁰⁰
00-00-00⁰⁰ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80⁸⁸ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-FF-80⁸⁸ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-00-00⁰⁰
00-00-00⁰⁰ 00-FF-80⁸⁸ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80⁸⁸ 00-FF-80⁸⁸ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80⁸⁸ 00-00-00⁰⁰
00-00-00⁰⁰ 00-00-00⁰⁰ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-00-00⁰⁰ 00-00-00⁰⁰
00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-FF-80⁸⁸ 00-FF-80ᶠᶠ 00-FF-80ᶠᶠ 00-FF-80⁸⁸ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰
00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰ 00-00-00⁰⁰
`;
@@ -0,0 +1,27 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Normalize > change grayscale image 1`] = `
Visualization:
■5▦
5▦A
▦A□
Data:
00-00-00ᶠᶠ 55-55-55ᶠᶠ 80-80-80ᶠᶠ
55-55-55ᶠᶠ 80-80-80ᶠᶠ AA-AA-AAᶠᶠ
80-80-80ᶠᶠ AA-AA-AAᶠᶠ FF-FF-FFᶠᶠ
`;
exports[`Normalize > change red/blue image 1`] = `
Visualization:
■□▩
E▸▰
Data:
00-00-00ᶠᶠ 7F-00-66ᶠᶠ 7F-00-66⁰⁰
7F-00-00ᶠᶠ 00-00-66ᶠᶠ FF-00-FFᶠᶠ
`;
+18
View File
@@ -0,0 +1,18 @@
import { expect, test, describe } from "vitest";
import png from "@jimp/js-png";
import jpeg from "@jimp/js-jpeg";
import { createJimp } from "@jimp/core";
import "@jimp/test-utils/image-snapshot";
import { methods } from "./index.js";
const jimp = createJimp({ formats: [png, jpeg], plugins: [methods] });
describe("Brightness", function () {
test("3x3 box blur matrix using convolute", async () => {
const image = await jimp.read(__dirname + "/images/tiles.jpg");
const output = await image.brightness(2).getBuffer("image/png");
expect(output).toMatchImageSnapshot();
});
});
+42
View File
@@ -0,0 +1,42 @@
import { expect, test, describe } from "vitest";
import png from "@jimp/js-png";
import jpeg from "@jimp/js-jpeg";
import { createJimp } from "@jimp/core";
import "@jimp/test-utils/image-snapshot";
import { methods } from "./index.js";
const jimp = createJimp({ formats: [png, jpeg], plugins: [methods] });
describe("Convolution", function () {
const blurM = [
[1 / 9, 1 / 9, 1 / 9],
[1 / 9, 1 / 9, 1 / 9],
[1 / 9, 1 / 9, 1 / 9],
];
test("3x3 box blur matrix using convolute", async () => {
const image = await jimp.read(__dirname + "/images/tiles.jpg");
const output = await image.convolute(blurM).getBuffer("image/png");
expect(output).toMatchImageSnapshot();
});
test("new pixel value is greater than 255", async () => {
const image = await jimp.read(__dirname + "/images/qr.jpg");
const convolutionMatrix = [
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 0],
[0, 1, 0, 1, 0],
[0, 1, 1, 1, 0],
[0, 0, 0, 0, 0],
];
const output = await image
.convolution(convolutionMatrix)
.getBuffer("image/png");
expect(output).toMatchImageSnapshot();
});
});
+71
View File
@@ -0,0 +1,71 @@
import { expect, test, describe } from "vitest";
import { makeTestImage } from "@jimp/test-utils";
import png from "@jimp/js-png";
import jpeg from "@jimp/js-jpeg";
import { Edge } from "@jimp/types";
import { createJimp } from "@jimp/core";
import { methods } from "./index.js";
const jimp = createJimp({ formats: [png, jpeg], plugins: [methods] });
describe("Convolution", function () {
const imgMid = jimp.fromBitmap(
makeTestImage(
"22222222",
"22222222",
"22888822",
"22888822",
"22888822",
"22888822",
"22222222",
"22222222",
),
);
/** stores the Jimp instances of the JGD images above. */
const imgTopLeft = jimp.fromBitmap(
makeTestImage(
"88222222",
"88222222",
"22222222",
"22222222",
"22222222",
"22222222",
"22222222",
"22222222",
),
);
const sharpM = [
[-1, -1, 0],
[-1, 1, 1],
[0, 1, 1],
];
test("3x3 sharp matrix on EDGE_EXTEND", () => {
expect(imgMid.clone().convolution(sharpM)).toMatchSnapshot();
expect(imgTopLeft.clone().convolution(sharpM)).toMatchSnapshot();
});
test("3x3 sharp matrix on EDGE_WRAP", () => {
expect(
imgMid.clone().convolution({ kernel: sharpM, edgeHandling: Edge.WRAP }),
).toMatchSnapshot();
expect(
imgTopLeft
.clone()
.convolution({ kernel: sharpM, edgeHandling: Edge.WRAP }),
).toMatchSnapshot();
});
test("3x3 sharp matrix on EDGE_CROP", () => {
expect(
imgMid.clone().convolution({ kernel: sharpM, edgeHandling: Edge.CROP }),
).toMatchSnapshot();
expect(
imgTopLeft
.clone()
.convolution({ kernel: sharpM, edgeHandling: Edge.CROP }),
).toMatchSnapshot();
});
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

+63
View File
@@ -0,0 +1,63 @@
import { expect, test, describe } from "vitest";
import { makeDonutTestImage } from "@jimp/test-utils";
import { createJimp } from "@jimp/core";
import { methods as color } from "./index.js";
const jimp = createJimp({ plugins: [color] });
describe("canvas color transformation", () => {
const redDonutJGD = makeDonutTestImage(0x00000000, 0xff000088, 0xff0000ff);
test("can apply more than one color transformation", () => {
const image = jimp.fromBitmap(redDonutJGD);
const newJGD = image.color([
{ apply: "hue", params: [-180] },
{ apply: "lighten", params: [25] },
]);
expect(newJGD.bitmap).toMatchSnapshot();
});
test("lighten", () => {
const image = jimp.fromBitmap(redDonutJGD);
expect(image.color([{ apply: "lighten", params: [25] }])).toMatchSnapshot();
});
test("brighten", () => {
const image = jimp.fromBitmap(redDonutJGD);
expect(
image.color([{ apply: "brighten", params: [25] }]),
).toMatchSnapshot();
});
test("spin hue", () => {
const image = jimp.fromBitmap(redDonutJGD);
expect(image.color([{ apply: "hue", params: [150] }])).toMatchSnapshot();
});
});
describe("brightness", () => {
test("brightness of 1 should be the same as no change", () => {
const jgd = makeDonutTestImage(0xff000088, 0xff000088, 0xff000088);
const image = jimp.fromBitmap(jgd);
const image2 = jimp.fromBitmap(jgd);
expect(image.brightness(1).bitmap).toStrictEqual(image2.bitmap);
});
test("should be able to brighten", () => {
const jgd = makeDonutTestImage(0xaa000088, 0xaa000088, 0xaa000088);
const image = jimp.fromBitmap(jgd);
expect(image.brightness(2).bitmap).toMatchSnapshot();
});
test("should be able to darken", () => {
const jgd = makeDonutTestImage(0xaa000088, 0xaa000088, 0xaa000088);
const image = jimp.fromBitmap(jgd);
expect(image.brightness(0.2).bitmap).toMatchSnapshot();
});
});
+863
View File
@@ -0,0 +1,863 @@
import tinyColor from "tinycolor2";
import { clone, limit255, scan } from "@jimp/utils";
import { Edge, JimpClass, RGBColor } from "@jimp/types";
import { z } from "zod";
const ConvolutionMatrixSchema = z.array(z.number()).min(1).array();
const ConvolutionComplexOptionsSchema = z.object({
/** a matrix to weight the neighbors sum */
kernel: ConvolutionMatrixSchema,
/**define how to sum pixels from outside the border */
edgeHandling: z.nativeEnum(Edge).optional(),
});
const ConvolutionOptionsSchema = z.union([
ConvolutionMatrixSchema,
ConvolutionComplexOptionsSchema,
]);
type ConvolutionOptions = z.infer<typeof ConvolutionOptionsSchema>;
const ConvoluteComplexOptionsSchema = z.object({
/** the convolution kernel */
kernel: ConvolutionMatrixSchema,
/** the x position of the region to apply convolution to */
x: z.number().optional(),
/** the y position of the region to apply convolution to */
y: z.number().optional(),
/** the width of the region to apply convolution to */
w: z.number().optional(),
/** the height of the region to apply convolution to */
h: z.number().optional(),
});
const ConvoluteOptionsSchema = z.union([
ConvolutionMatrixSchema,
ConvoluteComplexOptionsSchema,
]);
type ConvoluteComplexOptions = z.infer<typeof ConvoluteComplexOptionsSchema>;
type ConvoluteOptions = z.infer<typeof ConvoluteOptionsSchema>;
const PixelateSize = z.number().min(1).max(Infinity);
const PixelateComplexOptionsSchema = z.object({
/** the size of the pixels */
size: PixelateSize,
/** the x position of the region to pixelate */
x: z.number().optional(),
/** the y position of the region to pixelate */
y: z.number().optional(),
/** the width of the region to pixelate */
w: z.number().optional(),
/** the height of the region to pixelate */
h: z.number().optional(),
});
const PixelateOptionsSchema = z.union([
PixelateSize,
PixelateComplexOptionsSchema,
]);
type PixelateComplexOptions = z.infer<typeof PixelateComplexOptionsSchema>;
type PixelateOptions = z.infer<typeof PixelateOptionsSchema>;
function applyKernel(
image: JimpClass,
kernel: number[][],
x: number,
y: number,
) {
const value = [0, 0, 0, 0] as [number, number, number, number];
const size = (kernel.length - 1) / 2;
for (let kx = 0; kx < kernel.length; kx += 1) {
for (let ky = 0; ky < kernel[kx]!.length; ky += 1) {
const idx = image.getPixelIndex(x + kx - size, y + ky - size);
value[0] += image.bitmap.data[idx]! * kernel[kx]![ky]!;
value[1] += image.bitmap.data[idx + 1]! * kernel[kx]![ky]!;
value[2] += image.bitmap.data[idx + 2]! * kernel[kx]![ky]!;
value[3] += image.bitmap.data[idx + 3]! * kernel[kx]![ky]!;
}
}
return value;
}
function mix(clr: RGBColor, clr2: RGBColor, p = 50) {
return {
r: (clr2.r - clr.r) * (p / 100) + clr.r,
g: (clr2.g - clr.g) * (p / 100) + clr.g,
b: (clr2.b - clr.b) * (p / 100) + clr.b,
};
}
const HueActionSchema = z.object({
apply: z.literal("hue"),
params: z.tuple([z.number().min(-360).max(360)]),
});
export type HueAction = z.infer<typeof HueActionSchema>;
const SpinActionSchema = z.object({
apply: z.literal("spin"),
params: z.tuple([z.number().min(-360).max(360)]),
});
export type SpinAction = z.infer<typeof SpinActionSchema>;
const LightenActionSchema = z.object({
apply: z.literal("lighten"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
export type LightenAction = z.infer<typeof LightenActionSchema>;
const RGBColorSchema = z.object({
r: z.number().min(0).max(255),
g: z.number().min(0).max(255),
b: z.number().min(0).max(255),
});
const MixActionSchema = z.object({
apply: z.literal("mix"),
params: z.union([
z.tuple([RGBColorSchema]),
z.tuple([RGBColorSchema, z.number().min(0).max(100)]),
]),
});
export type MixAction = z.infer<typeof MixActionSchema>;
const TintActionSchema = z.object({
apply: z.literal("tint"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
export type TintAction = z.infer<typeof TintActionSchema>;
const ShadeActionSchema = z.object({
apply: z.literal("shade"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
export type ShadeAction = z.infer<typeof ShadeActionSchema>;
const XorActionSchema = z.object({
apply: z.literal("xor"),
params: z.tuple([RGBColorSchema]),
});
export type XorAction = z.infer<typeof XorActionSchema>;
const RedActionSchema = z.object({
apply: z.literal("red"),
params: z.tuple([z.number().min(-255).max(255)]),
});
export type RedAction = z.infer<typeof RedActionSchema>;
const GreenActionSchema = z.object({
apply: z.literal("green"),
params: z.tuple([z.number().min(-255).max(255)]),
});
export type GreenAction = z.infer<typeof GreenActionSchema>;
const BlueActionSchema = z.object({
apply: z.literal("blue"),
params: z.tuple([z.number().min(-255).max(255)]),
});
export type BlueAction = z.infer<typeof BlueActionSchema>;
const BrightenActionSchema = z.object({
apply: z.literal("brighten"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
export type BrightenAction = z.infer<typeof BrightenActionSchema>;
const DarkenActionSchema = z.object({
apply: z.literal("darken"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
export type DarkenAction = z.infer<typeof DarkenActionSchema>;
const DesaturateActionSchema = z.object({
apply: z.literal("desaturate"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
export type DesaturateAction = z.infer<typeof DesaturateActionSchema>;
const SaturateActionSchema = z.object({
apply: z.literal("saturate"),
params: z.tuple([z.number().min(0).max(100)]).optional(),
});
export type SaturateAction = z.infer<typeof SaturateActionSchema>;
const GrayscaleActionSchema = z.object({
apply: z.literal("greyscale"),
params: z.tuple([]).optional(),
});
export type GrayscaleAction = z.infer<typeof GrayscaleActionSchema>;
const ColorActionNameSchema = z.union([
HueActionSchema,
SpinActionSchema,
LightenActionSchema,
MixActionSchema,
TintActionSchema,
ShadeActionSchema,
XorActionSchema,
RedActionSchema,
GreenActionSchema,
BlueActionSchema,
BrightenActionSchema,
DarkenActionSchema,
DesaturateActionSchema,
SaturateActionSchema,
GrayscaleActionSchema,
]);
export type ColorAction = z.infer<typeof ColorActionNameSchema>;
export const ColorActionName = Object.freeze({
LIGHTEN: "lighten",
BRIGHTEN: "brighten",
DARKEN: "darken",
DESATURATE: "desaturate",
SATURATE: "saturate",
GREYSCALE: "greyscale",
SPIN: "spin",
HUE: "hue",
MIX: "mix",
TINT: "tint",
SHADE: "shade",
XOR: "xor",
RED: "red",
GREEN: "green",
BLUE: "blue",
});
/**
* Get an image's histogram
* @return An object with an array of color occurrence counts for each channel (r,g,b)
*/
function histogram<I extends JimpClass>(image: I) {
const histogram = {
r: new Array<number>(256).fill(0),
g: new Array<number>(256).fill(0),
b: new Array<number>(256).fill(0),
};
image.scan((_, __, index) => {
histogram.r[image.bitmap.data[index + 0]!]!++;
histogram.g[image.bitmap.data[index + 1]!]!++;
histogram.b[image.bitmap.data[index + 2]!]!++;
});
return histogram;
}
/**
* Normalize values
* @param value Pixel channel value.
* @param min Minimum value for channel
* @param max Maximum value for channel
*/
const normalizeValue = function (value: number, min: number, max: number) {
return ((value - min) * 255) / (max - min);
};
const getBounds = function (histogramChannel: number[]) {
return [
histogramChannel.findIndex((value) => value > 0),
255 -
histogramChannel
.slice()
.reverse()
.findIndex((value) => value > 0),
];
};
export const methods = {
/**
* Normalizes the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.normalize();
* ```
*/
normalize<I extends JimpClass>(image: I) {
const h = histogram(image);
// store bounds (minimum and maximum values)
const bounds = {
r: getBounds(h.r),
g: getBounds(h.g),
b: getBounds(h.b),
};
// apply value transformations
image.scan((_, __, idx) => {
const r = image.bitmap.data[idx + 0]!;
const g = image.bitmap.data[idx + 1]!;
const b = image.bitmap.data[idx + 2]!;
image.bitmap.data[idx + 0] = normalizeValue(
r,
bounds.r[0]!,
bounds.r[1]!,
);
image.bitmap.data[idx + 1] = normalizeValue(
g,
bounds.g[0]!,
bounds.g[1]!,
);
image.bitmap.data[idx + 2] = normalizeValue(
b,
bounds.b[0]!,
bounds.b[1]!,
);
});
return image;
},
/**
* Inverts the colors in the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.invert();
* ```
*/
invert<I extends JimpClass>(image: I) {
image.scan((_, __, idx) => {
image.bitmap.data[idx] = 255 - image.bitmap.data[idx]!;
image.bitmap.data[idx + 1] = 255 - image.bitmap.data[idx + 1]!;
image.bitmap.data[idx + 2] = 255 - image.bitmap.data[idx + 2]!;
});
return image;
},
/**
* Adjusts the brightness of the image
* @param val the amount to adjust the brightness.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.brightness(0.5);
* ```
*/
brightness<I extends JimpClass>(image: I, val: number) {
if (typeof val !== "number") {
throw new Error("val must be numbers");
}
image.scan((_, __, idx) => {
image.bitmap.data[idx]! = limit255(image.bitmap.data[idx]! * val);
image.bitmap.data[idx + 1]! = limit255(image.bitmap.data[idx + 1]! * val);
image.bitmap.data[idx + 2]! = limit255(image.bitmap.data[idx + 2]! * val);
});
return image;
},
/**
* Adjusts the contrast of the image
* @param val the amount to adjust the contrast, a number between -1 and +1
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.contrast(0.75);
* ```
*/
contrast<I extends JimpClass>(image: I, val: number) {
if (typeof val !== "number") {
throw new Error("val must be numbers");
}
if (val < -1 || val > +1) {
throw new Error("val must be a number between -1 and +1");
}
const factor = (val + 1) / (1 - val);
function adjust(value: number) {
value = Math.floor(factor * (value - 127) + 127);
return value < 0 ? 0 : value > 255 ? 255 : value;
}
image.scan((_, __, idx) => {
image.bitmap.data[idx] = adjust(image.bitmap.data[idx]!);
image.bitmap.data[idx + 1] = adjust(image.bitmap.data[idx + 1]!);
image.bitmap.data[idx + 2] = adjust(image.bitmap.data[idx + 2]!);
});
return image;
},
/**
* Apply a posterize effect
* @param n the amount to adjust the contrast, minimum threshold is two
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.posterize(5);
* ```
*/
posterize<I extends JimpClass>(image: I, n: number) {
if (typeof n !== "number") {
throw new Error("n must be numbers");
}
// minimum of 2 levels
if (n < 2) {
n = 2;
}
image.scan((_, __, idx) => {
const r = image.bitmap.data[idx]!;
const g = image.bitmap.data[idx + 1]!;
const b = image.bitmap.data[idx + 2]!;
image.bitmap.data[idx] =
(Math.floor((r / 255) * (n - 1)) / (n - 1)) * 255;
image.bitmap.data[idx + 1] =
(Math.floor((g / 255) * (n - 1)) / (n - 1)) * 255;
image.bitmap.data[idx + 2] =
(Math.floor((b / 255) * (n - 1)) / (n - 1)) * 255;
});
return image;
},
/**
* Removes colour from the image using ITU Rec 709 luminance values
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.greyscale();
* ```
*/
greyscale<I extends JimpClass>(image: I) {
image.scan((_, __, idx) => {
// const grey = parseInt(
// 0.2126 * image.bitmap.data[idx]! +
// 0.7152 * image.bitmap.data[idx + 1]! +
// 0.0722 * image.bitmap.data[idx + 2]!,
// 10
// );
const grey =
0.2126 * image.bitmap.data[idx]! +
0.7152 * image.bitmap.data[idx + 1]! +
0.0722 * image.bitmap.data[idx + 2]!;
image.bitmap.data[idx] = grey;
image.bitmap.data[idx + 1] = grey;
image.bitmap.data[idx + 2] = grey;
});
return image;
},
/**
* Multiplies the opacity of each pixel by a factor between 0 and 1
* @param f A number, the factor by which to multiply the opacity of each pixel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opacity(0.5);
* ```
*/
opacity<I extends JimpClass>(image: I, f: number) {
if (typeof f !== "number") {
throw new Error("f must be a number");
}
if (f < 0 || f > 1) {
throw new Error("f must be a number from 0 to 1");
}
image.scan((_, __, idx) => {
const v = image.bitmap.data[idx + 3]! * f;
image.bitmap.data[idx + 3] = v;
});
return image;
},
/**
* Applies a sepia tone to the image.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.sepia();
* ```
*/
sepia<I extends JimpClass>(image: I) {
image.scan((_, __, idx) => {
let red = image.bitmap.data[idx]!;
let green = image.bitmap.data[idx + 1]!;
let blue = image.bitmap.data[idx + 2]!;
red = red * 0.393 + green * 0.769 + blue * 0.189;
green = red * 0.349 + green * 0.686 + blue * 0.168;
blue = red * 0.272 + green * 0.534 + blue * 0.131;
image.bitmap.data[idx] = red < 255 ? red : 255;
image.bitmap.data[idx + 1] = green < 255 ? green : 255;
image.bitmap.data[idx + 2] = blue < 255 ? blue : 255;
});
return image;
},
/**
* Fades each pixel by a factor between 0 and 1
* @param f A number from 0 to 1. 0 will haven no effect. 1 will turn the image completely transparent.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.fade(0.7);
* ```
*/
fade<I extends JimpClass>(image: I, f: number) {
if (typeof f !== "number") {
throw new Error("f must be a number");
}
if (f < 0 || f > 1) {
throw new Error("f must be a number from 0 to 1");
}
// this method is an alternative to opacity (which may be deprecated)
return this.opacity(image, 1 - f);
},
/**
* Adds each element of the image to its local neighbors, weighted by the kernel
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.convolute([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
* ```
*/
convolution<I extends JimpClass>(image: I, options: ConvolutionOptions) {
const parsed = ConvolutionOptionsSchema.parse(options);
const { kernel, edgeHandling = Edge.EXTEND } =
"kernel" in parsed ? parsed : { kernel: parsed, edgeHandling: undefined };
if (!kernel[0]) {
throw new Error("kernel must be a matrix");
}
const newData = Buffer.from(image.bitmap.data);
const kRows = kernel.length;
const kCols = kernel[0].length;
const rowEnd = Math.floor(kRows / 2);
const colEnd = Math.floor(kCols / 2);
const rowIni = -rowEnd;
const colIni = -colEnd;
let weight;
let rSum;
let gSum;
let bSum;
let ri;
let gi;
let bi;
let xi;
let yi;
let idxi;
image.scan((x, y, idx) => {
bSum = 0;
gSum = 0;
rSum = 0;
for (let row = rowIni; row <= rowEnd; row++) {
for (let col = colIni; col <= colEnd; col++) {
xi = x + col;
yi = y + row;
weight = kernel[row + rowEnd]![col + colEnd]!;
idxi = image.getPixelIndex(xi, yi, edgeHandling);
if (idxi === -1) {
bi = 0;
gi = 0;
ri = 0;
} else {
ri = image.bitmap.data[idxi + 0]!;
gi = image.bitmap.data[idxi + 1]!;
bi = image.bitmap.data[idxi + 2]!;
}
rSum += weight * ri;
gSum += weight * gi;
bSum += weight * bi;
}
}
if (rSum < 0) {
rSum = 0;
}
if (gSum < 0) {
gSum = 0;
}
if (bSum < 0) {
bSum = 0;
}
if (rSum > 255) {
rSum = 255;
}
if (gSum > 255) {
gSum = 255;
}
if (bSum > 255) {
bSum = 255;
}
newData[idx + 0] = rSum;
newData[idx + 1] = gSum;
newData[idx + 2] = bSum;
});
image.bitmap.data = newData;
return image;
},
/**
* Set the alpha channel on every pixel to fully opaque.
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.opaque();
* ```
*/
opaque<I extends JimpClass>(image: I) {
image.scan((_, __, idx) => {
image.bitmap.data[idx + 3] = 255;
});
return image;
},
/**
* Pixelates the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // pixelate the whole image
* image.pixelate(10);
*
* // pixelate a region
* image.pixelate(10, 10, 10, 20, 20);
* ```
*/
pixelate<I extends JimpClass>(image: I, options: PixelateOptions) {
const parsed = PixelateOptionsSchema.parse(options);
const {
size,
x = 0,
y = 0,
w = image.bitmap.width - x,
h = image.bitmap.height - y,
} = typeof parsed === "number"
? ({ size: parsed } as PixelateComplexOptions)
: parsed;
const kernel = [
[1 / 16, 2 / 16, 1 / 16],
[2 / 16, 4 / 16, 2 / 16],
[1 / 16, 2 / 16, 1 / 16],
];
const source = clone(image);
scan(source, x, y, w, h, (xx, yx, idx) => {
xx = size * Math.floor(xx / size);
yx = size * Math.floor(yx / size);
const value = applyKernel(source, kernel, xx, yx);
image.bitmap.data[idx] = value[0]!;
image.bitmap.data[idx + 1] = value[1]!;
image.bitmap.data[idx + 2] = value[2]!;
image.bitmap.data[idx + 3] = value[3]!;
});
return image;
},
/**
* Applies a convolution kernel to the image or a region
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* // apply a convolution kernel to the whole image
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ]);
*
* // apply a convolution kernel to a region
* image.convolution([
* [-1, -1, 0],
* [-1, 1, 1],
* [0, 1, 1],
* ], 10, 10, 10, 20);
* ```
*/
convolute<I extends JimpClass>(image: I, options: ConvoluteOptions) {
const parsed = ConvoluteOptionsSchema.parse(options);
const {
kernel,
x = 0,
y = 0,
w = image.bitmap.width - x,
h = image.bitmap.height - y,
} = "kernel" in parsed
? parsed
: ({ kernel: parsed } as ConvoluteComplexOptions);
const source = clone(image);
scan(source, x, y, w, h, (xx, yx, idx) => {
const value = applyKernel(source, kernel, xx, yx);
image.bitmap.data[idx] = limit255(value[0]!);
image.bitmap.data[idx + 1] = limit255(value[1]!);
image.bitmap.data[idx + 2] = limit255(value[2]!);
image.bitmap.data[idx + 3] = limit255(value[3]!);
});
return image;
},
/**
* Apply multiple color modification rules
* @param actions list of color modification rules, in following format: { apply: '<rule-name>', params: [ <rule-parameters> ] }
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.color([
* { apply: "hue", params: [-90] },
* { apply: "lighten", params: [50] },
* { apply: "xor", params: ["#06D"] },
* ]);
* ```
*/
color<I extends JimpClass>(image: I, actions: ColorAction[]) {
if (!actions || !Array.isArray(actions)) {
throw new Error("actions must be an array");
}
actions.forEach((action) => ColorActionNameSchema.parse(action));
actions = actions.map((action) => {
if (action.apply === "xor" || action.apply === "mix") {
action.params[0] = tinyColor(action.params[0]).toRgb();
}
return action;
});
image.scan((_, __, idx) => {
let clr: RGBColor = {
r: image.bitmap.data[idx]!,
g: image.bitmap.data[idx + 1]!,
b: image.bitmap.data[idx + 2]!,
};
const colorModifier = (i: "r" | "g" | "b", amount: number) =>
limit255(clr[i] + amount);
actions.forEach((action) => {
if (action.apply === "mix") {
clr = mix(clr, action.params[0], action.params[1]);
} else if (action.apply === "tint") {
clr = mix(clr, { r: 255, g: 255, b: 255 }, action.params?.[0]);
} else if (action.apply === "shade") {
clr = mix(clr, { r: 0, g: 0, b: 0 }, action.params?.[0]);
} else if (action.apply === "xor") {
clr = {
r: clr.r! ^ action.params[0].r,
g: clr.g! ^ action.params[0].g,
b: clr.b! ^ action.params[0].b,
};
} else if (action.apply === "red") {
clr.r = colorModifier("r", action.params[0]);
} else if (action.apply === "green") {
clr.g = colorModifier("g", action.params[0]);
} else if (action.apply === "blue") {
clr.b = colorModifier("b", action.params[0]);
} else {
if (action.apply === "hue") {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
action.apply = "spin";
}
const tnyClr = tinyColor(clr);
const fn = tnyClr[action.apply].bind(tnyClr);
if (!fn) {
throw new Error("action " + action.apply + " not supported");
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
clr = (fn as any)(...(action.params || [])).toRgb();
}
});
image.bitmap.data[idx] = clr.r;
image.bitmap.data[idx + 1] = clr.g;
image.bitmap.data[idx + 2] = clr.b;
});
return image;
},
};
+27
View File
@@ -0,0 +1,27 @@
import { expect, test, describe } from "vitest";
import { makeTestImage } from "@jimp/test-utils";
import { methods } from "./index.js";
import { createJimp } from "@jimp/core";
const jimp = createJimp({ plugins: [methods] });
describe("Normalize", () => {
test("change grayscale image", () => {
const image = jimp.fromBitmap(makeTestImage("36▦", "6▦9", "▦9C"));
expect(image.normalize()).toMatchSnapshot();
});
test("change red/blue image", () => {
const image = jimp.fromBitmap({
width: 3,
height: 2,
data: [
0x000000ff, 0x400022ff, 0x40002200, 0x400000ff, 0x000022ff, 0x800055ff,
],
});
expect(image.normalize()).toMatchSnapshot();
});
});
+6
View File
@@ -0,0 +1,6 @@
{
"extends": "@jimp/config-typescript/base.json",
"compilerOptions": {
"outDir": "dist"
}
}
+3
View File
@@ -0,0 +1,3 @@
import config from "@jimp/config-vitest/browser";
export default config;