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-resize@1.5.0 build /Users/andrewlisowski/Documents/jimp/plugins/plugin-resize
> tshy
+5
View File
@@ -0,0 +1,5 @@

> @jimp/plugin-resize@1.1.2 lint /Users/andrewlisowski/Documents/jimp/plugins/plugin-resize
> eslint .
+74
View File
@@ -0,0 +1,74 @@

> @jimp/plugin-resize@1.1.2 test:browser /Users/andrewlisowski/Documents/jimp/plugins/plugin-resize
> vitest --config vitest.config.browser.mjs "--watch=false"
Re-optimizing dependencies because lockfile has changed
 RUN  v2.0.5 /Users/andrewlisowski/Documents/jimp/plugins/plugin-resize
 Browser runner started at http://localhost:5173/
1:39:23 AM [vite] ✨ new dependencies optimized: vite-plugin-node-polyfills/shims/buffer, vite-plugin-node-polyfills/shims/global, vite-plugin-node-polyfills/shims/process, path
1:39:23 AM [vite] ✨ optimized dependencies changed. reloading
[?25l · to default 6x6
· to NEAREST_NEIGHBOR 6x6
· to BILINEAR 6x6
· to BICUBIC 6x6
· to HERMITE 6x6
· to BEZIER 6x6
· mutch contrast 4x4 (6)
· to default 6x6
· to NEAREST_NEIGHBOR 6x6
· to BILINEAR 6x6
· to BICUBIC 6x6
· to HERMITE 6x6
· to BEZIER 6x6
[?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 ✓ to default 6x6
✓ to NEAREST_NEIGHBOR 6x6
✓ to BILINEAR 6x6
✓ to BICUBIC 6x6
✓ to HERMITE 6x6
✓ to BEZIER 6x6
✓ mutch contrast 4x4 (6)
✓ to default 6x6
✓ to NEAREST_NEIGHBOR 6x6
✓ to BILINEAR 6x6
✓ to BICUBIC 6x6
✓ to HERMITE 6x6
✓ to BEZIER 6x6
[?25l ✓ src/index.test.ts (24)
✓ Resize images (24)
✓ max contrast 8x8 (12)
✓ to default 4x4
✓ to NEAREST_NEIGHBOR 4x4
✓ to BILINEAR 4x4
✓ to BICUBIC 4x4
✓ to HERMITE 4x4
✓ to BEZIER 4x4
✓ to default 2x5
✓ to NEAREST_NEIGHBOR 2x5
✓ to BILINEAR 2x5
✓ to BICUBIC 2x5
✓ to HERMITE 2x5
✓ to BEZIER 2x5
✓ max contrast 12x12 with dots (6)
✓ to default 6x6
✓ to NEAREST_NEIGHBOR 6x6
✓ to BILINEAR 6x6
✓ to BICUBIC 6x6
✓ to HERMITE 6x6
✓ to BEZIER 6x6
✓ mutch contrast 4x4 (6)
✓ to default 6x6
✓ to NEAREST_NEIGHBOR 6x6
✓ to BILINEAR 6x6
✓ to BICUBIC 6x6
✓ to HERMITE 6x6
✓ to BEZIER 6x6
 Test Files  1 passed (1)
 Tests  24 passed (24)
 Start at  01:39:12
 Duration  13.87s (transform 0ms, setup 0ms, collect 133ms, tests 9ms, environment 0ms, prepare 1.63s)
[?25h[?25h
+74
View File
@@ -0,0 +1,74 @@

> @jimp/plugin-resize@1.1.2 test /Users/andrewlisowski/Documents/jimp/plugins/plugin-resize
> vitest "--watch=false"
 RUN  v2.0.5 /Users/andrewlisowski/Documents/jimp/plugins/plugin-resize
[?25l · to BEZIER 2x5
· max contrast 12x12 with dots (6)
· to default 6x6
· to NEAREST_NEIGHBOR 6x6
· to BILINEAR 6x6
· to BICUBIC 6x6
· to HERMITE 6x6
· to BEZIER 6x6
· mutch contrast 4x4 (6)
· to default 6x6
· to NEAREST_NEIGHBOR 6x6
· to BILINEAR 6x6
· to BICUBIC 6x6
· to HERMITE 6x6
· to BEZIER 6x6
[?25l ✓ to BEZIER 2x5
✓ max contrast 12x12 with dots (6)
✓ to default 6x6
✓ to NEAREST_NEIGHBOR 6x6
✓ to BILINEAR 6x6
✓ to BICUBIC 6x6
✓ to HERMITE 6x6
✓ to BEZIER 6x6
✓ mutch contrast 4x4 (6)
✓ to default 6x6
✓ to NEAREST_NEIGHBOR 6x6
✓ to BILINEAR 6x6
✓ to BICUBIC 6x6
✓ to HERMITE 6x6
✓ to BEZIER 6x6
[?25l ✓ src/index.test.ts (24)
✓ Resize images (24)
✓ max contrast 8x8 (12)
✓ to default 4x4
✓ to NEAREST_NEIGHBOR 4x4
✓ to BILINEAR 4x4
✓ to BICUBIC 4x4
✓ to HERMITE 4x4
✓ to BEZIER 4x4
✓ to default 2x5
✓ to NEAREST_NEIGHBOR 2x5
✓ to BILINEAR 2x5
✓ to BICUBIC 2x5
✓ to HERMITE 2x5
✓ to BEZIER 2x5
✓ max contrast 12x12 with dots (6)
✓ to default 6x6
✓ to NEAREST_NEIGHBOR 6x6
✓ to BILINEAR 6x6
✓ to BICUBIC 6x6
✓ to HERMITE 6x6
✓ to BEZIER 6x6
✓ mutch contrast 4x4 (6)
✓ to default 6x6
✓ to NEAREST_NEIGHBOR 6x6
✓ to BILINEAR 6x6
✓ to BICUBIC 6x6
✓ to HERMITE 6x6
✓ to BEZIER 6x6
 Test Files  1 passed (1)
 Tests  24 passed (24)
 Start at  01:33:45
 Duration  2.28s (transform 518ms, setup 0ms, collect 842ms, tests 14ms, environment 1ms, prepare 531ms)
[?25h[?25h
+52
View File
@@ -0,0 +1,52 @@
# 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.0 (Sun Sep 01 2024)
#### ⚠️ Pushed to `main`
- upgrade tshy ([@hipstersmoothie](https://github.com/hipstersmoothie))
- 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.
+12
View File
@@ -0,0 +1,12 @@
<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/plugin-resize</h1>
<p>Resize an image.</p>
</div>
Resizes the image to a set width and height using a 2-pass bilinear algorithm.
- [resize](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#resize)
- [scale](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#scale)
- [scaleToFit](http://jimp-dev.github.io/jimp/api/jimp/classes/jimp#scaletofit)
+27
View File
@@ -0,0 +1,27 @@
/**
* What resizing algorithm to use.
*/
export declare enum ResizeStrategy {
/**
* Nearest Neighbor resizing is a method used in image processing that assigns the value of the nearest pixel to the output pixel when resizing an image.
* While fast, it can lead to lower quality outputs with noticeable pixelation, especially at larger scaling factors.
*/
NEAREST_NEIGHBOR = "nearestNeighbor",
/**
* Bilinear resizing is an image scaling method that uses the weighted average of the four nearest pixel values, providing smoother gradients than nearest neighbor resizing.
* It's computationally more intense than nearest neighbor but results in images of higher quality and fewer artifacts.
*/
BILINEAR = "bilinearInterpolation",
/**
* Bicubic resizing is an image interpolation method that uses the values of the nearest 16 pixels in the input image to calculate the output pixel value, providing even more smoothness and sharpness than bilinear resizing.
* Although it's computationally more expensive than bilinear and nearest neighbor, it produces higher quality images, making it ideal for photographic image scaling.
*/
BICUBIC = "bicubicInterpolation",
/**
* Hermite resizing is an image resizing method that uses Hermite interpolation, a mathematical formula, to determine the values of output pixels based on a weighted average of the surrounding pixels.
* Although slower than some simpler techniques like bilinear or nearest neighbor, Hermite resizing can produce higher quality visuals and detailed renderings with less blurring.
*/
HERMITE = "hermiteInterpolation",
BEZIER = "bezierInterpolation"
}
//# sourceMappingURL=constants.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,cAAc;IACxB;;;OAGG;IACH,gBAAgB,oBAAoB;IACpC;;;OAGG;IACH,QAAQ,0BAA0B;IAClC;;;OAGG;IACH,OAAO,yBAAyB;IAChC;;;OAGG;IACH,OAAO,yBAAyB;IAChC,MAAM,wBAAwB;CAC/B"}
+31
View File
@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResizeStrategy = void 0;
/**
* What resizing algorithm to use.
*/
var ResizeStrategy;
(function (ResizeStrategy) {
/**
* Nearest Neighbor resizing is a method used in image processing that assigns the value of the nearest pixel to the output pixel when resizing an image.
* While fast, it can lead to lower quality outputs with noticeable pixelation, especially at larger scaling factors.
*/
ResizeStrategy["NEAREST_NEIGHBOR"] = "nearestNeighbor";
/**
* Bilinear resizing is an image scaling method that uses the weighted average of the four nearest pixel values, providing smoother gradients than nearest neighbor resizing.
* It's computationally more intense than nearest neighbor but results in images of higher quality and fewer artifacts.
*/
ResizeStrategy["BILINEAR"] = "bilinearInterpolation";
/**
* Bicubic resizing is an image interpolation method that uses the values of the nearest 16 pixels in the input image to calculate the output pixel value, providing even more smoothness and sharpness than bilinear resizing.
* Although it's computationally more expensive than bilinear and nearest neighbor, it produces higher quality images, making it ideal for photographic image scaling.
*/
ResizeStrategy["BICUBIC"] = "bicubicInterpolation";
/**
* Hermite resizing is an image resizing method that uses Hermite interpolation, a mathematical formula, to determine the values of output pixels based on a weighted average of the surrounding pixels.
* Although slower than some simpler techniques like bilinear or nearest neighbor, Hermite resizing can produce higher quality visuals and detailed renderings with less blurring.
*/
ResizeStrategy["HERMITE"] = "hermiteInterpolation";
ResizeStrategy["BEZIER"] = "bezierInterpolation";
})(ResizeStrategy || (exports.ResizeStrategy = ResizeStrategy = {}));
//# sourceMappingURL=constants.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,IAAY,cAsBX;AAtBD,WAAY,cAAc;IACxB;;;OAGG;IACH,sDAAoC,CAAA;IACpC;;;OAGG;IACH,oDAAkC,CAAA;IAClC;;;OAGG;IACH,kDAAgC,CAAA;IAChC;;;OAGG;IACH,kDAAgC,CAAA;IAChC,gDAA8B,CAAA;AAChC,CAAC,EAtBW,cAAc,8BAAd,cAAc,QAsBzB"}
+111
View File
@@ -0,0 +1,111 @@
import { JimpClass } from "@jimp/types";
import { ResizeStrategy } from "./constants.js";
import { z } from "zod";
export * from "./constants.js";
declare const ResizeOptionsSchema: z.ZodUnion<[z.ZodObject<{
/** the width to resize the image to */
w: z.ZodNumber;
/** the height to resize the image to */
h: z.ZodOptional<z.ZodNumber>;
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: z.ZodOptional<z.ZodNativeEnum<typeof ResizeStrategy>>;
}, "strip", z.ZodTypeAny, {
w: number;
h?: number | undefined;
mode?: ResizeStrategy | undefined;
}, {
w: number;
h?: number | undefined;
mode?: ResizeStrategy | undefined;
}>, z.ZodObject<{
/** the width to resize the image to */
w: z.ZodOptional<z.ZodNumber>;
/** the height to resize the image to */
h: z.ZodNumber;
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: z.ZodOptional<z.ZodNativeEnum<typeof ResizeStrategy>>;
}, "strip", z.ZodTypeAny, {
h: number;
w?: number | undefined;
mode?: ResizeStrategy | undefined;
}, {
h: number;
w?: number | undefined;
mode?: ResizeStrategy | undefined;
}>]>;
export type ResizeOptions = z.infer<typeof ResizeOptionsSchema>;
declare const ScaleToFitOptionsSchema: z.ZodObject<{
/** the width to resize the image to */
w: z.ZodNumber;
/** the height to resize the image to */
h: z.ZodNumber;
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: z.ZodOptional<z.ZodNativeEnum<typeof ResizeStrategy>>;
}, "strip", z.ZodTypeAny, {
w: number;
h: number;
mode?: ResizeStrategy | undefined;
}, {
w: number;
h: number;
mode?: ResizeStrategy | undefined;
}>;
export type ScaleToFitOptions = z.infer<typeof ScaleToFitOptionsSchema>;
declare const ScaleComplexOptionsSchema: z.ZodObject<{
/** the width to resize the image to */
f: z.ZodNumber;
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: z.ZodOptional<z.ZodNativeEnum<typeof ResizeStrategy>>;
}, "strip", z.ZodTypeAny, {
f: number;
mode?: ResizeStrategy | undefined;
}, {
f: number;
mode?: ResizeStrategy | undefined;
}>;
export type ScaleComplexOptions = z.infer<typeof ScaleComplexOptionsSchema>;
export type ScaleOptions = number | ScaleComplexOptions;
export declare const methods: {
/**
* Resizes the image to a set width and height using a 2-pass bilinear algorithm
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.resize({ w: 150 });
* ```
*/
resize<I extends JimpClass>(image: I, options: ResizeOptions): I;
/**
* Uniformly scales the image by a factor.
* @param f the factor to scale the image by
* @param mode (optional) a scaling method (e.g. Jimp.RESIZE_BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scale(0.5);
* ```
*/
scale<I extends JimpClass>(image: I, options: ScaleOptions): I;
/**
* Scale the image to the largest size that fits inside the rectangle that has the given width and height.
* @param w the width to resize the image to
* @param h the height to resize the image to
* @param mode a scaling method (e.g. ResizeStrategy.BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scaleToFit(100, 100);
* ```
*/
scaleToFit<I extends JimpClass>(image: I, options: ScaleToFitOptions): I;
};
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,cAAc,gBAAgB,CAAC;AAkB/B,QAAA,MAAM,mBAAmB;IAErB,uCAAuC;;IAEvC,wCAAwC;;IAExC,oDAAoD;;;;;;;;;;;IAIpD,uCAAuC;;IAEvC,wCAAwC;;IAExC,oDAAoD;;;;;;;;;;IAGtD,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,QAAA,MAAM,uBAAuB;IAC3B,uCAAuC;;IAEvC,wCAAwC;;IAExC,iDAAiD;;;;;;;;;;EAEjD,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,QAAA,MAAM,yBAAyB;IAC7B,uCAAuC;;IAEvC,iDAAiD;;;;;;;;EAEjD,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC5E,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,mBAAmB,CAAC;AAExD,eAAO,MAAM,OAAO;IAClB;;;;;;;;;;OAUG;WACI,CAAC,SAAS,SAAS,SAAS,CAAC,WAAW,aAAa;IAiD5D;;;;;;;;;;;;OAYG;UACG,CAAC,SAAS,SAAS,SAAS,CAAC,WAAW,YAAY;IAW1D;;;;;;;;;;;;;OAaG;eACQ,CAAC,SAAS,SAAS,SAAS,CAAC,WAAW,iBAAiB;CASrE,CAAC"}
+150
View File
@@ -0,0 +1,150 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.methods = void 0;
const constants_js_1 = require("./constants.js");
const zod_1 = require("zod");
const resize_js_1 = __importDefault(require("./modules/resize.js"));
const resize2_js_1 = require("./modules/resize2.js");
__exportStar(require("./constants.js"), exports);
const ResizeOptionsSchema = zod_1.z.union([
zod_1.z.object({
/** the width to resize the image to */
w: zod_1.z.number().min(0),
/** the height to resize the image to */
h: zod_1.z.number().min(0).optional(),
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: zod_1.z.nativeEnum(constants_js_1.ResizeStrategy).optional(),
}),
zod_1.z.object({
/** the width to resize the image to */
w: zod_1.z.number().min(0).optional(),
/** the height to resize the image to */
h: zod_1.z.number().min(0),
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: zod_1.z.nativeEnum(constants_js_1.ResizeStrategy).optional(),
}),
]);
const ScaleToFitOptionsSchema = zod_1.z.object({
/** the width to resize the image to */
w: zod_1.z.number().min(0),
/** the height to resize the image to */
h: zod_1.z.number().min(0),
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: zod_1.z.nativeEnum(constants_js_1.ResizeStrategy).optional(),
});
const ScaleComplexOptionsSchema = zod_1.z.object({
/** the width to resize the image to */
f: zod_1.z.number().min(0),
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: zod_1.z.nativeEnum(constants_js_1.ResizeStrategy).optional(),
});
exports.methods = {
/**
* Resizes the image to a set width and height using a 2-pass bilinear algorithm
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.resize({ w: 150 });
* ```
*/
resize(image, options) {
const { mode } = ResizeOptionsSchema.parse(options);
let w;
let h;
if (typeof options.w === "number") {
w = options.w;
h = options.h ?? image.bitmap.height * (w / image.bitmap.width);
}
else if (typeof options.h === "number") {
h = options.h;
w = options.w ?? image.bitmap.width * (h / image.bitmap.height);
}
else {
throw new Error("w must be a number");
}
// round inputs
w = Math.round(w) || 1;
h = Math.round(h) || 1;
if (mode && typeof resize2_js_1.operations[mode] === "function") {
const dst = {
data: Buffer.alloc(w * h * 4),
width: w,
height: h,
};
resize2_js_1.operations[mode](image.bitmap, dst);
image.bitmap = dst;
}
else {
const resize = new resize_js_1.default(image.bitmap.width, image.bitmap.height, w, h, true, true, (buffer) => {
image.bitmap.data = Buffer.from(buffer);
image.bitmap.width = w;
image.bitmap.height = h;
});
resize.resize(image.bitmap.data);
}
return image;
},
/**
* Uniformly scales the image by a factor.
* @param f the factor to scale the image by
* @param mode (optional) a scaling method (e.g. Jimp.RESIZE_BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scale(0.5);
* ```
*/
scale(image, options) {
const { f, mode } = typeof options === "number"
? { f: options }
: ScaleComplexOptionsSchema.parse(options);
const w = image.bitmap.width * f;
const h = image.bitmap.height * f;
return this.resize(image, { w, h, mode: mode });
},
/**
* Scale the image to the largest size that fits inside the rectangle that has the given width and height.
* @param w the width to resize the image to
* @param h the height to resize the image to
* @param mode a scaling method (e.g. ResizeStrategy.BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scaleToFit(100, 100);
* ```
*/
scaleToFit(image, options) {
const { h, w, mode } = ScaleToFitOptionsSchema.parse(options);
const f = w / h > image.bitmap.width / image.bitmap.height
? h / image.bitmap.height
: w / image.bitmap.width;
return this.scale(image, { f, mode: mode });
},
};
//# 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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"}
+3
View File
@@ -0,0 +1,3 @@
declare function Resize(widthOriginal: any, heightOriginal: any, targetWidth: any, targetHeight: any, blendAlpha: any, interpolationPass: any, resizeCallback: any): void;
export default Resize;
//# sourceMappingURL=resize.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"resize.d.ts","sourceRoot":"","sources":["../../../src/modules/resize.ts"],"names":[],"mappings":"AAMA,iBAAS,MAAM,CACb,aAAa,KAAA,EACb,cAAc,KAAA,EACd,WAAW,KAAA,EACX,YAAY,KAAA,EACZ,UAAU,KAAA,EACV,iBAAiB,KAAA,EACjB,cAAc,KAAA,QAqBf;AAwgBD,eAAe,MAAM,CAAC"}
+412
View File
@@ -0,0 +1,412 @@
"use strict";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
Object.defineProperty(exports, "__esModule", { value: true });
// JavaScript Image Resizer (c) 2012 - Grant Galitz
// Released to public domain 29 July 2013: https://github.com/grantgalitz/JS-Image-Resizer/issues/4
function Resize(widthOriginal, heightOriginal, targetWidth, targetHeight, blendAlpha, interpolationPass, resizeCallback) {
this.widthOriginal = Math.abs(Math.floor(widthOriginal) || 0);
this.heightOriginal = Math.abs(Math.floor(heightOriginal) || 0);
this.targetWidth = Math.abs(Math.floor(targetWidth) || 0);
this.targetHeight = Math.abs(Math.floor(targetHeight) || 0);
this.colorChannels = blendAlpha ? 4 : 3;
this.interpolationPass = Boolean(interpolationPass);
this.resizeCallback =
typeof resizeCallback === "function" ? resizeCallback : function () { };
this.targetWidthMultipliedByChannels = this.targetWidth * this.colorChannels;
this.originalWidthMultipliedByChannels =
this.widthOriginal * this.colorChannels;
this.originalHeightMultipliedByChannels =
this.heightOriginal * this.colorChannels;
this.widthPassResultSize =
this.targetWidthMultipliedByChannels * this.heightOriginal;
this.finalResultSize =
this.targetWidthMultipliedByChannels * this.targetHeight;
this.initialize();
}
Resize.prototype.initialize = function () {
// Perform some checks:
if (this.widthOriginal > 0 &&
this.heightOriginal > 0 &&
this.targetWidth > 0 &&
this.targetHeight > 0) {
this.configurePasses();
}
else {
console.log(this);
throw new Error("Invalid settings specified for the resizer.");
}
};
Resize.prototype.configurePasses = function () {
if (this.widthOriginal === this.targetWidth) {
// Bypass the width resizer pass:
this.resizeWidth = this.bypassResizer;
}
else {
// Setup the width resizer pass:
this.ratioWeightWidthPass = this.widthOriginal / this.targetWidth;
if (this.ratioWeightWidthPass < 1 && this.interpolationPass) {
this.initializeFirstPassBuffers(true);
this.resizeWidth =
this.colorChannels === 4
? this.resizeWidthInterpolatedRGBA
: this.resizeWidthInterpolatedRGB;
}
else {
this.initializeFirstPassBuffers(false);
this.resizeWidth =
this.colorChannels === 4 ? this.resizeWidthRGBA : this.resizeWidthRGB;
}
}
if (this.heightOriginal === this.targetHeight) {
// Bypass the height resizer pass:
this.resizeHeight = this.bypassResizer;
}
else {
// Setup the height resizer pass:
this.ratioWeightHeightPass = this.heightOriginal / this.targetHeight;
if (this.ratioWeightHeightPass < 1 && this.interpolationPass) {
this.initializeSecondPassBuffers(true);
this.resizeHeight = this.resizeHeightInterpolated;
}
else {
this.initializeSecondPassBuffers(false);
this.resizeHeight =
this.colorChannels === 4 ? this.resizeHeightRGBA : this.resizeHeightRGB;
}
}
};
Resize.prototype._resizeWidthInterpolatedRGBChannels = function (buffer, fourthChannel) {
const channelsNum = fourthChannel ? 4 : 3;
const ratioWeight = this.ratioWeightWidthPass;
const outputBuffer = this.widthBuffer;
let weight = 0;
let finalOffset = 0;
let pixelOffset = 0;
let firstWeight = 0;
let secondWeight = 0;
let targetPosition;
// Handle for only one interpolation input being valid for start calculation:
for (targetPosition = 0; weight < 1 / 3; targetPosition += channelsNum, weight += ratioWeight) {
for (finalOffset = targetPosition, pixelOffset = 0; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels,
finalOffset += this.targetWidthMultipliedByChannels) {
outputBuffer[finalOffset] = buffer[pixelOffset];
outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1];
outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2];
if (fourthChannel)
outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3];
}
}
// Adjust for overshoot of the last pass's counter:
weight -= 1 / 3;
let interpolationWidthSourceReadStop;
for (interpolationWidthSourceReadStop = this.widthOriginal - 1; weight < interpolationWidthSourceReadStop; targetPosition += channelsNum, weight += ratioWeight) {
// Calculate weightings:
secondWeight = weight % 1;
firstWeight = 1 - secondWeight;
// Interpolate:
for (finalOffset = targetPosition,
pixelOffset = Math.floor(weight) * channelsNum; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels,
finalOffset += this.targetWidthMultipliedByChannels) {
outputBuffer[finalOffset + 0] =
buffer[pixelOffset + 0] * firstWeight +
buffer[pixelOffset + channelsNum + 0] * secondWeight;
outputBuffer[finalOffset + 1] =
buffer[pixelOffset + 1] * firstWeight +
buffer[pixelOffset + channelsNum + 1] * secondWeight;
outputBuffer[finalOffset + 2] =
buffer[pixelOffset + 2] * firstWeight +
buffer[pixelOffset + channelsNum + 2] * secondWeight;
if (fourthChannel)
outputBuffer[finalOffset + 3] =
buffer[pixelOffset + 3] * firstWeight +
buffer[pixelOffset + channelsNum + 3] * secondWeight;
}
}
// Handle for only one interpolation input being valid for end calculation:
for (interpolationWidthSourceReadStop =
this.originalWidthMultipliedByChannels - channelsNum; targetPosition < this.targetWidthMultipliedByChannels; targetPosition += channelsNum) {
for (finalOffset = targetPosition,
pixelOffset = interpolationWidthSourceReadStop; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels,
finalOffset += this.targetWidthMultipliedByChannels) {
outputBuffer[finalOffset] = buffer[pixelOffset];
outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1];
outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2];
if (fourthChannel)
outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3];
}
}
return outputBuffer;
};
Resize.prototype._resizeWidthRGBChannels = function (buffer, fourthChannel) {
const channelsNum = fourthChannel ? 4 : 3;
const ratioWeight = this.ratioWeightWidthPass;
const ratioWeightDivisor = 1 / ratioWeight;
const nextLineOffsetOriginalWidth = this.originalWidthMultipliedByChannels - channelsNum + 1;
const nextLineOffsetTargetWidth = this.targetWidthMultipliedByChannels - channelsNum + 1;
const output = this.outputWidthWorkBench;
const outputBuffer = this.widthBuffer;
const trustworthyColorsCount = this.outputWidthWorkBenchOpaquePixelsCount;
let weight = 0;
let amountToNext = 0;
let actualPosition = 0;
let currentPosition = 0;
let line = 0;
let pixelOffset = 0;
let outputOffset = 0;
let multiplier = 1;
let r = 0;
let g = 0;
let b = 0;
let a = 0;
do {
for (line = 0; line < this.originalHeightMultipliedByChannels;) {
output[line++] = 0;
output[line++] = 0;
output[line++] = 0;
if (fourthChannel) {
output[line++] = 0;
trustworthyColorsCount[line / channelsNum - 1] = 0;
}
}
weight = ratioWeight;
do {
amountToNext = 1 + actualPosition - currentPosition;
multiplier = Math.min(weight, amountToNext);
for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) {
r = buffer[pixelOffset];
g = buffer[++pixelOffset];
b = buffer[++pixelOffset];
a = fourthChannel ? buffer[++pixelOffset] : 255;
// Ignore RGB values if pixel is completely transparent
output[line++] += (a ? r : 0) * multiplier;
output[line++] += (a ? g : 0) * multiplier;
output[line++] += (a ? b : 0) * multiplier;
if (fourthChannel) {
output[line++] += a * multiplier;
trustworthyColorsCount[line / channelsNum - 1] += a ? multiplier : 0;
}
}
if (weight >= amountToNext) {
actualPosition += channelsNum;
currentPosition = actualPosition;
weight -= amountToNext;
}
else {
currentPosition += weight;
break;
}
} while (weight > 0 &&
actualPosition < this.originalWidthMultipliedByChannels);
for (line = 0, pixelOffset = outputOffset; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetTargetWidth) {
weight = fourthChannel ? trustworthyColorsCount[line / channelsNum] : 1;
multiplier = fourthChannel
? weight
? 1 / weight
: 0
: ratioWeightDivisor;
outputBuffer[pixelOffset] = output[line++] * multiplier;
outputBuffer[++pixelOffset] = output[line++] * multiplier;
outputBuffer[++pixelOffset] = output[line++] * multiplier;
if (fourthChannel)
outputBuffer[++pixelOffset] = output[line++] * ratioWeightDivisor;
}
outputOffset += channelsNum;
} while (outputOffset < this.targetWidthMultipliedByChannels);
return outputBuffer;
};
Resize.prototype._resizeHeightRGBChannels = function (buffer, fourthChannel) {
const ratioWeight = this.ratioWeightHeightPass;
const ratioWeightDivisor = 1 / ratioWeight;
const output = this.outputHeightWorkBench;
const outputBuffer = this.heightBuffer;
const trustworthyColorsCount = this.outputHeightWorkBenchOpaquePixelsCount;
let weight = 0;
let amountToNext = 0;
let actualPosition = 0;
let currentPosition = 0;
let pixelOffset = 0;
let outputOffset = 0;
let caret = 0;
let multiplier = 1;
let r = 0;
let g = 0;
let b = 0;
let a = 0;
do {
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) {
output[pixelOffset++] = 0;
output[pixelOffset++] = 0;
output[pixelOffset++] = 0;
if (fourthChannel) {
output[pixelOffset++] = 0;
trustworthyColorsCount[pixelOffset / 4 - 1] = 0;
}
}
weight = ratioWeight;
do {
amountToNext = 1 + actualPosition - currentPosition;
multiplier = Math.min(weight, amountToNext);
caret = actualPosition;
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) {
r = buffer[caret++];
g = buffer[caret++];
b = buffer[caret++];
a = fourthChannel ? buffer[caret++] : 255;
// Ignore RGB values if pixel is completely transparent
output[pixelOffset++] += (a ? r : 0) * multiplier;
output[pixelOffset++] += (a ? g : 0) * multiplier;
output[pixelOffset++] += (a ? b : 0) * multiplier;
if (fourthChannel) {
output[pixelOffset++] += a * multiplier;
trustworthyColorsCount[pixelOffset / 4 - 1] += a ? multiplier : 0;
}
}
if (weight >= amountToNext) {
actualPosition = caret;
currentPosition = actualPosition;
weight -= amountToNext;
}
else {
currentPosition += weight;
break;
}
} while (weight > 0 && actualPosition < this.widthPassResultSize);
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) {
weight = fourthChannel ? trustworthyColorsCount[pixelOffset / 4] : 1;
multiplier = fourthChannel
? weight
? 1 / weight
: 0
: ratioWeightDivisor;
outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * multiplier);
outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * multiplier);
outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * multiplier);
if (fourthChannel) {
outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor);
}
}
} while (outputOffset < this.finalResultSize);
return outputBuffer;
};
Resize.prototype.resizeWidthInterpolatedRGB = function (buffer) {
return this._resizeWidthInterpolatedRGBChannels(buffer, false);
};
Resize.prototype.resizeWidthInterpolatedRGBA = function (buffer) {
return this._resizeWidthInterpolatedRGBChannels(buffer, true);
};
Resize.prototype.resizeWidthRGB = function (buffer) {
return this._resizeWidthRGBChannels(buffer, false);
};
Resize.prototype.resizeWidthRGBA = function (buffer) {
return this._resizeWidthRGBChannels(buffer, true);
};
Resize.prototype.resizeHeightInterpolated = function (buffer) {
const ratioWeight = this.ratioWeightHeightPass;
const outputBuffer = this.heightBuffer;
let weight = 0;
let finalOffset = 0;
let pixelOffset = 0;
let pixelOffsetAccumulated = 0;
let pixelOffsetAccumulated2 = 0;
let firstWeight = 0;
let secondWeight = 0;
let interpolationHeightSourceReadStop;
// Handle for only one interpolation input being valid for start calculation:
for (; weight < 1 / 3; weight += ratioWeight) {
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) {
outputBuffer[finalOffset++] = Math.round(buffer[pixelOffset++]);
}
}
// Adjust for overshoot of the last pass's counter:
weight -= 1 / 3;
for (interpolationHeightSourceReadStop = this.heightOriginal - 1; weight < interpolationHeightSourceReadStop; weight += ratioWeight) {
// Calculate weightings:
secondWeight = weight % 1;
firstWeight = 1 - secondWeight;
// Interpolate:
pixelOffsetAccumulated =
Math.floor(weight) * this.targetWidthMultipliedByChannels;
pixelOffsetAccumulated2 =
pixelOffsetAccumulated + this.targetWidthMultipliedByChannels;
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels; ++pixelOffset) {
outputBuffer[finalOffset++] = Math.round(buffer[pixelOffsetAccumulated++] * firstWeight +
buffer[pixelOffsetAccumulated2++] * secondWeight);
}
}
// Handle for only one interpolation input being valid for end calculation:
while (finalOffset < this.finalResultSize) {
for (pixelOffset = 0,
pixelOffsetAccumulated =
interpolationHeightSourceReadStop *
this.targetWidthMultipliedByChannels; pixelOffset < this.targetWidthMultipliedByChannels; ++pixelOffset) {
outputBuffer[finalOffset++] = Math.round(buffer[pixelOffsetAccumulated++]);
}
}
return outputBuffer;
};
Resize.prototype.resizeHeightRGB = function (buffer) {
return this._resizeHeightRGBChannels(buffer, false);
};
Resize.prototype.resizeHeightRGBA = function (buffer) {
return this._resizeHeightRGBChannels(buffer, true);
};
Resize.prototype.resize = function (buffer) {
this.resizeCallback(this.resizeHeight(this.resizeWidth(buffer)));
};
Resize.prototype.bypassResizer = function (buffer) {
// Just return the buffer passed:
return buffer;
};
Resize.prototype.initializeFirstPassBuffers = function (BILINEARAlgo) {
// Initialize the internal width pass buffers:
this.widthBuffer = this.generateFloatBuffer(this.widthPassResultSize);
if (!BILINEARAlgo) {
this.outputWidthWorkBench = this.generateFloatBuffer(this.originalHeightMultipliedByChannels);
if (this.colorChannels > 3) {
this.outputWidthWorkBenchOpaquePixelsCount = this.generateFloat64Buffer(this.heightOriginal);
}
}
};
Resize.prototype.initializeSecondPassBuffers = function (BILINEARAlgo) {
// Initialize the internal height pass buffers:
this.heightBuffer = this.generateUint8Buffer(this.finalResultSize);
if (!BILINEARAlgo) {
this.outputHeightWorkBench = this.generateFloatBuffer(this.targetWidthMultipliedByChannels);
if (this.colorChannels > 3) {
this.outputHeightWorkBenchOpaquePixelsCount = this.generateFloat64Buffer(this.targetWidth);
}
}
};
Resize.prototype.generateFloatBuffer = function (bufferLength) {
// Generate a float32 typed array buffer:
try {
return new Float32Array(bufferLength);
}
catch (error) {
console.error(error);
return [];
}
};
Resize.prototype.generateFloat64Buffer = function (bufferLength) {
// Generate a float64 typed array buffer:
try {
return new Float64Array(bufferLength);
}
catch (error) {
console.error(error);
return [];
}
};
Resize.prototype.generateUint8Buffer = function (bufferLength) {
// Generate a uint8 typed array buffer:
try {
return new Uint8Array(bufferLength);
}
catch (error) {
console.error(error);
return [];
}
};
exports.default = Resize;
//# sourceMappingURL=resize.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"resize.js","sourceRoot":"","sources":["../../../src/modules/resize.ts"],"names":[],"mappings":"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 truncated
+30
View File
@@ -0,0 +1,30 @@
/**
* Copyright (c) 2015 Guyon Roche
*
* 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:</p>
*
* 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.
*/
export declare const operations: {
nearestNeighbor(src: any, dst: any): void;
bilinearInterpolation(src: any, dst: any): void;
_interpolate2D(src: any, dst: any, options?: any, interpolate?: any): void;
bicubicInterpolation(src: any, dst: any, options?: any): void;
hermiteInterpolation(src: any, dst: any, options?: any): void;
bezierInterpolation(src: any, dst: any, options?: any): void;
};
//# sourceMappingURL=resize2.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"resize2.d.ts","sourceRoot":"","sources":["../../../src/modules/resize2.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,eAAO,MAAM,UAAU;yBACA,GAAG,OAAO,GAAG;+BA0BP,GAAG,OAAO,GAAG;wBAuEpB,GAAG,OAAO,GAAG,YAAY,GAAG,gBAAgB,GAAG;8BAmIzC,GAAG,OAAO,GAAG,YAAY,GAAG;8BAqB5B,GAAG,OAAO,GAAG,YAAY,GAAG;6BAqB7B,GAAG,OAAO,GAAG,YAAY,GAAG;CAgCtD,CAAC"}
+251
View File
@@ -0,0 +1,251 @@
"use strict";
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* Copyright (c) 2015 Guyon Roche
*
* 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:</p>
*
* 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.operations = void 0;
exports.operations = {
nearestNeighbor(src, dst) {
const wSrc = src.width;
const hSrc = src.height;
const wDst = dst.width;
const hDst = dst.height;
const bufSrc = src.data;
const bufDst = dst.data;
for (let i = 0; i < hDst; i++) {
for (let j = 0; j < wDst; j++) {
let posDst = (i * wDst + j) * 4;
const iSrc = Math.floor((i * hSrc) / hDst);
const jSrc = Math.floor((j * wSrc) / wDst);
let posSrc = (iSrc * wSrc + jSrc) * 4;
bufDst[posDst++] = bufSrc[posSrc++];
bufDst[posDst++] = bufSrc[posSrc++];
bufDst[posDst++] = bufSrc[posSrc++];
bufDst[posDst++] = bufSrc[posSrc++];
}
}
},
bilinearInterpolation(src, dst) {
const wSrc = src.width;
const hSrc = src.height;
const wDst = dst.width;
const hDst = dst.height;
const bufSrc = src.data;
const bufDst = dst.data;
const interpolate = function (k, kMin, vMin, kMax, vMax) {
// special case - k is integer
if (kMin === kMax) {
return vMin;
}
return Math.round((k - kMin) * vMax + (kMax - k) * vMin);
};
const assign = function (pos, offset, x, xMin, xMax, y, yMin, yMax) {
let posMin = (yMin * wSrc + xMin) * 4 + offset;
let posMax = (yMin * wSrc + xMax) * 4 + offset;
const vMin = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]);
// special case, y is integer
if (yMax === yMin) {
bufDst[pos + offset] = vMin;
}
else {
posMin = (yMax * wSrc + xMin) * 4 + offset;
posMax = (yMax * wSrc + xMax) * 4 + offset;
const vMax = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]);
bufDst[pos + offset] = interpolate(y, yMin, vMin, yMax, vMax);
}
};
for (let i = 0; i < hDst; i++) {
for (let j = 0; j < wDst; j++) {
const posDst = (i * wDst + j) * 4;
// x & y in src coordinates
const x = (j * wSrc) / wDst;
const xMin = Math.floor(x);
const xMax = Math.min(Math.ceil(x), wSrc - 1);
const y = (i * hSrc) / hDst;
const yMin = Math.floor(y);
const yMax = Math.min(Math.ceil(y), hSrc - 1);
assign(posDst, 0, x, xMin, xMax, y, yMin, yMax);
assign(posDst, 1, x, xMin, xMax, y, yMin, yMax);
assign(posDst, 2, x, xMin, xMax, y, yMin, yMax);
assign(posDst, 3, x, xMin, xMax, y, yMin, yMax);
}
}
},
_interpolate2D(src, dst, options, interpolate) {
const bufSrc = src.data;
const bufDst = dst.data;
const wSrc = src.width;
const hSrc = src.height;
const wDst = dst.width;
const hDst = dst.height;
// when dst smaller than src/2, interpolate first to a multiple between 0.5 and 1.0 src, then sum squares
const wM = Math.max(1, Math.floor(wSrc / wDst));
const wDst2 = wDst * wM;
const hM = Math.max(1, Math.floor(hSrc / hDst));
const hDst2 = hDst * hM;
// ===========================================================
// Pass 1 - interpolate rows
// buf1 has width of dst2 and height of src
const buf1 = Buffer.alloc(wDst2 * hSrc * 4);
for (let i = 0; i < hSrc; i++) {
for (let j = 0; j < wDst2; j++) {
// i in src coords, j in dst coords
// calculate x in src coords
// this interpolation requires 4 sample points and the two inner ones must be real
// the outer points can be fudged for the edges.
// therefore (wSrc-1)/wDst2
const x = (j * (wSrc - 1)) / wDst2;
const xPos = Math.floor(x);
const t = x - xPos;
const srcPos = (i * wSrc + xPos) * 4;
const buf1Pos = (i * wDst2 + j) * 4;
for (let k = 0; k < 4; k++) {
const kPos = srcPos + k;
const x0 = xPos > 0 ? bufSrc[kPos - 4] : 2 * bufSrc[kPos] - bufSrc[kPos + 4];
const x1 = bufSrc[kPos];
const x2 = bufSrc[kPos + 4];
const x3 = xPos < wSrc - 2
? bufSrc[kPos + 8]
: 2 * bufSrc[kPos + 4] - bufSrc[kPos];
buf1[buf1Pos + k] = interpolate(x0, x1, x2, x3, t);
}
}
}
// this._writeFile(wDst2, hSrc, buf1, "out/buf1.jpg");
// ===========================================================
// Pass 2 - interpolate columns
// buf2 has width and height of dst2
const buf2 = Buffer.alloc(wDst2 * hDst2 * 4);
for (let i = 0; i < hDst2; i++) {
for (let j = 0; j < wDst2; j++) {
// i&j in dst2 coords
// calculate y in buf1 coords
// this interpolation requires 4 sample points and the two inner ones must be real
// the outer points can be fudged for the edges.
// therefore (hSrc-1)/hDst2
const y = (i * (hSrc - 1)) / hDst2;
const yPos = Math.floor(y);
const t = y - yPos;
const buf1Pos = (yPos * wDst2 + j) * 4;
const buf2Pos = (i * wDst2 + j) * 4;
for (let k = 0; k < 4; k++) {
const kPos = buf1Pos + k;
const y0 = yPos > 0
? buf1[kPos - wDst2 * 4]
: 2 * buf1[kPos] - buf1[kPos + wDst2 * 4];
const y1 = buf1[kPos];
const y2 = buf1[kPos + wDst2 * 4];
const y3 = yPos < hSrc - 2
? buf1[kPos + wDst2 * 8]
: 2 * buf1[kPos + wDst2 * 4] - buf1[kPos];
buf2[buf2Pos + k] = interpolate(y0, y1, y2, y3, t);
}
}
}
// this._writeFile(wDst2, hDst2, buf2, "out/buf2.jpg");
// ===========================================================
// Pass 3 - scale to dst
const m = wM * hM;
if (m > 1) {
for (let i = 0; i < hDst; i++) {
for (let j = 0; j < wDst; j++) {
// i&j in dst bounded coords
let r = 0;
let g = 0;
let b = 0;
let a = 0;
let realColors = 0;
for (let y = 0; y < hM; y++) {
const yPos = i * hM + y;
for (let x = 0; x < wM; x++) {
const xPos = j * wM + x;
const xyPos = (yPos * wDst2 + xPos) * 4;
const pixelAlpha = buf2[xyPos + 3];
if (pixelAlpha) {
r += buf2[xyPos];
g += buf2[xyPos + 1];
b += buf2[xyPos + 2];
realColors++;
}
a += pixelAlpha;
}
}
const pos = (i * wDst + j) * 4;
bufDst[pos] = realColors ? Math.round(r / realColors) : 0;
bufDst[pos + 1] = realColors ? Math.round(g / realColors) : 0;
bufDst[pos + 2] = realColors ? Math.round(b / realColors) : 0;
bufDst[pos + 3] = Math.round(a / m);
}
}
}
else {
// replace dst buffer with buf2
dst.data = buf2;
}
},
bicubicInterpolation(src, dst, options) {
const interpolateCubic = function (x0, x1, x2, x3, t) {
const a0 = x3 - x2 - x0 + x1;
const a1 = x0 - x1 - a0;
const a2 = x2 - x0;
const a3 = x1;
return Math.max(0, Math.min(255, a0 * (t * t * t) + a1 * (t * t) + a2 * t + a3));
};
return this._interpolate2D(src, dst, options, interpolateCubic);
},
hermiteInterpolation(src, dst, options) {
const interpolateHermite = function (x0, x1, x2, x3, t) {
const c0 = x1;
const c1 = 0.5 * (x2 - x0);
const c2 = x0 - 2.5 * x1 + 2 * x2 - 0.5 * x3;
const c3 = 0.5 * (x3 - x0) + 1.5 * (x1 - x2);
return Math.max(0, Math.min(255, Math.round(((c3 * t + c2) * t + c1) * t + c0)));
};
return this._interpolate2D(src, dst, options, interpolateHermite);
},
bezierInterpolation(src, dst, options) {
// between 2 points y(n), y(n+1), use next points out, y(n-1), y(n+2)
// to predict control points (a & b) to be placed at n+0.5
// ya(n) = y(n) + (y(n+1)-y(n-1))/4
// yb(n) = y(n+1) - (y(n+2)-y(n))/4
// then use std bezier to interpolate [n,n+1)
// y(n+t) = y(n)*(1-t)^3 + 3 * ya(n)*(1-t)^2*t + 3 * yb(n)*(1-t)*t^2 + y(n+1)*t^3
// note the 3* factor for the two control points
// for edge cases, can choose:
// y(-1) = y(0) - 2*(y(1)-y(0))
// y(w) = y(w-1) + 2*(y(w-1)-y(w-2))
// but can go with y(-1) = y(0) and y(w) = y(w-1)
const interpolateBezier = function (x0, x1, x2, x3, t) {
// x1, x2 are the knots, use x0 and x3 to calculate control points
const cp1 = x1 + (x2 - x0) / 4;
const cp2 = x2 - (x3 - x1) / 4;
const nt = 1 - t;
const c0 = x1 * nt * nt * nt;
const c1 = 3 * cp1 * nt * nt * t;
const c2 = 3 * cp2 * nt * t * t;
const c3 = x2 * t * t * t;
return Math.max(0, Math.min(255, Math.round(c0 + c1 + c2 + c3)));
};
return this._interpolate2D(src, dst, options, interpolateBezier);
},
};
//# sourceMappingURL=resize2.js.map
@@ -0,0 +1 @@
{"version":3,"file":"resize2.js","sourceRoot":"","sources":["../../../src/modules/resize2.ts"],"names":[],"mappings":"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 truncated
+3
View File
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
+27
View File
@@ -0,0 +1,27 @@
/**
* What resizing algorithm to use.
*/
export declare enum ResizeStrategy {
/**
* Nearest Neighbor resizing is a method used in image processing that assigns the value of the nearest pixel to the output pixel when resizing an image.
* While fast, it can lead to lower quality outputs with noticeable pixelation, especially at larger scaling factors.
*/
NEAREST_NEIGHBOR = "nearestNeighbor",
/**
* Bilinear resizing is an image scaling method that uses the weighted average of the four nearest pixel values, providing smoother gradients than nearest neighbor resizing.
* It's computationally more intense than nearest neighbor but results in images of higher quality and fewer artifacts.
*/
BILINEAR = "bilinearInterpolation",
/**
* Bicubic resizing is an image interpolation method that uses the values of the nearest 16 pixels in the input image to calculate the output pixel value, providing even more smoothness and sharpness than bilinear resizing.
* Although it's computationally more expensive than bilinear and nearest neighbor, it produces higher quality images, making it ideal for photographic image scaling.
*/
BICUBIC = "bicubicInterpolation",
/**
* Hermite resizing is an image resizing method that uses Hermite interpolation, a mathematical formula, to determine the values of output pixels based on a weighted average of the surrounding pixels.
* Although slower than some simpler techniques like bilinear or nearest neighbor, Hermite resizing can produce higher quality visuals and detailed renderings with less blurring.
*/
HERMITE = "hermiteInterpolation",
BEZIER = "bezierInterpolation"
}
//# sourceMappingURL=constants.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,cAAc;IACxB;;;OAGG;IACH,gBAAgB,oBAAoB;IACpC;;;OAGG;IACH,QAAQ,0BAA0B;IAClC;;;OAGG;IACH,OAAO,yBAAyB;IAChC;;;OAGG;IACH,OAAO,yBAAyB;IAChC,MAAM,wBAAwB;CAC/B"}
+28
View File
@@ -0,0 +1,28 @@
/**
* What resizing algorithm to use.
*/
export var ResizeStrategy;
(function (ResizeStrategy) {
/**
* Nearest Neighbor resizing is a method used in image processing that assigns the value of the nearest pixel to the output pixel when resizing an image.
* While fast, it can lead to lower quality outputs with noticeable pixelation, especially at larger scaling factors.
*/
ResizeStrategy["NEAREST_NEIGHBOR"] = "nearestNeighbor";
/**
* Bilinear resizing is an image scaling method that uses the weighted average of the four nearest pixel values, providing smoother gradients than nearest neighbor resizing.
* It's computationally more intense than nearest neighbor but results in images of higher quality and fewer artifacts.
*/
ResizeStrategy["BILINEAR"] = "bilinearInterpolation";
/**
* Bicubic resizing is an image interpolation method that uses the values of the nearest 16 pixels in the input image to calculate the output pixel value, providing even more smoothness and sharpness than bilinear resizing.
* Although it's computationally more expensive than bilinear and nearest neighbor, it produces higher quality images, making it ideal for photographic image scaling.
*/
ResizeStrategy["BICUBIC"] = "bicubicInterpolation";
/**
* Hermite resizing is an image resizing method that uses Hermite interpolation, a mathematical formula, to determine the values of output pixels based on a weighted average of the surrounding pixels.
* Although slower than some simpler techniques like bilinear or nearest neighbor, Hermite resizing can produce higher quality visuals and detailed renderings with less blurring.
*/
ResizeStrategy["HERMITE"] = "hermiteInterpolation";
ResizeStrategy["BEZIER"] = "bezierInterpolation";
})(ResizeStrategy || (ResizeStrategy = {}));
//# sourceMappingURL=constants.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAN,IAAY,cAsBX;AAtBD,WAAY,cAAc;IACxB;;;OAGG;IACH,sDAAoC,CAAA;IACpC;;;OAGG;IACH,oDAAkC,CAAA;IAClC;;;OAGG;IACH,kDAAgC,CAAA;IAChC;;;OAGG;IACH,kDAAgC,CAAA;IAChC,gDAA8B,CAAA;AAChC,CAAC,EAtBW,cAAc,KAAd,cAAc,QAsBzB"}
+111
View File
@@ -0,0 +1,111 @@
import { JimpClass } from "@jimp/types";
import { ResizeStrategy } from "./constants.js";
import { z } from "zod";
export * from "./constants.js";
declare const ResizeOptionsSchema: z.ZodUnion<[z.ZodObject<{
/** the width to resize the image to */
w: z.ZodNumber;
/** the height to resize the image to */
h: z.ZodOptional<z.ZodNumber>;
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: z.ZodOptional<z.ZodNativeEnum<typeof ResizeStrategy>>;
}, "strip", z.ZodTypeAny, {
w: number;
h?: number | undefined;
mode?: ResizeStrategy | undefined;
}, {
w: number;
h?: number | undefined;
mode?: ResizeStrategy | undefined;
}>, z.ZodObject<{
/** the width to resize the image to */
w: z.ZodOptional<z.ZodNumber>;
/** the height to resize the image to */
h: z.ZodNumber;
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: z.ZodOptional<z.ZodNativeEnum<typeof ResizeStrategy>>;
}, "strip", z.ZodTypeAny, {
h: number;
w?: number | undefined;
mode?: ResizeStrategy | undefined;
}, {
h: number;
w?: number | undefined;
mode?: ResizeStrategy | undefined;
}>]>;
export type ResizeOptions = z.infer<typeof ResizeOptionsSchema>;
declare const ScaleToFitOptionsSchema: z.ZodObject<{
/** the width to resize the image to */
w: z.ZodNumber;
/** the height to resize the image to */
h: z.ZodNumber;
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: z.ZodOptional<z.ZodNativeEnum<typeof ResizeStrategy>>;
}, "strip", z.ZodTypeAny, {
w: number;
h: number;
mode?: ResizeStrategy | undefined;
}, {
w: number;
h: number;
mode?: ResizeStrategy | undefined;
}>;
export type ScaleToFitOptions = z.infer<typeof ScaleToFitOptionsSchema>;
declare const ScaleComplexOptionsSchema: z.ZodObject<{
/** the width to resize the image to */
f: z.ZodNumber;
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: z.ZodOptional<z.ZodNativeEnum<typeof ResizeStrategy>>;
}, "strip", z.ZodTypeAny, {
f: number;
mode?: ResizeStrategy | undefined;
}, {
f: number;
mode?: ResizeStrategy | undefined;
}>;
export type ScaleComplexOptions = z.infer<typeof ScaleComplexOptionsSchema>;
export type ScaleOptions = number | ScaleComplexOptions;
export declare const methods: {
/**
* Resizes the image to a set width and height using a 2-pass bilinear algorithm
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.resize({ w: 150 });
* ```
*/
resize<I extends JimpClass>(image: I, options: ResizeOptions): I;
/**
* Uniformly scales the image by a factor.
* @param f the factor to scale the image by
* @param mode (optional) a scaling method (e.g. Jimp.RESIZE_BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scale(0.5);
* ```
*/
scale<I extends JimpClass>(image: I, options: ScaleOptions): I;
/**
* Scale the image to the largest size that fits inside the rectangle that has the given width and height.
* @param w the width to resize the image to
* @param h the height to resize the image to
* @param mode a scaling method (e.g. ResizeStrategy.BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scaleToFit(100, 100);
* ```
*/
scaleToFit<I extends JimpClass>(image: I, options: ScaleToFitOptions): I;
};
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,cAAc,gBAAgB,CAAC;AAkB/B,QAAA,MAAM,mBAAmB;IAErB,uCAAuC;;IAEvC,wCAAwC;;IAExC,oDAAoD;;;;;;;;;;;IAIpD,uCAAuC;;IAEvC,wCAAwC;;IAExC,oDAAoD;;;;;;;;;;IAGtD,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,QAAA,MAAM,uBAAuB;IAC3B,uCAAuC;;IAEvC,wCAAwC;;IAExC,iDAAiD;;;;;;;;;;EAEjD,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,QAAA,MAAM,yBAAyB;IAC7B,uCAAuC;;IAEvC,iDAAiD;;;;;;;;EAEjD,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC5E,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,mBAAmB,CAAC;AAExD,eAAO,MAAM,OAAO;IAClB;;;;;;;;;;OAUG;WACI,CAAC,SAAS,SAAS,SAAS,CAAC,WAAW,aAAa;IAiD5D;;;;;;;;;;;;OAYG;UACG,CAAC,SAAS,SAAS,SAAS,CAAC,WAAW,YAAY;IAW1D;;;;;;;;;;;;;OAaG;eACQ,CAAC,SAAS,SAAS,SAAS,CAAC,WAAW,iBAAiB;CASrE,CAAC"}
+130
View File
@@ -0,0 +1,130 @@
import { ResizeStrategy } from "./constants.js";
import { z } from "zod";
import Resize from "./modules/resize.js";
import { operations as Resize2 } from "./modules/resize2.js";
export * from "./constants.js";
const ResizeOptionsSchema = z.union([
z.object({
/** the width to resize the image to */
w: z.number().min(0),
/** the height to resize the image to */
h: z.number().min(0).optional(),
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: z.nativeEnum(ResizeStrategy).optional(),
}),
z.object({
/** the width to resize the image to */
w: z.number().min(0).optional(),
/** the height to resize the image to */
h: z.number().min(0),
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: z.nativeEnum(ResizeStrategy).optional(),
}),
]);
const ScaleToFitOptionsSchema = z.object({
/** the width to resize the image to */
w: z.number().min(0),
/** the height to resize the image to */
h: z.number().min(0),
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: z.nativeEnum(ResizeStrategy).optional(),
});
const ScaleComplexOptionsSchema = z.object({
/** the width to resize the image to */
f: z.number().min(0),
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: z.nativeEnum(ResizeStrategy).optional(),
});
export const methods = {
/**
* Resizes the image to a set width and height using a 2-pass bilinear algorithm
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.resize({ w: 150 });
* ```
*/
resize(image, options) {
const { mode } = ResizeOptionsSchema.parse(options);
let w;
let h;
if (typeof options.w === "number") {
w = options.w;
h = options.h ?? image.bitmap.height * (w / image.bitmap.width);
}
else if (typeof options.h === "number") {
h = options.h;
w = options.w ?? image.bitmap.width * (h / image.bitmap.height);
}
else {
throw new Error("w must be a number");
}
// round inputs
w = Math.round(w) || 1;
h = Math.round(h) || 1;
if (mode && typeof Resize2[mode] === "function") {
const dst = {
data: Buffer.alloc(w * h * 4),
width: w,
height: h,
};
Resize2[mode](image.bitmap, dst);
image.bitmap = dst;
}
else {
const resize = new Resize(image.bitmap.width, image.bitmap.height, w, h, true, true, (buffer) => {
image.bitmap.data = Buffer.from(buffer);
image.bitmap.width = w;
image.bitmap.height = h;
});
resize.resize(image.bitmap.data);
}
return image;
},
/**
* Uniformly scales the image by a factor.
* @param f the factor to scale the image by
* @param mode (optional) a scaling method (e.g. Jimp.RESIZE_BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scale(0.5);
* ```
*/
scale(image, options) {
const { f, mode } = typeof options === "number"
? { f: options }
: ScaleComplexOptionsSchema.parse(options);
const w = image.bitmap.width * f;
const h = image.bitmap.height * f;
return this.resize(image, { w, h, mode: mode });
},
/**
* Scale the image to the largest size that fits inside the rectangle that has the given width and height.
* @param w the width to resize the image to
* @param h the height to resize the image to
* @param mode a scaling method (e.g. ResizeStrategy.BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scaleToFit(100, 100);
* ```
*/
scaleToFit(image, options) {
const { h, w, mode } = ScaleToFitOptionsSchema.parse(options);
const f = w / h > image.bitmap.width / image.bitmap.height
? h / image.bitmap.height
: w / image.bitmap.width;
return this.scale(image, { f, mode: mode });
},
};
//# 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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"}
+3
View File
@@ -0,0 +1,3 @@
declare function Resize(widthOriginal: any, heightOriginal: any, targetWidth: any, targetHeight: any, blendAlpha: any, interpolationPass: any, resizeCallback: any): void;
export default Resize;
//# sourceMappingURL=resize.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"resize.d.ts","sourceRoot":"","sources":["../../../src/modules/resize.ts"],"names":[],"mappings":"AAMA,iBAAS,MAAM,CACb,aAAa,KAAA,EACb,cAAc,KAAA,EACd,WAAW,KAAA,EACX,YAAY,KAAA,EACZ,UAAU,KAAA,EACV,iBAAiB,KAAA,EACjB,cAAc,KAAA,QAqBf;AAwgBD,eAAe,MAAM,CAAC"}
+410
View File
@@ -0,0 +1,410 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
// JavaScript Image Resizer (c) 2012 - Grant Galitz
// Released to public domain 29 July 2013: https://github.com/grantgalitz/JS-Image-Resizer/issues/4
function Resize(widthOriginal, heightOriginal, targetWidth, targetHeight, blendAlpha, interpolationPass, resizeCallback) {
this.widthOriginal = Math.abs(Math.floor(widthOriginal) || 0);
this.heightOriginal = Math.abs(Math.floor(heightOriginal) || 0);
this.targetWidth = Math.abs(Math.floor(targetWidth) || 0);
this.targetHeight = Math.abs(Math.floor(targetHeight) || 0);
this.colorChannels = blendAlpha ? 4 : 3;
this.interpolationPass = Boolean(interpolationPass);
this.resizeCallback =
typeof resizeCallback === "function" ? resizeCallback : function () { };
this.targetWidthMultipliedByChannels = this.targetWidth * this.colorChannels;
this.originalWidthMultipliedByChannels =
this.widthOriginal * this.colorChannels;
this.originalHeightMultipliedByChannels =
this.heightOriginal * this.colorChannels;
this.widthPassResultSize =
this.targetWidthMultipliedByChannels * this.heightOriginal;
this.finalResultSize =
this.targetWidthMultipliedByChannels * this.targetHeight;
this.initialize();
}
Resize.prototype.initialize = function () {
// Perform some checks:
if (this.widthOriginal > 0 &&
this.heightOriginal > 0 &&
this.targetWidth > 0 &&
this.targetHeight > 0) {
this.configurePasses();
}
else {
console.log(this);
throw new Error("Invalid settings specified for the resizer.");
}
};
Resize.prototype.configurePasses = function () {
if (this.widthOriginal === this.targetWidth) {
// Bypass the width resizer pass:
this.resizeWidth = this.bypassResizer;
}
else {
// Setup the width resizer pass:
this.ratioWeightWidthPass = this.widthOriginal / this.targetWidth;
if (this.ratioWeightWidthPass < 1 && this.interpolationPass) {
this.initializeFirstPassBuffers(true);
this.resizeWidth =
this.colorChannels === 4
? this.resizeWidthInterpolatedRGBA
: this.resizeWidthInterpolatedRGB;
}
else {
this.initializeFirstPassBuffers(false);
this.resizeWidth =
this.colorChannels === 4 ? this.resizeWidthRGBA : this.resizeWidthRGB;
}
}
if (this.heightOriginal === this.targetHeight) {
// Bypass the height resizer pass:
this.resizeHeight = this.bypassResizer;
}
else {
// Setup the height resizer pass:
this.ratioWeightHeightPass = this.heightOriginal / this.targetHeight;
if (this.ratioWeightHeightPass < 1 && this.interpolationPass) {
this.initializeSecondPassBuffers(true);
this.resizeHeight = this.resizeHeightInterpolated;
}
else {
this.initializeSecondPassBuffers(false);
this.resizeHeight =
this.colorChannels === 4 ? this.resizeHeightRGBA : this.resizeHeightRGB;
}
}
};
Resize.prototype._resizeWidthInterpolatedRGBChannels = function (buffer, fourthChannel) {
const channelsNum = fourthChannel ? 4 : 3;
const ratioWeight = this.ratioWeightWidthPass;
const outputBuffer = this.widthBuffer;
let weight = 0;
let finalOffset = 0;
let pixelOffset = 0;
let firstWeight = 0;
let secondWeight = 0;
let targetPosition;
// Handle for only one interpolation input being valid for start calculation:
for (targetPosition = 0; weight < 1 / 3; targetPosition += channelsNum, weight += ratioWeight) {
for (finalOffset = targetPosition, pixelOffset = 0; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels,
finalOffset += this.targetWidthMultipliedByChannels) {
outputBuffer[finalOffset] = buffer[pixelOffset];
outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1];
outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2];
if (fourthChannel)
outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3];
}
}
// Adjust for overshoot of the last pass's counter:
weight -= 1 / 3;
let interpolationWidthSourceReadStop;
for (interpolationWidthSourceReadStop = this.widthOriginal - 1; weight < interpolationWidthSourceReadStop; targetPosition += channelsNum, weight += ratioWeight) {
// Calculate weightings:
secondWeight = weight % 1;
firstWeight = 1 - secondWeight;
// Interpolate:
for (finalOffset = targetPosition,
pixelOffset = Math.floor(weight) * channelsNum; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels,
finalOffset += this.targetWidthMultipliedByChannels) {
outputBuffer[finalOffset + 0] =
buffer[pixelOffset + 0] * firstWeight +
buffer[pixelOffset + channelsNum + 0] * secondWeight;
outputBuffer[finalOffset + 1] =
buffer[pixelOffset + 1] * firstWeight +
buffer[pixelOffset + channelsNum + 1] * secondWeight;
outputBuffer[finalOffset + 2] =
buffer[pixelOffset + 2] * firstWeight +
buffer[pixelOffset + channelsNum + 2] * secondWeight;
if (fourthChannel)
outputBuffer[finalOffset + 3] =
buffer[pixelOffset + 3] * firstWeight +
buffer[pixelOffset + channelsNum + 3] * secondWeight;
}
}
// Handle for only one interpolation input being valid for end calculation:
for (interpolationWidthSourceReadStop =
this.originalWidthMultipliedByChannels - channelsNum; targetPosition < this.targetWidthMultipliedByChannels; targetPosition += channelsNum) {
for (finalOffset = targetPosition,
pixelOffset = interpolationWidthSourceReadStop; finalOffset < this.widthPassResultSize; pixelOffset += this.originalWidthMultipliedByChannels,
finalOffset += this.targetWidthMultipliedByChannels) {
outputBuffer[finalOffset] = buffer[pixelOffset];
outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1];
outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2];
if (fourthChannel)
outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3];
}
}
return outputBuffer;
};
Resize.prototype._resizeWidthRGBChannels = function (buffer, fourthChannel) {
const channelsNum = fourthChannel ? 4 : 3;
const ratioWeight = this.ratioWeightWidthPass;
const ratioWeightDivisor = 1 / ratioWeight;
const nextLineOffsetOriginalWidth = this.originalWidthMultipliedByChannels - channelsNum + 1;
const nextLineOffsetTargetWidth = this.targetWidthMultipliedByChannels - channelsNum + 1;
const output = this.outputWidthWorkBench;
const outputBuffer = this.widthBuffer;
const trustworthyColorsCount = this.outputWidthWorkBenchOpaquePixelsCount;
let weight = 0;
let amountToNext = 0;
let actualPosition = 0;
let currentPosition = 0;
let line = 0;
let pixelOffset = 0;
let outputOffset = 0;
let multiplier = 1;
let r = 0;
let g = 0;
let b = 0;
let a = 0;
do {
for (line = 0; line < this.originalHeightMultipliedByChannels;) {
output[line++] = 0;
output[line++] = 0;
output[line++] = 0;
if (fourthChannel) {
output[line++] = 0;
trustworthyColorsCount[line / channelsNum - 1] = 0;
}
}
weight = ratioWeight;
do {
amountToNext = 1 + actualPosition - currentPosition;
multiplier = Math.min(weight, amountToNext);
for (line = 0, pixelOffset = actualPosition; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetOriginalWidth) {
r = buffer[pixelOffset];
g = buffer[++pixelOffset];
b = buffer[++pixelOffset];
a = fourthChannel ? buffer[++pixelOffset] : 255;
// Ignore RGB values if pixel is completely transparent
output[line++] += (a ? r : 0) * multiplier;
output[line++] += (a ? g : 0) * multiplier;
output[line++] += (a ? b : 0) * multiplier;
if (fourthChannel) {
output[line++] += a * multiplier;
trustworthyColorsCount[line / channelsNum - 1] += a ? multiplier : 0;
}
}
if (weight >= amountToNext) {
actualPosition += channelsNum;
currentPosition = actualPosition;
weight -= amountToNext;
}
else {
currentPosition += weight;
break;
}
} while (weight > 0 &&
actualPosition < this.originalWidthMultipliedByChannels);
for (line = 0, pixelOffset = outputOffset; line < this.originalHeightMultipliedByChannels; pixelOffset += nextLineOffsetTargetWidth) {
weight = fourthChannel ? trustworthyColorsCount[line / channelsNum] : 1;
multiplier = fourthChannel
? weight
? 1 / weight
: 0
: ratioWeightDivisor;
outputBuffer[pixelOffset] = output[line++] * multiplier;
outputBuffer[++pixelOffset] = output[line++] * multiplier;
outputBuffer[++pixelOffset] = output[line++] * multiplier;
if (fourthChannel)
outputBuffer[++pixelOffset] = output[line++] * ratioWeightDivisor;
}
outputOffset += channelsNum;
} while (outputOffset < this.targetWidthMultipliedByChannels);
return outputBuffer;
};
Resize.prototype._resizeHeightRGBChannels = function (buffer, fourthChannel) {
const ratioWeight = this.ratioWeightHeightPass;
const ratioWeightDivisor = 1 / ratioWeight;
const output = this.outputHeightWorkBench;
const outputBuffer = this.heightBuffer;
const trustworthyColorsCount = this.outputHeightWorkBenchOpaquePixelsCount;
let weight = 0;
let amountToNext = 0;
let actualPosition = 0;
let currentPosition = 0;
let pixelOffset = 0;
let outputOffset = 0;
let caret = 0;
let multiplier = 1;
let r = 0;
let g = 0;
let b = 0;
let a = 0;
do {
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) {
output[pixelOffset++] = 0;
output[pixelOffset++] = 0;
output[pixelOffset++] = 0;
if (fourthChannel) {
output[pixelOffset++] = 0;
trustworthyColorsCount[pixelOffset / 4 - 1] = 0;
}
}
weight = ratioWeight;
do {
amountToNext = 1 + actualPosition - currentPosition;
multiplier = Math.min(weight, amountToNext);
caret = actualPosition;
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) {
r = buffer[caret++];
g = buffer[caret++];
b = buffer[caret++];
a = fourthChannel ? buffer[caret++] : 255;
// Ignore RGB values if pixel is completely transparent
output[pixelOffset++] += (a ? r : 0) * multiplier;
output[pixelOffset++] += (a ? g : 0) * multiplier;
output[pixelOffset++] += (a ? b : 0) * multiplier;
if (fourthChannel) {
output[pixelOffset++] += a * multiplier;
trustworthyColorsCount[pixelOffset / 4 - 1] += a ? multiplier : 0;
}
}
if (weight >= amountToNext) {
actualPosition = caret;
currentPosition = actualPosition;
weight -= amountToNext;
}
else {
currentPosition += weight;
break;
}
} while (weight > 0 && actualPosition < this.widthPassResultSize);
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) {
weight = fourthChannel ? trustworthyColorsCount[pixelOffset / 4] : 1;
multiplier = fourthChannel
? weight
? 1 / weight
: 0
: ratioWeightDivisor;
outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * multiplier);
outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * multiplier);
outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * multiplier);
if (fourthChannel) {
outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] * ratioWeightDivisor);
}
}
} while (outputOffset < this.finalResultSize);
return outputBuffer;
};
Resize.prototype.resizeWidthInterpolatedRGB = function (buffer) {
return this._resizeWidthInterpolatedRGBChannels(buffer, false);
};
Resize.prototype.resizeWidthInterpolatedRGBA = function (buffer) {
return this._resizeWidthInterpolatedRGBChannels(buffer, true);
};
Resize.prototype.resizeWidthRGB = function (buffer) {
return this._resizeWidthRGBChannels(buffer, false);
};
Resize.prototype.resizeWidthRGBA = function (buffer) {
return this._resizeWidthRGBChannels(buffer, true);
};
Resize.prototype.resizeHeightInterpolated = function (buffer) {
const ratioWeight = this.ratioWeightHeightPass;
const outputBuffer = this.heightBuffer;
let weight = 0;
let finalOffset = 0;
let pixelOffset = 0;
let pixelOffsetAccumulated = 0;
let pixelOffsetAccumulated2 = 0;
let firstWeight = 0;
let secondWeight = 0;
let interpolationHeightSourceReadStop;
// Handle for only one interpolation input being valid for start calculation:
for (; weight < 1 / 3; weight += ratioWeight) {
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels;) {
outputBuffer[finalOffset++] = Math.round(buffer[pixelOffset++]);
}
}
// Adjust for overshoot of the last pass's counter:
weight -= 1 / 3;
for (interpolationHeightSourceReadStop = this.heightOriginal - 1; weight < interpolationHeightSourceReadStop; weight += ratioWeight) {
// Calculate weightings:
secondWeight = weight % 1;
firstWeight = 1 - secondWeight;
// Interpolate:
pixelOffsetAccumulated =
Math.floor(weight) * this.targetWidthMultipliedByChannels;
pixelOffsetAccumulated2 =
pixelOffsetAccumulated + this.targetWidthMultipliedByChannels;
for (pixelOffset = 0; pixelOffset < this.targetWidthMultipliedByChannels; ++pixelOffset) {
outputBuffer[finalOffset++] = Math.round(buffer[pixelOffsetAccumulated++] * firstWeight +
buffer[pixelOffsetAccumulated2++] * secondWeight);
}
}
// Handle for only one interpolation input being valid for end calculation:
while (finalOffset < this.finalResultSize) {
for (pixelOffset = 0,
pixelOffsetAccumulated =
interpolationHeightSourceReadStop *
this.targetWidthMultipliedByChannels; pixelOffset < this.targetWidthMultipliedByChannels; ++pixelOffset) {
outputBuffer[finalOffset++] = Math.round(buffer[pixelOffsetAccumulated++]);
}
}
return outputBuffer;
};
Resize.prototype.resizeHeightRGB = function (buffer) {
return this._resizeHeightRGBChannels(buffer, false);
};
Resize.prototype.resizeHeightRGBA = function (buffer) {
return this._resizeHeightRGBChannels(buffer, true);
};
Resize.prototype.resize = function (buffer) {
this.resizeCallback(this.resizeHeight(this.resizeWidth(buffer)));
};
Resize.prototype.bypassResizer = function (buffer) {
// Just return the buffer passed:
return buffer;
};
Resize.prototype.initializeFirstPassBuffers = function (BILINEARAlgo) {
// Initialize the internal width pass buffers:
this.widthBuffer = this.generateFloatBuffer(this.widthPassResultSize);
if (!BILINEARAlgo) {
this.outputWidthWorkBench = this.generateFloatBuffer(this.originalHeightMultipliedByChannels);
if (this.colorChannels > 3) {
this.outputWidthWorkBenchOpaquePixelsCount = this.generateFloat64Buffer(this.heightOriginal);
}
}
};
Resize.prototype.initializeSecondPassBuffers = function (BILINEARAlgo) {
// Initialize the internal height pass buffers:
this.heightBuffer = this.generateUint8Buffer(this.finalResultSize);
if (!BILINEARAlgo) {
this.outputHeightWorkBench = this.generateFloatBuffer(this.targetWidthMultipliedByChannels);
if (this.colorChannels > 3) {
this.outputHeightWorkBenchOpaquePixelsCount = this.generateFloat64Buffer(this.targetWidth);
}
}
};
Resize.prototype.generateFloatBuffer = function (bufferLength) {
// Generate a float32 typed array buffer:
try {
return new Float32Array(bufferLength);
}
catch (error) {
console.error(error);
return [];
}
};
Resize.prototype.generateFloat64Buffer = function (bufferLength) {
// Generate a float64 typed array buffer:
try {
return new Float64Array(bufferLength);
}
catch (error) {
console.error(error);
return [];
}
};
Resize.prototype.generateUint8Buffer = function (bufferLength) {
// Generate a uint8 typed array buffer:
try {
return new Uint8Array(bufferLength);
}
catch (error) {
console.error(error);
return [];
}
};
export default Resize;
//# sourceMappingURL=resize.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"resize.js","sourceRoot":"","sources":["../../../src/modules/resize.ts"],"names":[],"mappings":"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 truncated
+30
View File
@@ -0,0 +1,30 @@
/**
* Copyright (c) 2015 Guyon Roche
*
* 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:</p>
*
* 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.
*/
export declare const operations: {
nearestNeighbor(src: any, dst: any): void;
bilinearInterpolation(src: any, dst: any): void;
_interpolate2D(src: any, dst: any, options?: any, interpolate?: any): void;
bicubicInterpolation(src: any, dst: any, options?: any): void;
hermiteInterpolation(src: any, dst: any, options?: any): void;
bezierInterpolation(src: any, dst: any, options?: any): void;
};
//# sourceMappingURL=resize2.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"resize2.d.ts","sourceRoot":"","sources":["../../../src/modules/resize2.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,eAAO,MAAM,UAAU;yBACA,GAAG,OAAO,GAAG;+BA0BP,GAAG,OAAO,GAAG;wBAuEpB,GAAG,OAAO,GAAG,YAAY,GAAG,gBAAgB,GAAG;8BAmIzC,GAAG,OAAO,GAAG,YAAY,GAAG;8BAqB5B,GAAG,OAAO,GAAG,YAAY,GAAG;6BAqB7B,GAAG,OAAO,GAAG,YAAY,GAAG;CAgCtD,CAAC"}
+248
View File
@@ -0,0 +1,248 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* Copyright (c) 2015 Guyon Roche
*
* 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:</p>
*
* 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.
*/
export const operations = {
nearestNeighbor(src, dst) {
const wSrc = src.width;
const hSrc = src.height;
const wDst = dst.width;
const hDst = dst.height;
const bufSrc = src.data;
const bufDst = dst.data;
for (let i = 0; i < hDst; i++) {
for (let j = 0; j < wDst; j++) {
let posDst = (i * wDst + j) * 4;
const iSrc = Math.floor((i * hSrc) / hDst);
const jSrc = Math.floor((j * wSrc) / wDst);
let posSrc = (iSrc * wSrc + jSrc) * 4;
bufDst[posDst++] = bufSrc[posSrc++];
bufDst[posDst++] = bufSrc[posSrc++];
bufDst[posDst++] = bufSrc[posSrc++];
bufDst[posDst++] = bufSrc[posSrc++];
}
}
},
bilinearInterpolation(src, dst) {
const wSrc = src.width;
const hSrc = src.height;
const wDst = dst.width;
const hDst = dst.height;
const bufSrc = src.data;
const bufDst = dst.data;
const interpolate = function (k, kMin, vMin, kMax, vMax) {
// special case - k is integer
if (kMin === kMax) {
return vMin;
}
return Math.round((k - kMin) * vMax + (kMax - k) * vMin);
};
const assign = function (pos, offset, x, xMin, xMax, y, yMin, yMax) {
let posMin = (yMin * wSrc + xMin) * 4 + offset;
let posMax = (yMin * wSrc + xMax) * 4 + offset;
const vMin = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]);
// special case, y is integer
if (yMax === yMin) {
bufDst[pos + offset] = vMin;
}
else {
posMin = (yMax * wSrc + xMin) * 4 + offset;
posMax = (yMax * wSrc + xMax) * 4 + offset;
const vMax = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]);
bufDst[pos + offset] = interpolate(y, yMin, vMin, yMax, vMax);
}
};
for (let i = 0; i < hDst; i++) {
for (let j = 0; j < wDst; j++) {
const posDst = (i * wDst + j) * 4;
// x & y in src coordinates
const x = (j * wSrc) / wDst;
const xMin = Math.floor(x);
const xMax = Math.min(Math.ceil(x), wSrc - 1);
const y = (i * hSrc) / hDst;
const yMin = Math.floor(y);
const yMax = Math.min(Math.ceil(y), hSrc - 1);
assign(posDst, 0, x, xMin, xMax, y, yMin, yMax);
assign(posDst, 1, x, xMin, xMax, y, yMin, yMax);
assign(posDst, 2, x, xMin, xMax, y, yMin, yMax);
assign(posDst, 3, x, xMin, xMax, y, yMin, yMax);
}
}
},
_interpolate2D(src, dst, options, interpolate) {
const bufSrc = src.data;
const bufDst = dst.data;
const wSrc = src.width;
const hSrc = src.height;
const wDst = dst.width;
const hDst = dst.height;
// when dst smaller than src/2, interpolate first to a multiple between 0.5 and 1.0 src, then sum squares
const wM = Math.max(1, Math.floor(wSrc / wDst));
const wDst2 = wDst * wM;
const hM = Math.max(1, Math.floor(hSrc / hDst));
const hDst2 = hDst * hM;
// ===========================================================
// Pass 1 - interpolate rows
// buf1 has width of dst2 and height of src
const buf1 = Buffer.alloc(wDst2 * hSrc * 4);
for (let i = 0; i < hSrc; i++) {
for (let j = 0; j < wDst2; j++) {
// i in src coords, j in dst coords
// calculate x in src coords
// this interpolation requires 4 sample points and the two inner ones must be real
// the outer points can be fudged for the edges.
// therefore (wSrc-1)/wDst2
const x = (j * (wSrc - 1)) / wDst2;
const xPos = Math.floor(x);
const t = x - xPos;
const srcPos = (i * wSrc + xPos) * 4;
const buf1Pos = (i * wDst2 + j) * 4;
for (let k = 0; k < 4; k++) {
const kPos = srcPos + k;
const x0 = xPos > 0 ? bufSrc[kPos - 4] : 2 * bufSrc[kPos] - bufSrc[kPos + 4];
const x1 = bufSrc[kPos];
const x2 = bufSrc[kPos + 4];
const x3 = xPos < wSrc - 2
? bufSrc[kPos + 8]
: 2 * bufSrc[kPos + 4] - bufSrc[kPos];
buf1[buf1Pos + k] = interpolate(x0, x1, x2, x3, t);
}
}
}
// this._writeFile(wDst2, hSrc, buf1, "out/buf1.jpg");
// ===========================================================
// Pass 2 - interpolate columns
// buf2 has width and height of dst2
const buf2 = Buffer.alloc(wDst2 * hDst2 * 4);
for (let i = 0; i < hDst2; i++) {
for (let j = 0; j < wDst2; j++) {
// i&j in dst2 coords
// calculate y in buf1 coords
// this interpolation requires 4 sample points and the two inner ones must be real
// the outer points can be fudged for the edges.
// therefore (hSrc-1)/hDst2
const y = (i * (hSrc - 1)) / hDst2;
const yPos = Math.floor(y);
const t = y - yPos;
const buf1Pos = (yPos * wDst2 + j) * 4;
const buf2Pos = (i * wDst2 + j) * 4;
for (let k = 0; k < 4; k++) {
const kPos = buf1Pos + k;
const y0 = yPos > 0
? buf1[kPos - wDst2 * 4]
: 2 * buf1[kPos] - buf1[kPos + wDst2 * 4];
const y1 = buf1[kPos];
const y2 = buf1[kPos + wDst2 * 4];
const y3 = yPos < hSrc - 2
? buf1[kPos + wDst2 * 8]
: 2 * buf1[kPos + wDst2 * 4] - buf1[kPos];
buf2[buf2Pos + k] = interpolate(y0, y1, y2, y3, t);
}
}
}
// this._writeFile(wDst2, hDst2, buf2, "out/buf2.jpg");
// ===========================================================
// Pass 3 - scale to dst
const m = wM * hM;
if (m > 1) {
for (let i = 0; i < hDst; i++) {
for (let j = 0; j < wDst; j++) {
// i&j in dst bounded coords
let r = 0;
let g = 0;
let b = 0;
let a = 0;
let realColors = 0;
for (let y = 0; y < hM; y++) {
const yPos = i * hM + y;
for (let x = 0; x < wM; x++) {
const xPos = j * wM + x;
const xyPos = (yPos * wDst2 + xPos) * 4;
const pixelAlpha = buf2[xyPos + 3];
if (pixelAlpha) {
r += buf2[xyPos];
g += buf2[xyPos + 1];
b += buf2[xyPos + 2];
realColors++;
}
a += pixelAlpha;
}
}
const pos = (i * wDst + j) * 4;
bufDst[pos] = realColors ? Math.round(r / realColors) : 0;
bufDst[pos + 1] = realColors ? Math.round(g / realColors) : 0;
bufDst[pos + 2] = realColors ? Math.round(b / realColors) : 0;
bufDst[pos + 3] = Math.round(a / m);
}
}
}
else {
// replace dst buffer with buf2
dst.data = buf2;
}
},
bicubicInterpolation(src, dst, options) {
const interpolateCubic = function (x0, x1, x2, x3, t) {
const a0 = x3 - x2 - x0 + x1;
const a1 = x0 - x1 - a0;
const a2 = x2 - x0;
const a3 = x1;
return Math.max(0, Math.min(255, a0 * (t * t * t) + a1 * (t * t) + a2 * t + a3));
};
return this._interpolate2D(src, dst, options, interpolateCubic);
},
hermiteInterpolation(src, dst, options) {
const interpolateHermite = function (x0, x1, x2, x3, t) {
const c0 = x1;
const c1 = 0.5 * (x2 - x0);
const c2 = x0 - 2.5 * x1 + 2 * x2 - 0.5 * x3;
const c3 = 0.5 * (x3 - x0) + 1.5 * (x1 - x2);
return Math.max(0, Math.min(255, Math.round(((c3 * t + c2) * t + c1) * t + c0)));
};
return this._interpolate2D(src, dst, options, interpolateHermite);
},
bezierInterpolation(src, dst, options) {
// between 2 points y(n), y(n+1), use next points out, y(n-1), y(n+2)
// to predict control points (a & b) to be placed at n+0.5
// ya(n) = y(n) + (y(n+1)-y(n-1))/4
// yb(n) = y(n+1) - (y(n+2)-y(n))/4
// then use std bezier to interpolate [n,n+1)
// y(n+t) = y(n)*(1-t)^3 + 3 * ya(n)*(1-t)^2*t + 3 * yb(n)*(1-t)*t^2 + y(n+1)*t^3
// note the 3* factor for the two control points
// for edge cases, can choose:
// y(-1) = y(0) - 2*(y(1)-y(0))
// y(w) = y(w-1) + 2*(y(w-1)-y(w-2))
// but can go with y(-1) = y(0) and y(w) = y(w-1)
const interpolateBezier = function (x0, x1, x2, x3, t) {
// x1, x2 are the knots, use x0 and x3 to calculate control points
const cp1 = x1 + (x2 - x0) / 4;
const cp2 = x2 - (x3 - x1) / 4;
const nt = 1 - t;
const c0 = x1 * nt * nt * nt;
const c1 = 3 * cp1 * nt * nt * t;
const c2 = 3 * cp2 * nt * t * t;
const c3 = x2 * t * t * t;
return Math.max(0, Math.min(255, Math.round(c0 + c1 + c2 + c3)));
};
return this._interpolate2D(src, dst, options, interpolateBezier);
},
};
//# sourceMappingURL=resize2.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"resize2.js","sourceRoot":"","sources":["../../../src/modules/resize2.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];
+67
View File
@@ -0,0 +1,67 @@
{
"name": "@jimp/plugin-resize",
"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",
"dependencies": {
"@jimp/core": "1.6.0",
"@jimp/types": "1.6.0",
"zod": "^3.23.8"
},
"devDependencies": {
"@jimp/config-eslint": "1.6.0",
"@jimp/config-typescript": "1.6.0",
"@jimp/config-vitest": "1.6.0",
"@jimp/test-utils": "1.6.0",
"@types/node": "^18.19.48",
"@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"
},
"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"
}
+445
View File
@@ -0,0 +1,445 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Resize images > max contrast 8x8 > to BEZIER 2x5 1`] = `
Visualization:
■▩
■▩
■▩
□D
□D
Data:
00-00-00ᶠᶠ DF-DF-DFᶠᶠ
00-00-00ᶠᶠ DF-DF-DFᶠᶠ
00-00-00ᶠᶠ DF-DF-DFᶠᶠ
FF-FF-FFᶠᶠ 20-20-20ᶠᶠ
FF-FF-FFᶠᶠ 20-20-20ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to BEZIER 4x4 1`] = `
Visualization:
■■D□
■■D□
DD3▩
□□▩■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ C0-C0-C0ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ C0-C0-C0ᶠᶠ FF-FF-FFᶠᶠ
C0-C0-C0ᶠᶠ C0-C0-C0ᶠᶠ 60-60-60ᶠᶠ 40-40-40ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 40-40-40ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to BICUBIC 2x5 1`] = `
Visualization:
■▩
■▩
■▩
□D
□D
Data:
00-00-00ᶠᶠ DF-DF-DFᶠᶠ
00-00-00ᶠᶠ DF-DF-DFᶠᶠ
00-00-00ᶠᶠ DF-DF-DFᶠᶠ
FF-FF-FFᶠᶠ 20-20-20ᶠᶠ
FF-FF-FFᶠᶠ 20-20-20ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to BICUBIC 4x4 1`] = `
Visualization:
■■▥□
■■▥□
▥▥!▩
□□▩■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ BF-BF-BFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ BF-BF-BFᶠᶠ FF-FF-FFᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 5F-5F-5Fᶠᶠ 40-40-40ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 40-40-40ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to BILINEAR 2x5 1`] = `
Visualization:
■□
■□
3C
□■
□■
Data:
00-00-00ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ FF-FF-FFᶠᶠ
33-33-33ᶠᶠ CC-CC-CCᶠᶠ
FF-FF-FFᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to BILINEAR 4x4 1`] = `
Visualization:
■■□□
■■□□
□□■■
□□■■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to HERMITE 2x5 1`] = `
Visualization:
■▩
■▩
■▩
□D
□D
Data:
00-00-00ᶠᶠ DF-DF-DFᶠᶠ
00-00-00ᶠᶠ DF-DF-DFᶠᶠ
00-00-00ᶠᶠ DF-DF-DFᶠᶠ
FF-FF-FFᶠᶠ 20-20-20ᶠᶠ
FF-FF-FFᶠᶠ 20-20-20ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to HERMITE 4x4 1`] = `
Visualization:
■■D□
■■D□
DD3▩
□□▩■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ C0-C0-C0ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ C0-C0-C0ᶠᶠ FF-FF-FFᶠᶠ
C0-C0-C0ᶠᶠ C0-C0-C0ᶠᶠ 60-60-60ᶠᶠ 40-40-40ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 40-40-40ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to NEAREST_NEIGHBOR 2x5 1`] = `
Visualization:
■□
■□
■□
□■
□■
Data:
00-00-00ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ FF-FF-FFᶠᶠ
FF-FF-FFᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to NEAREST_NEIGHBOR 4x4 1`] = `
Visualization:
■■□□
■■□□
□□■■
□□■■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to default 2x5 1`] = `
Visualization:
■□
■□
▦▦
□■
□■
Data:
00-00-00ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ FF-FF-FFᶠᶠ
80-80-80ᶠᶠ 80-80-80ᶠᶠ
FF-FF-FFᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 8x8 > to default 4x4 1`] = `
Visualization:
■■□□
■■□□
□□■■
□□■■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 12x12 with dots > to BEZIER 6x6 1`] = `
Visualization:
■■■D□□
■4◇D◇□
■■■D□□
DDD3▩▩
□▴◇▩3■
□D▩▩▴■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ C0-C0-C0ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 44-44-44ᶠᶠ 1D-1D-1Dᶠᶠ C0-C0-C0ᶠᶠ 9F-9F-9Fᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ C0-C0-C0ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
C0-C0-C0ᶠᶠ C0-C0-C0ᶠᶠ C0-C0-C0ᶠᶠ 60-60-60ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
FF-FF-FFᶠᶠ F0-F0-F0ᶠᶠ F9-F9-F9ᶠᶠ 40-40-40ᶠᶠ 15-15-15ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ CA-CA-CAᶠᶠ E9-E9-E9ᶠᶠ 40-40-40ᶠᶠ 4B-4B-4Bᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 12x12 with dots > to BICUBIC 6x6 1`] = `
Visualization:
■■■▥□□
■3D▥3□
■■■▥□□
▥▥▥!▩▩
□ED▩◇■
□3▴▩▩■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ BF-BF-BFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 47-47-47ᶠᶠ 20-20-20ᶠᶠ BF-BF-BFᶠᶠ 97-97-97ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ BF-BF-BFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 5F-5F-5Fᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
FF-FF-FFᶠᶠ EE-EE-EEᶠᶠ F7-F7-F7ᶠᶠ 40-40-40ᶠᶠ 18-18-18ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ C9-C9-C9ᶠᶠ E6-E6-E6ᶠᶠ 40-40-40ᶠᶠ 4E-4E-4Eᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 12x12 with dots > to BILINEAR 6x6 1`] = `
Visualization:
■■■□□□
■■■□■□
■■■□□□
□□□■■■
□□□■■■
□□□■■■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 12x12 with dots > to HERMITE 6x6 1`] = `
Visualization:
■■■D□□
■▩▴D3□
■■■D□□
DDD3▩▩
□▩▴▩1■
□▩▴▩D■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ C0-C0-C0ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 40-40-40ᶠᶠ 19-19-19ᶠᶠ C0-C0-C0ᶠᶠ A6-A6-A6ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ C0-C0-C0ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
C0-C0-C0ᶠᶠ C0-C0-C0ᶠᶠ C0-C0-C0ᶠᶠ 60-60-60ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
FF-FF-FFᶠᶠ F3-F3-F3ᶠᶠ FA-FA-FAᶠᶠ 40-40-40ᶠᶠ 11-11-11ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ CB-CB-CBᶠᶠ EB-EB-EBᶠᶠ 40-40-40ᶠᶠ 48-48-48ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 12x12 with dots > to NEAREST_NEIGHBOR 6x6 1`] = `
Visualization:
■■■□□□
■■■□■□
■■■□□□
□□□■■■
□□□■■■
□□□■■■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > max contrast 12x12 with dots > to default 6x6 1`] = `
Visualization:
■■■□□□
■▩■□▥□
■■■□□□
□□□■■■
□▥□■▩■
□□□■■■
Data:
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 40-40-40ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ BF-BF-BFᶠᶠ FF-FF-FFᶠᶠ
00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ BF-BF-BFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 40-40-40ᶠᶠ 00-00-00ᶠᶠ
FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ FF-FF-FFᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ 00-00-00ᶠᶠ
`;
exports[`Resize images > mutch contrast 4x4 > to BEZIER 6x6 1`] = `
Visualization:
▩D▩▦▥▩
D▩D▦▩D
▩D▩▦▥▩
▦▦▦▦▦▦
▥▩▥▦▩D
▩D▩▦D▩
Data:
40-40-40ᶠᶠ 34-34-34ᶠᶠ 40-40-40ᶠᶠ 80-80-80ᶠᶠ BF-BF-BFᶠᶠ CB-CB-CBᶠᶠ
34-34-34ᶠᶠ 26-26-26ᶠᶠ 34-34-34ᶠᶠ 80-80-80ᶠᶠ CB-CB-CBᶠᶠ D9-D9-D9ᶠᶠ
40-40-40ᶠᶠ 34-34-34ᶠᶠ 40-40-40ᶠᶠ 80-80-80ᶠᶠ BF-BF-BFᶠᶠ CB-CB-CBᶠᶠ
80-80-80ᶠᶠ 80-80-80ᶠᶠ 80-80-80ᶠᶠ 80-80-80ᶠᶠ 80-80-80ᶠᶠ 80-80-80ᶠᶠ
BF-BF-BFᶠᶠ CB-CB-CBᶠᶠ BF-BF-BFᶠᶠ 80-80-80ᶠᶠ 40-40-40ᶠᶠ 34-34-34ᶠᶠ
CB-CB-CBᶠᶠ D9-D9-D9ᶠᶠ CB-CB-CBᶠᶠ 80-80-80ᶠᶠ 34-34-34ᶠᶠ 26-26-26ᶠᶠ
`;
exports[`Resize images > mutch contrast 4x4 > to BICUBIC 6x6 1`] = `
Visualization:
▩▩▩D▥3
▩▩▩D3▴
▩▩▩D▥3
DDDDDD
▥3▥D▩▩
3▴3D▩▩
Data:
40-40-40ᶠᶠ 30-30-30ᶠᶠ 40-40-40ᶠᶠ 7F-7F-7Fᶠᶠ BF-BF-BFᶠᶠ CE-CE-CEᶠᶠ
30-30-30ᶠᶠ 1C-1C-1Cᶠᶠ 30-30-30ᶠᶠ 7F-7F-7Fᶠᶠ CE-CE-CEᶠᶠ E1-E1-E1ᶠᶠ
40-40-40ᶠᶠ 30-30-30ᶠᶠ 40-40-40ᶠᶠ 7F-7F-7Fᶠᶠ BF-BF-BFᶠᶠ CE-CE-CEᶠᶠ
7F-7F-7Fᶠᶠ 7F-7F-7Fᶠᶠ 7F-7F-7Fᶠᶠ 7F-7F-7Fᶠᶠ 7F-7F-7Fᶠᶠ 7F-7F-7Fᶠᶠ
BF-BF-BFᶠᶠ CE-CE-CEᶠᶠ BF-BF-BFᶠᶠ 7F-7F-7Fᶠᶠ 40-40-40ᶠᶠ 30-30-30ᶠᶠ
CE-CE-CEᶠᶠ E1-E1-E1ᶠᶠ CE-CE-CEᶠᶠ 7F-7F-7Fᶠᶠ 30-30-30ᶠᶠ 1C-1C-1Cᶠᶠ
`;
exports[`Resize images > mutch contrast 4x4 > to BILINEAR 6x6 1`] = `
Visualization:
▩▩3▥▥▥
▩▩3▥▥▥
33▴◇◇◇
▥▥◇▩▩▩
▥▥◇▩▩▩
▥▥◇▩▩▩
Data:
40-40-40ᶠᶠ 40-40-40ᶠᶠ 6A-6A-6Aᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ
40-40-40ᶠᶠ 40-40-40ᶠᶠ 6A-6A-6Aᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ
6A-6A-6Aᶠᶠ 6A-6A-6Aᶠᶠ 78-78-78ᶠᶠ 95-95-95ᶠᶠ 95-95-95ᶠᶠ 95-95-95ᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 95-95-95ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 95-95-95ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 95-95-95ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
`;
exports[`Resize images > mutch contrast 4x4 > to HERMITE 6x6 1`] = `
Visualization:
▩3▩▦▥◇
3D3▦◇▩
▩3▩▦▥◇
▦▦▦▦▦▦
▥◇▥▦▩3
◇▩◇▦3D
Data:
40-40-40ᶠᶠ 38-38-38ᶠᶠ 40-40-40ᶠᶠ 80-80-80ᶠᶠ BF-BF-BFᶠᶠ C7-C7-C7ᶠᶠ
38-38-38ᶠᶠ 2F-2F-2Fᶠᶠ 38-38-38ᶠᶠ 80-80-80ᶠᶠ C7-C7-C7ᶠᶠ D0-D0-D0ᶠᶠ
40-40-40ᶠᶠ 38-38-38ᶠᶠ 40-40-40ᶠᶠ 80-80-80ᶠᶠ BF-BF-BFᶠᶠ C7-C7-C7ᶠᶠ
80-80-80ᶠᶠ 80-80-80ᶠᶠ 80-80-80ᶠᶠ 80-80-80ᶠᶠ 80-80-80ᶠᶠ 80-80-80ᶠᶠ
BF-BF-BFᶠᶠ C7-C7-C7ᶠᶠ BF-BF-BFᶠᶠ 80-80-80ᶠᶠ 40-40-40ᶠᶠ 38-38-38ᶠᶠ
C7-C7-C7ᶠᶠ D0-D0-D0ᶠᶠ C7-C7-C7ᶠᶠ 80-80-80ᶠᶠ 38-38-38ᶠᶠ 2F-2F-2Fᶠᶠ
`;
exports[`Resize images > mutch contrast 4x4 > to NEAREST_NEIGHBOR 6x6 1`] = `
Visualization:
▩▩▩▥▥▥
▩▩▩▥▥▥
▩▩▩▥▥▥
▥▥▥▩▩▩
▥▥▥▩▩▩
▥▥▥▩▩▩
Data:
40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ
40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ
40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
`;
exports[`Resize images > mutch contrast 4x4 > to default 6x6 1`] = `
Visualization:
▩▩▩◇▥▥
▩▩▩◇▥▥
▩▩▩◇▥▥
◇◇◇▴33
▥▥▥3▩▩
▥▥▥3▩▩
Data:
40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ 95-95-95ᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ
40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ 95-95-95ᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ
40-40-40ᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ 95-95-95ᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ
95-95-95ᶠᶠ 95-95-95ᶠᶠ 95-95-95ᶠᶠ 78-78-78ᶠᶠ 6A-6A-6Aᶠᶠ 6A-6A-6Aᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 6A-6A-6Aᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ BF-BF-BFᶠᶠ 6A-6A-6Aᶠᶠ 40-40-40ᶠᶠ 40-40-40ᶠᶠ
`;
+26
View File
@@ -0,0 +1,26 @@
/**
* What resizing algorithm to use.
*/
export enum ResizeStrategy {
/**
* Nearest Neighbor resizing is a method used in image processing that assigns the value of the nearest pixel to the output pixel when resizing an image.
* While fast, it can lead to lower quality outputs with noticeable pixelation, especially at larger scaling factors.
*/
NEAREST_NEIGHBOR = "nearestNeighbor",
/**
* Bilinear resizing is an image scaling method that uses the weighted average of the four nearest pixel values, providing smoother gradients than nearest neighbor resizing.
* It's computationally more intense than nearest neighbor but results in images of higher quality and fewer artifacts.
*/
BILINEAR = "bilinearInterpolation",
/**
* Bicubic resizing is an image interpolation method that uses the values of the nearest 16 pixels in the input image to calculate the output pixel value, providing even more smoothness and sharpness than bilinear resizing.
* Although it's computationally more expensive than bilinear and nearest neighbor, it produces higher quality images, making it ideal for photographic image scaling.
*/
BICUBIC = "bicubicInterpolation",
/**
* Hermite resizing is an image resizing method that uses Hermite interpolation, a mathematical formula, to determine the values of output pixels based on a weighted average of the surrounding pixels.
* Although slower than some simpler techniques like bilinear or nearest neighbor, Hermite resizing can produce higher quality visuals and detailed renderings with less blurring.
*/
HERMITE = "hermiteInterpolation",
BEZIER = "bezierInterpolation",
}
+101
View File
@@ -0,0 +1,101 @@
import { expect, test, describe } from "vitest";
import { makeTestImage } from "@jimp/test-utils";
import { createJimp } from "@jimp/core";
import { methods, ResizeStrategy } from "./index.js";
const jimp = createJimp({ plugins: [methods], formats: [] });
describe("Resize images", () => {
const testImages = [
{
title: "max contrast 8x8",
src: jimp.fromBitmap(
makeTestImage(
"■■■■□□□□",
"■■■■□□□□",
"■■■■□□□□",
"■■■■□□□□",
"□□□□■■■■",
"□□□□■■■■",
"□□□□■■■■",
"□□□□■■■■"
)
),
tests: [
{ mode: "default", size: { height: 4, width: 4 } },
{ mode: "NEAREST_NEIGHBOR", size: { height: 4, width: 4 } },
{ mode: "BILINEAR", size: { height: 4, width: 4 } },
{ mode: "BICUBIC", size: { height: 4, width: 4 } },
{ mode: "HERMITE", size: { height: 4, width: 4 } },
{ mode: "BEZIER", size: { height: 4, width: 4 } },
{ mode: "default", size: { height: 5, width: 2 } },
{ mode: "NEAREST_NEIGHBOR", size: { height: 5, width: 2 } },
{ mode: "BILINEAR", size: { height: 5, width: 2 } },
{ mode: "BICUBIC", size: { height: 5, width: 2 } },
{ mode: "HERMITE", size: { height: 5, width: 2 } },
{ mode: "BEZIER", size: { height: 5, width: 2 } },
],
},
/**********************************************************************/
{
title: "max contrast 12x12 with dots",
src: jimp.fromBitmap(
makeTestImage(
"■■■■■■□□□□□□",
"■■■■■■□□□□□□",
"■■■□■■□□■□□□",
"■■■■■■□□□□□□",
"■■■■■■□□□□□□",
"■■■■■■□□□□□□",
"□□□□□□■■■■■■",
"□□□□□□■■■■■■",
"□□□□□□■■■■■■",
"□□□■□□■■□■■■",
"□□□□□□■■■■■■",
"□□□□□□■■■■■■"
)
),
tests: [
{ mode: "default", size: { height: 6, width: 6 } },
{ mode: "NEAREST_NEIGHBOR", size: { height: 6, width: 6 } },
{ mode: "BILINEAR", size: { height: 6, width: 6 } },
{ mode: "BICUBIC", size: { height: 6, width: 6 } },
{ mode: "HERMITE", size: { height: 6, width: 6 } },
{ mode: "BEZIER", size: { height: 6, width: 6 } },
],
},
/**********************************************************************/
{
title: "mutch contrast 4x4",
src: jimp.fromBitmap(makeTestImage("▩▩▥▥", "▩▩▥▥", "▥▥▩▩", "▥▥▩▩")),
tests: [
{ mode: "default", size: { height: 6, width: 6 } },
{ mode: "NEAREST_NEIGHBOR", size: { height: 6, width: 6 } },
{ mode: "BILINEAR", size: { height: 6, width: 6 } },
{ mode: "BICUBIC", size: { height: 6, width: 6 } },
{ mode: "HERMITE", size: { height: 6, width: 6 } },
{ mode: "BEZIER", size: { height: 6, width: 6 } },
],
},
];
testImages.forEach((image) => {
describe(image.title, () => {
image.tests.forEach(({ mode: modeType, size }) => {
test(`to ${modeType} ${size.width}x${size.height}`, () => {
const mode = ResizeStrategy[modeType as keyof typeof ResizeStrategy];
expect(
image.src.clone().resize({
w: size.width,
h: size.height,
mode,
})
).toMatchSnapshot();
});
});
});
});
});
+176
View File
@@ -0,0 +1,176 @@
import { JimpClass } from "@jimp/types";
import { ResizeStrategy } from "./constants.js";
import { z } from "zod";
import Resize from "./modules/resize.js";
import { operations as Resize2 } from "./modules/resize2.js";
export * from "./constants.js";
interface ResizeClass {
// eslint-disable-next-line @typescript-eslint/no-misused-new
new (
widthOriginal: number,
heightOriginal: number,
targetWidth: number,
targetHeight: number,
blendAlpha: boolean,
interpolationPass: boolean,
resizeCallback: (buffer: Buffer) => void
): ResizeClass;
resize(buffer: Buffer): void;
}
type Constructable<T> = new (...args: unknown[]) => T;
const ResizeOptionsSchema = z.union([
z.object({
/** the width to resize the image to */
w: z.number().min(0),
/** the height to resize the image to */
h: z.number().min(0).optional(),
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: z.nativeEnum(ResizeStrategy).optional(),
}),
z.object({
/** the width to resize the image to */
w: z.number().min(0).optional(),
/** the height to resize the image to */
h: z.number().min(0),
/** a scaling method (e.g. ResizeStrategy.BEZIER) */
mode: z.nativeEnum(ResizeStrategy).optional(),
}),
]);
export type ResizeOptions = z.infer<typeof ResizeOptionsSchema>;
const ScaleToFitOptionsSchema = z.object({
/** the width to resize the image to */
w: z.number().min(0),
/** the height to resize the image to */
h: z.number().min(0),
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: z.nativeEnum(ResizeStrategy).optional(),
});
export type ScaleToFitOptions = z.infer<typeof ScaleToFitOptionsSchema>;
const ScaleComplexOptionsSchema = z.object({
/** the width to resize the image to */
f: z.number().min(0),
/** a scaling method (e.g. Jimp.RESIZE_BEZIER) */
mode: z.nativeEnum(ResizeStrategy).optional(),
});
export type ScaleComplexOptions = z.infer<typeof ScaleComplexOptionsSchema>;
export type ScaleOptions = number | ScaleComplexOptions;
export const methods = {
/**
* Resizes the image to a set width and height using a 2-pass bilinear algorithm
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.resize({ w: 150 });
* ```
*/
resize<I extends JimpClass>(image: I, options: ResizeOptions) {
const { mode } = ResizeOptionsSchema.parse(options);
let w: number;
let h: number;
if (typeof options.w === "number") {
w = options.w;
h = options.h ?? image.bitmap.height * (w / image.bitmap.width);
} else if (typeof options.h === "number") {
h = options.h;
w = options.w ?? image.bitmap.width * (h / image.bitmap.height);
} else {
throw new Error("w must be a number");
}
// round inputs
w = Math.round(w) || 1;
h = Math.round(h) || 1;
if (mode && typeof Resize2[mode] === "function") {
const dst = {
data: Buffer.alloc(w * h * 4),
width: w,
height: h,
};
Resize2[mode](image.bitmap, dst);
image.bitmap = dst;
} else {
const resize = new (Resize as unknown as Constructable<ResizeClass>)(
image.bitmap.width,
image.bitmap.height,
w,
h,
true,
true,
(buffer: Buffer) => {
image.bitmap.data = Buffer.from(buffer);
image.bitmap.width = w;
image.bitmap.height = h;
}
);
resize.resize(image.bitmap.data);
}
return image;
},
/**
* Uniformly scales the image by a factor.
* @param f the factor to scale the image by
* @param mode (optional) a scaling method (e.g. Jimp.RESIZE_BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scale(0.5);
* ```
*/
scale<I extends JimpClass>(image: I, options: ScaleOptions) {
const { f, mode } =
typeof options === "number"
? ({ f: options } as ScaleComplexOptions)
: ScaleComplexOptionsSchema.parse(options);
const w = image.bitmap.width * f;
const h = image.bitmap.height * f;
return this.resize(image, { w, h, mode: mode });
},
/**
* Scale the image to the largest size that fits inside the rectangle that has the given width and height.
* @param w the width to resize the image to
* @param h the height to resize the image to
* @param mode a scaling method (e.g. ResizeStrategy.BEZIER)
* @example
* ```ts
* import { Jimp } from "jimp";
*
* const image = await Jimp.read("test/image.png");
*
* image.scaleToFit(100, 100);
* ```
*/
scaleToFit<I extends JimpClass>(image: I, options: ScaleToFitOptions) {
const { h, w, mode } = ScaleToFitOptionsSchema.parse(options);
const f =
w / h > image.bitmap.width / image.bitmap.height
? h / image.bitmap.height
: w / image.bitmap.width;
return this.scale(image, { f, mode: mode });
},
};
+555
View File
@@ -0,0 +1,555 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
// JavaScript Image Resizer (c) 2012 - Grant Galitz
// Released to public domain 29 July 2013: https://github.com/grantgalitz/JS-Image-Resizer/issues/4
function Resize(
widthOriginal,
heightOriginal,
targetWidth,
targetHeight,
blendAlpha,
interpolationPass,
resizeCallback
) {
this.widthOriginal = Math.abs(Math.floor(widthOriginal) || 0);
this.heightOriginal = Math.abs(Math.floor(heightOriginal) || 0);
this.targetWidth = Math.abs(Math.floor(targetWidth) || 0);
this.targetHeight = Math.abs(Math.floor(targetHeight) || 0);
this.colorChannels = blendAlpha ? 4 : 3;
this.interpolationPass = Boolean(interpolationPass);
this.resizeCallback =
typeof resizeCallback === "function" ? resizeCallback : function () {};
this.targetWidthMultipliedByChannels = this.targetWidth * this.colorChannels;
this.originalWidthMultipliedByChannels =
this.widthOriginal * this.colorChannels;
this.originalHeightMultipliedByChannels =
this.heightOriginal * this.colorChannels;
this.widthPassResultSize =
this.targetWidthMultipliedByChannels * this.heightOriginal;
this.finalResultSize =
this.targetWidthMultipliedByChannels * this.targetHeight;
this.initialize();
}
Resize.prototype.initialize = function () {
// Perform some checks:
if (
this.widthOriginal > 0 &&
this.heightOriginal > 0 &&
this.targetWidth > 0 &&
this.targetHeight > 0
) {
this.configurePasses();
} else {
console.log(this);
throw new Error("Invalid settings specified for the resizer.");
}
};
Resize.prototype.configurePasses = function () {
if (this.widthOriginal === this.targetWidth) {
// Bypass the width resizer pass:
this.resizeWidth = this.bypassResizer;
} else {
// Setup the width resizer pass:
this.ratioWeightWidthPass = this.widthOriginal / this.targetWidth;
if (this.ratioWeightWidthPass < 1 && this.interpolationPass) {
this.initializeFirstPassBuffers(true);
this.resizeWidth =
this.colorChannels === 4
? this.resizeWidthInterpolatedRGBA
: this.resizeWidthInterpolatedRGB;
} else {
this.initializeFirstPassBuffers(false);
this.resizeWidth =
this.colorChannels === 4 ? this.resizeWidthRGBA : this.resizeWidthRGB;
}
}
if (this.heightOriginal === this.targetHeight) {
// Bypass the height resizer pass:
this.resizeHeight = this.bypassResizer;
} else {
// Setup the height resizer pass:
this.ratioWeightHeightPass = this.heightOriginal / this.targetHeight;
if (this.ratioWeightHeightPass < 1 && this.interpolationPass) {
this.initializeSecondPassBuffers(true);
this.resizeHeight = this.resizeHeightInterpolated;
} else {
this.initializeSecondPassBuffers(false);
this.resizeHeight =
this.colorChannels === 4 ? this.resizeHeightRGBA : this.resizeHeightRGB;
}
}
};
Resize.prototype._resizeWidthInterpolatedRGBChannels = function (
buffer,
fourthChannel
) {
const channelsNum = fourthChannel ? 4 : 3;
const ratioWeight = this.ratioWeightWidthPass;
const outputBuffer = this.widthBuffer;
let weight = 0;
let finalOffset = 0;
let pixelOffset = 0;
let firstWeight = 0;
let secondWeight = 0;
let targetPosition;
// Handle for only one interpolation input being valid for start calculation:
for (
targetPosition = 0;
weight < 1 / 3;
targetPosition += channelsNum, weight += ratioWeight
) {
for (
finalOffset = targetPosition, pixelOffset = 0;
finalOffset < this.widthPassResultSize;
pixelOffset += this.originalWidthMultipliedByChannels,
finalOffset += this.targetWidthMultipliedByChannels
) {
outputBuffer[finalOffset] = buffer[pixelOffset];
outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1];
outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2];
if (fourthChannel)
outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3];
}
}
// Adjust for overshoot of the last pass's counter:
weight -= 1 / 3;
let interpolationWidthSourceReadStop;
for (
interpolationWidthSourceReadStop = this.widthOriginal - 1;
weight < interpolationWidthSourceReadStop;
targetPosition += channelsNum, weight += ratioWeight
) {
// Calculate weightings:
secondWeight = weight % 1;
firstWeight = 1 - secondWeight;
// Interpolate:
for (
finalOffset = targetPosition,
pixelOffset = Math.floor(weight) * channelsNum;
finalOffset < this.widthPassResultSize;
pixelOffset += this.originalWidthMultipliedByChannels,
finalOffset += this.targetWidthMultipliedByChannels
) {
outputBuffer[finalOffset + 0] =
buffer[pixelOffset + 0] * firstWeight +
buffer[pixelOffset + channelsNum + 0] * secondWeight;
outputBuffer[finalOffset + 1] =
buffer[pixelOffset + 1] * firstWeight +
buffer[pixelOffset + channelsNum + 1] * secondWeight;
outputBuffer[finalOffset + 2] =
buffer[pixelOffset + 2] * firstWeight +
buffer[pixelOffset + channelsNum + 2] * secondWeight;
if (fourthChannel)
outputBuffer[finalOffset + 3] =
buffer[pixelOffset + 3] * firstWeight +
buffer[pixelOffset + channelsNum + 3] * secondWeight;
}
}
// Handle for only one interpolation input being valid for end calculation:
for (
interpolationWidthSourceReadStop =
this.originalWidthMultipliedByChannels - channelsNum;
targetPosition < this.targetWidthMultipliedByChannels;
targetPosition += channelsNum
) {
for (
finalOffset = targetPosition,
pixelOffset = interpolationWidthSourceReadStop;
finalOffset < this.widthPassResultSize;
pixelOffset += this.originalWidthMultipliedByChannels,
finalOffset += this.targetWidthMultipliedByChannels
) {
outputBuffer[finalOffset] = buffer[pixelOffset];
outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1];
outputBuffer[finalOffset + 2] = buffer[pixelOffset + 2];
if (fourthChannel)
outputBuffer[finalOffset + 3] = buffer[pixelOffset + 3];
}
}
return outputBuffer;
};
Resize.prototype._resizeWidthRGBChannels = function (buffer, fourthChannel) {
const channelsNum = fourthChannel ? 4 : 3;
const ratioWeight = this.ratioWeightWidthPass;
const ratioWeightDivisor = 1 / ratioWeight;
const nextLineOffsetOriginalWidth =
this.originalWidthMultipliedByChannels - channelsNum + 1;
const nextLineOffsetTargetWidth =
this.targetWidthMultipliedByChannels - channelsNum + 1;
const output = this.outputWidthWorkBench;
const outputBuffer = this.widthBuffer;
const trustworthyColorsCount = this.outputWidthWorkBenchOpaquePixelsCount;
let weight = 0;
let amountToNext = 0;
let actualPosition = 0;
let currentPosition = 0;
let line = 0;
let pixelOffset = 0;
let outputOffset = 0;
let multiplier = 1;
let r = 0;
let g = 0;
let b = 0;
let a = 0;
do {
for (line = 0; line < this.originalHeightMultipliedByChannels; ) {
output[line++] = 0;
output[line++] = 0;
output[line++] = 0;
if (fourthChannel) {
output[line++] = 0;
trustworthyColorsCount[line / channelsNum - 1] = 0;
}
}
weight = ratioWeight;
do {
amountToNext = 1 + actualPosition - currentPosition;
multiplier = Math.min(weight, amountToNext);
for (
line = 0, pixelOffset = actualPosition;
line < this.originalHeightMultipliedByChannels;
pixelOffset += nextLineOffsetOriginalWidth
) {
r = buffer[pixelOffset];
g = buffer[++pixelOffset];
b = buffer[++pixelOffset];
a = fourthChannel ? buffer[++pixelOffset] : 255;
// Ignore RGB values if pixel is completely transparent
output[line++] += (a ? r : 0) * multiplier;
output[line++] += (a ? g : 0) * multiplier;
output[line++] += (a ? b : 0) * multiplier;
if (fourthChannel) {
output[line++] += a * multiplier;
trustworthyColorsCount[line / channelsNum - 1] += a ? multiplier : 0;
}
}
if (weight >= amountToNext) {
actualPosition += channelsNum;
currentPosition = actualPosition;
weight -= amountToNext;
} else {
currentPosition += weight;
break;
}
} while (
weight > 0 &&
actualPosition < this.originalWidthMultipliedByChannels
);
for (
line = 0, pixelOffset = outputOffset;
line < this.originalHeightMultipliedByChannels;
pixelOffset += nextLineOffsetTargetWidth
) {
weight = fourthChannel ? trustworthyColorsCount[line / channelsNum] : 1;
multiplier = fourthChannel
? weight
? 1 / weight
: 0
: ratioWeightDivisor;
outputBuffer[pixelOffset] = output[line++] * multiplier;
outputBuffer[++pixelOffset] = output[line++] * multiplier;
outputBuffer[++pixelOffset] = output[line++] * multiplier;
if (fourthChannel)
outputBuffer[++pixelOffset] = output[line++] * ratioWeightDivisor;
}
outputOffset += channelsNum;
} while (outputOffset < this.targetWidthMultipliedByChannels);
return outputBuffer;
};
Resize.prototype._resizeHeightRGBChannels = function (buffer, fourthChannel) {
const ratioWeight = this.ratioWeightHeightPass;
const ratioWeightDivisor = 1 / ratioWeight;
const output = this.outputHeightWorkBench;
const outputBuffer = this.heightBuffer;
const trustworthyColorsCount = this.outputHeightWorkBenchOpaquePixelsCount;
let weight = 0;
let amountToNext = 0;
let actualPosition = 0;
let currentPosition = 0;
let pixelOffset = 0;
let outputOffset = 0;
let caret = 0;
let multiplier = 1;
let r = 0;
let g = 0;
let b = 0;
let a = 0;
do {
for (
pixelOffset = 0;
pixelOffset < this.targetWidthMultipliedByChannels;
) {
output[pixelOffset++] = 0;
output[pixelOffset++] = 0;
output[pixelOffset++] = 0;
if (fourthChannel) {
output[pixelOffset++] = 0;
trustworthyColorsCount[pixelOffset / 4 - 1] = 0;
}
}
weight = ratioWeight;
do {
amountToNext = 1 + actualPosition - currentPosition;
multiplier = Math.min(weight, amountToNext);
caret = actualPosition;
for (
pixelOffset = 0;
pixelOffset < this.targetWidthMultipliedByChannels;
) {
r = buffer[caret++];
g = buffer[caret++];
b = buffer[caret++];
a = fourthChannel ? buffer[caret++] : 255;
// Ignore RGB values if pixel is completely transparent
output[pixelOffset++] += (a ? r : 0) * multiplier;
output[pixelOffset++] += (a ? g : 0) * multiplier;
output[pixelOffset++] += (a ? b : 0) * multiplier;
if (fourthChannel) {
output[pixelOffset++] += a * multiplier;
trustworthyColorsCount[pixelOffset / 4 - 1] += a ? multiplier : 0;
}
}
if (weight >= amountToNext) {
actualPosition = caret;
currentPosition = actualPosition;
weight -= amountToNext;
} else {
currentPosition += weight;
break;
}
} while (weight > 0 && actualPosition < this.widthPassResultSize);
for (
pixelOffset = 0;
pixelOffset < this.targetWidthMultipliedByChannels;
) {
weight = fourthChannel ? trustworthyColorsCount[pixelOffset / 4] : 1;
multiplier = fourthChannel
? weight
? 1 / weight
: 0
: ratioWeightDivisor;
outputBuffer[outputOffset++] = Math.round(
output[pixelOffset++] * multiplier
);
outputBuffer[outputOffset++] = Math.round(
output[pixelOffset++] * multiplier
);
outputBuffer[outputOffset++] = Math.round(
output[pixelOffset++] * multiplier
);
if (fourthChannel) {
outputBuffer[outputOffset++] = Math.round(
output[pixelOffset++] * ratioWeightDivisor
);
}
}
} while (outputOffset < this.finalResultSize);
return outputBuffer;
};
Resize.prototype.resizeWidthInterpolatedRGB = function (buffer) {
return this._resizeWidthInterpolatedRGBChannels(buffer, false);
};
Resize.prototype.resizeWidthInterpolatedRGBA = function (buffer) {
return this._resizeWidthInterpolatedRGBChannels(buffer, true);
};
Resize.prototype.resizeWidthRGB = function (buffer) {
return this._resizeWidthRGBChannels(buffer, false);
};
Resize.prototype.resizeWidthRGBA = function (buffer) {
return this._resizeWidthRGBChannels(buffer, true);
};
Resize.prototype.resizeHeightInterpolated = function (buffer) {
const ratioWeight = this.ratioWeightHeightPass;
const outputBuffer = this.heightBuffer;
let weight = 0;
let finalOffset = 0;
let pixelOffset = 0;
let pixelOffsetAccumulated = 0;
let pixelOffsetAccumulated2 = 0;
let firstWeight = 0;
let secondWeight = 0;
let interpolationHeightSourceReadStop;
// Handle for only one interpolation input being valid for start calculation:
for (; weight < 1 / 3; weight += ratioWeight) {
for (
pixelOffset = 0;
pixelOffset < this.targetWidthMultipliedByChannels;
) {
outputBuffer[finalOffset++] = Math.round(buffer[pixelOffset++]);
}
}
// Adjust for overshoot of the last pass's counter:
weight -= 1 / 3;
for (
interpolationHeightSourceReadStop = this.heightOriginal - 1;
weight < interpolationHeightSourceReadStop;
weight += ratioWeight
) {
// Calculate weightings:
secondWeight = weight % 1;
firstWeight = 1 - secondWeight;
// Interpolate:
pixelOffsetAccumulated =
Math.floor(weight) * this.targetWidthMultipliedByChannels;
pixelOffsetAccumulated2 =
pixelOffsetAccumulated + this.targetWidthMultipliedByChannels;
for (
pixelOffset = 0;
pixelOffset < this.targetWidthMultipliedByChannels;
++pixelOffset
) {
outputBuffer[finalOffset++] = Math.round(
buffer[pixelOffsetAccumulated++] * firstWeight +
buffer[pixelOffsetAccumulated2++] * secondWeight
);
}
}
// Handle for only one interpolation input being valid for end calculation:
while (finalOffset < this.finalResultSize) {
for (
pixelOffset = 0,
pixelOffsetAccumulated =
interpolationHeightSourceReadStop *
this.targetWidthMultipliedByChannels;
pixelOffset < this.targetWidthMultipliedByChannels;
++pixelOffset
) {
outputBuffer[finalOffset++] = Math.round(
buffer[pixelOffsetAccumulated++]
);
}
}
return outputBuffer;
};
Resize.prototype.resizeHeightRGB = function (buffer) {
return this._resizeHeightRGBChannels(buffer, false);
};
Resize.prototype.resizeHeightRGBA = function (buffer) {
return this._resizeHeightRGBChannels(buffer, true);
};
Resize.prototype.resize = function (buffer) {
this.resizeCallback(this.resizeHeight(this.resizeWidth(buffer)));
};
Resize.prototype.bypassResizer = function (buffer) {
// Just return the buffer passed:
return buffer;
};
Resize.prototype.initializeFirstPassBuffers = function (BILINEARAlgo) {
// Initialize the internal width pass buffers:
this.widthBuffer = this.generateFloatBuffer(this.widthPassResultSize);
if (!BILINEARAlgo) {
this.outputWidthWorkBench = this.generateFloatBuffer(
this.originalHeightMultipliedByChannels
);
if (this.colorChannels > 3) {
this.outputWidthWorkBenchOpaquePixelsCount = this.generateFloat64Buffer(
this.heightOriginal
);
}
}
};
Resize.prototype.initializeSecondPassBuffers = function (BILINEARAlgo) {
// Initialize the internal height pass buffers:
this.heightBuffer = this.generateUint8Buffer(this.finalResultSize);
if (!BILINEARAlgo) {
this.outputHeightWorkBench = this.generateFloatBuffer(
this.targetWidthMultipliedByChannels
);
if (this.colorChannels > 3) {
this.outputHeightWorkBenchOpaquePixelsCount = this.generateFloat64Buffer(
this.targetWidth
);
}
}
};
Resize.prototype.generateFloatBuffer = function (bufferLength) {
// Generate a float32 typed array buffer:
try {
return new Float32Array(bufferLength);
} catch (error) {
console.error(error);
return [];
}
};
Resize.prototype.generateFloat64Buffer = function (bufferLength) {
// Generate a float64 typed array buffer:
try {
return new Float64Array(bufferLength);
} catch (error) {
console.error(error);
return [];
}
};
Resize.prototype.generateUint8Buffer = function (bufferLength) {
// Generate a uint8 typed array buffer:
try {
return new Uint8Array(bufferLength);
} catch (error) {
console.error(error);
return [];
}
};
export default Resize;
+327
View File
@@ -0,0 +1,327 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* Copyright (c) 2015 Guyon Roche
*
* 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:</p>
*
* 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.
*/
export const operations = {
nearestNeighbor(src: any, dst: any) {
const wSrc = src.width;
const hSrc = src.height;
const wDst = dst.width;
const hDst = dst.height;
const bufSrc = src.data;
const bufDst = dst.data;
for (let i = 0; i < hDst; i++) {
for (let j = 0; j < wDst; j++) {
let posDst = (i * wDst + j) * 4;
const iSrc = Math.floor((i * hSrc) / hDst);
const jSrc = Math.floor((j * wSrc) / wDst);
let posSrc = (iSrc * wSrc + jSrc) * 4;
bufDst[posDst++] = bufSrc[posSrc++];
bufDst[posDst++] = bufSrc[posSrc++];
bufDst[posDst++] = bufSrc[posSrc++];
bufDst[posDst++] = bufSrc[posSrc++];
}
}
},
bilinearInterpolation(src: any, dst: any) {
const wSrc = src.width;
const hSrc = src.height;
const wDst = dst.width;
const hDst = dst.height;
const bufSrc = src.data;
const bufDst = dst.data;
const interpolate = function (
k: number,
kMin: number,
vMin: number,
kMax: number,
vMax: number,
) {
// special case - k is integer
if (kMin === kMax) {
return vMin;
}
return Math.round((k - kMin) * vMax + (kMax - k) * vMin);
};
const assign = function (
pos: number,
offset: number,
x: number,
xMin: number,
xMax: number,
y: number,
yMin: number,
yMax: number,
) {
let posMin = (yMin * wSrc + xMin) * 4 + offset;
let posMax = (yMin * wSrc + xMax) * 4 + offset;
const vMin = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]);
// special case, y is integer
if (yMax === yMin) {
bufDst[pos + offset] = vMin;
} else {
posMin = (yMax * wSrc + xMin) * 4 + offset;
posMax = (yMax * wSrc + xMax) * 4 + offset;
const vMax = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]);
bufDst[pos + offset] = interpolate(y, yMin, vMin, yMax, vMax);
}
};
for (let i = 0; i < hDst; i++) {
for (let j = 0; j < wDst; j++) {
const posDst = (i * wDst + j) * 4;
// x & y in src coordinates
const x = (j * wSrc) / wDst;
const xMin = Math.floor(x);
const xMax = Math.min(Math.ceil(x), wSrc - 1);
const y = (i * hSrc) / hDst;
const yMin = Math.floor(y);
const yMax = Math.min(Math.ceil(y), hSrc - 1);
assign(posDst, 0, x, xMin, xMax, y, yMin, yMax);
assign(posDst, 1, x, xMin, xMax, y, yMin, yMax);
assign(posDst, 2, x, xMin, xMax, y, yMin, yMax);
assign(posDst, 3, x, xMin, xMax, y, yMin, yMax);
}
}
},
_interpolate2D(src: any, dst: any, options?: any, interpolate?: any) {
const bufSrc = src.data;
const bufDst = dst.data;
const wSrc = src.width;
const hSrc = src.height;
const wDst = dst.width;
const hDst = dst.height;
// when dst smaller than src/2, interpolate first to a multiple between 0.5 and 1.0 src, then sum squares
const wM = Math.max(1, Math.floor(wSrc / wDst));
const wDst2 = wDst * wM;
const hM = Math.max(1, Math.floor(hSrc / hDst));
const hDst2 = hDst * hM;
// ===========================================================
// Pass 1 - interpolate rows
// buf1 has width of dst2 and height of src
const buf1 = Buffer.alloc(wDst2 * hSrc * 4);
for (let i = 0; i < hSrc; i++) {
for (let j = 0; j < wDst2; j++) {
// i in src coords, j in dst coords
// calculate x in src coords
// this interpolation requires 4 sample points and the two inner ones must be real
// the outer points can be fudged for the edges.
// therefore (wSrc-1)/wDst2
const x = (j * (wSrc - 1)) / wDst2;
const xPos = Math.floor(x);
const t = x - xPos;
const srcPos = (i * wSrc + xPos) * 4;
const buf1Pos = (i * wDst2 + j) * 4;
for (let k = 0; k < 4; k++) {
const kPos = srcPos + k;
const x0 =
xPos > 0 ? bufSrc[kPos - 4] : 2 * bufSrc[kPos] - bufSrc[kPos + 4];
const x1 = bufSrc[kPos];
const x2 = bufSrc[kPos + 4];
const x3 =
xPos < wSrc - 2
? bufSrc[kPos + 8]
: 2 * bufSrc[kPos + 4] - bufSrc[kPos];
buf1[buf1Pos + k] = interpolate(x0, x1, x2, x3, t);
}
}
}
// this._writeFile(wDst2, hSrc, buf1, "out/buf1.jpg");
// ===========================================================
// Pass 2 - interpolate columns
// buf2 has width and height of dst2
const buf2 = Buffer.alloc(wDst2 * hDst2 * 4);
for (let i = 0; i < hDst2; i++) {
for (let j = 0; j < wDst2; j++) {
// i&j in dst2 coords
// calculate y in buf1 coords
// this interpolation requires 4 sample points and the two inner ones must be real
// the outer points can be fudged for the edges.
// therefore (hSrc-1)/hDst2
const y = (i * (hSrc - 1)) / hDst2;
const yPos = Math.floor(y);
const t = y - yPos;
const buf1Pos = (yPos * wDst2 + j) * 4;
const buf2Pos = (i * wDst2 + j) * 4;
for (let k = 0; k < 4; k++) {
const kPos = buf1Pos + k;
const y0 =
yPos > 0
? buf1[kPos - wDst2 * 4]
: 2 * buf1[kPos]! - buf1[kPos + wDst2 * 4]!;
const y1 = buf1[kPos];
const y2 = buf1[kPos + wDst2 * 4];
const y3 =
yPos < hSrc - 2
? buf1[kPos + wDst2 * 8]
: 2 * buf1[kPos + wDst2 * 4]! - buf1[kPos]!;
buf2[buf2Pos + k] = interpolate(y0, y1, y2, y3, t);
}
}
}
// this._writeFile(wDst2, hDst2, buf2, "out/buf2.jpg");
// ===========================================================
// Pass 3 - scale to dst
const m = wM * hM;
if (m > 1) {
for (let i = 0; i < hDst; i++) {
for (let j = 0; j < wDst; j++) {
// i&j in dst bounded coords
let r = 0;
let g = 0;
let b = 0;
let a = 0;
let realColors = 0;
for (let y = 0; y < hM; y++) {
const yPos = i * hM + y;
for (let x = 0; x < wM; x++) {
const xPos = j * wM + x;
const xyPos = (yPos * wDst2 + xPos) * 4;
const pixelAlpha = buf2[xyPos + 3]!;
if (pixelAlpha) {
r += buf2[xyPos]!;
g += buf2[xyPos + 1]!;
b += buf2[xyPos + 2]!;
realColors++;
}
a += pixelAlpha;
}
}
const pos = (i * wDst + j) * 4;
bufDst[pos] = realColors ? Math.round(r / realColors) : 0;
bufDst[pos + 1] = realColors ? Math.round(g / realColors) : 0;
bufDst[pos + 2] = realColors ? Math.round(b / realColors) : 0;
bufDst[pos + 3] = Math.round(a / m);
}
}
} else {
// replace dst buffer with buf2
dst.data = buf2;
}
},
bicubicInterpolation(src: any, dst: any, options?: any) {
const interpolateCubic = function (
x0: number,
x1: number,
x2: number,
x3: number,
t: number,
) {
const a0 = x3 - x2 - x0 + x1;
const a1 = x0 - x1 - a0;
const a2 = x2 - x0;
const a3 = x1;
return Math.max(
0,
Math.min(255, a0 * (t * t * t) + a1 * (t * t) + a2 * t + a3),
);
};
return this._interpolate2D(src, dst, options, interpolateCubic);
},
hermiteInterpolation(src: any, dst: any, options?: any) {
const interpolateHermite = function (
x0: number,
x1: number,
x2: number,
x3: number,
t: number,
) {
const c0 = x1;
const c1 = 0.5 * (x2 - x0);
const c2 = x0 - 2.5 * x1 + 2 * x2 - 0.5 * x3;
const c3 = 0.5 * (x3 - x0) + 1.5 * (x1 - x2);
return Math.max(
0,
Math.min(255, Math.round(((c3 * t + c2) * t + c1) * t + c0)),
);
};
return this._interpolate2D(src, dst, options, interpolateHermite);
},
bezierInterpolation(src: any, dst: any, options?: any) {
// between 2 points y(n), y(n+1), use next points out, y(n-1), y(n+2)
// to predict control points (a & b) to be placed at n+0.5
// ya(n) = y(n) + (y(n+1)-y(n-1))/4
// yb(n) = y(n+1) - (y(n+2)-y(n))/4
// then use std bezier to interpolate [n,n+1)
// y(n+t) = y(n)*(1-t)^3 + 3 * ya(n)*(1-t)^2*t + 3 * yb(n)*(1-t)*t^2 + y(n+1)*t^3
// note the 3* factor for the two control points
// for edge cases, can choose:
// y(-1) = y(0) - 2*(y(1)-y(0))
// y(w) = y(w-1) + 2*(y(w-1)-y(w-2))
// but can go with y(-1) = y(0) and y(w) = y(w-1)
const interpolateBezier = function (
x0: number,
x1: number,
x2: number,
x3: number,
t: number,
) {
// x1, x2 are the knots, use x0 and x3 to calculate control points
const cp1 = x1 + (x2 - x0) / 4;
const cp2 = x2 - (x3 - x1) / 4;
const nt = 1 - t;
const c0 = x1 * nt * nt * nt;
const c1 = 3 * cp1 * nt * nt * t;
const c2 = 3 * cp2 * nt * t * t;
const c3 = x2 * t * t * t;
return Math.max(0, Math.min(255, Math.round(c0 + c1 + c2 + c3)));
};
return this._interpolate2D(src, dst, options, interpolateBezier);
},
};
+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;