Skip to content

Commit

Permalink
so close
Browse files Browse the repository at this point in the history
  • Loading branch information
hipstersmoothie committed Mar 16, 2024
1 parent 296a776 commit 296d4b2
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 9 deletions.
8 changes: 4 additions & 4 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ export type JimpFormatArray<T> =

export type JimpFormatMime<T> = T extends Format<infer M> ? M : never;

export type JimpMethod<Args extends any[] = any[]> = (
img: Jimp,
...args: Args
) => Jimp;
export type JimpMethod<
Args extends any[] = any[],
J extends JimpClass = JimpClass,
> = (img: J, ...args: Args) => J;

type JimpInstanceMethod<M, T> =
T extends JimpMethod<infer Args>
Expand Down
1 change: 1 addition & 0 deletions packages/jimp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"author": "Andrew Lisowski <lisowski54@gmail.com>",
"license": "MIT",
"dependencies": {
"@jimp/plugin-blit": "workspace:*",
"@jimp/plugin-crop": "workspace:*",
"@jimp/js-png": "workspace:*",
"@jimp/core": "workspace:*"
Expand Down
20 changes: 19 additions & 1 deletion packages/jimp/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,33 @@ import { Jimp } from "./index.js";
// });

async function run() {
const image = new Jimp();
const imageBuffer = await fs.readFile(
path.join(__dirname, "../../../../images/GIgFDCFbAAA0zlg.png"),
);

const image = new Jimp();
await image.fromBuffer(imageBuffer);

const image2 = new Jimp();
await image2.fromBuffer(imageBuffer);

// works
image.blit({
src: image2,
x: 100,
y: 100,
});

// works
image.crop(100, 100, 150, 100);

// doesn't work
image.crop(100, 100, 150, 100).blit({
src: image2,
x: 100,
y: 100,
});

const outputBuffer = await image.toBuffer("image/png");
const outPath = path.join(__dirname, "./out.png");

Expand Down
3 changes: 2 additions & 1 deletion packages/jimp/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Jimp as JimpCustom } from "@jimp/core";

import crop from "@jimp/plugin-crop";
import blit from "@jimp/plugin-blit";

import png from "@jimp/js-png";

export const Jimp = JimpCustom.addFormat(png).plugin(crop);
export const Jimp = JimpCustom.addFormat(png).plugin(blit).plugin(crop);
14 changes: 12 additions & 2 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export function scan<I extends JimpClass>(
y: number,
w: number,
h: number,
cb: (image: I, x: number, y: number, idx: number) => any,
cb: (x: number, y: number, idx: number) => any,
) {
// round input
x = Math.round(x);
Expand All @@ -17,7 +17,7 @@ export function scan<I extends JimpClass>(
for (let _y = y; _y < y + h; _y++) {
for (let _x = x; _x < x + w; _x++) {
const idx = (image.bitmap.width * _y + _x) << 2;
cb(image, _x, _y, idx);
cb(_x, _y, idx);
}
}

Expand Down Expand Up @@ -108,3 +108,13 @@ export function colorDiff(rgba1: RGBAColor, rgba2: RGBAColor) {
maxVal
);
}

/**
* Limits a number to between 0 or 255
*/
export function limit255(n: number) {
n = Math.max(n, 0);
n = Math.min(n, 255);

return n;
}
47 changes: 47 additions & 0 deletions plugins/plugin-blit/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@jimp/plugin-blit",
"version": "1.0.0",
"repository": "jimp-dev/jimp",
"scripts": {
"lint": "eslint .",
"test": "vitest",
"build": "tshy",
"dev": "tshy --watch"
},
"author": "Andrew Lisowski <lisowski54@gmail.com>",
"license": "MIT",
"dependencies": {
"@jimp/utils": "workspace:*",
"@jimp/types": "workspace:*"
},
"devDependencies": {
"@jimp/config-eslint": "workspace:*",
"@jimp/config-typescript": "workspace:*",
"eslint": "^8.57.0",
"tshy": "^1.12.0",
"typescript": "^5.4.2",
"vitest": "^1.4.0"
},
"tshy": {
"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"
}
5 changes: 5 additions & 0 deletions plugins/plugin-blit/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { expect, test } from "vitest";

test("adds 1 + 2 to equal 3", () => {
expect(1 + 2).toBe(3);
});
97 changes: 97 additions & 0 deletions plugins/plugin-blit/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { JimpClass } from "@jimp/types";
import { limit255, scan } from "@jimp/utils";

/**
* Blits a source image on to this image
*/
function blit<I extends JimpClass>(
image: I,
{
src,
x = 0,
y = 0,
srcX = 0,
srcY = 0,
srcW = src.bitmap.width,
srcH = src.bitmap.height,
}: {
/** This image to blit on to the current image */
src: I;
/** the x position to blit the image */
x: number;
/** the y position to blit the image */
y: number;
/** the x position from which to crop the source image */
srcX?: number;
/** the y position from which to crop the source image */
srcY?: number;
/** the width to which to crop the source image */
srcW?: number;
/** the height to which to crop the source image */
srcH?: number;
},
) {
if (!("bitmap" in src)) {
throw new Error("The source must be a Jimp image");
}

if (typeof x !== "number" || typeof y !== "number") {
throw new Error("x and y must be numbers");
}

// round input
x = Math.round(x);
y = Math.round(y);

// round input
srcX = Math.round(srcX);
srcY = Math.round(srcY);
srcW = Math.round(srcW);
srcH = Math.round(srcH);

const maxWidth = image.bitmap.width;
const maxHeight = image.bitmap.height;

scan(src, srcX, srcY, srcW, srcH, function (sx, sy, idx) {
const xOffset = x + sx - srcX;
const yOffset = y + sy - srcY;

if (
xOffset >= 0 &&
yOffset >= 0 &&
maxWidth - xOffset > 0 &&
maxHeight - yOffset > 0
) {
const dstIdx = image.getPixelIndex(xOffset, yOffset);
const srcColor = {
r: src.bitmap.data[idx] || 0,
g: src.bitmap.data[idx + 1] || 0,
b: src.bitmap.data[idx + 2] || 0,
a: src.bitmap.data[idx + 3] || 0,
};

const dst = {
r: image.bitmap.data[dstIdx] || 0,
g: image.bitmap.data[dstIdx + 1] || 0,
b: image.bitmap.data[dstIdx + 2] || 0,
a: image.bitmap.data[dstIdx + 3] || 0,
};

image.bitmap.data[dstIdx] =
((srcColor.a * (srcColor.r - dst.r) - dst.r + 255) >> 8) + dst.r;
image.bitmap.data[dstIdx + 1] =
((srcColor.a * (srcColor.g - dst.g) - dst.g + 255) >> 8) + dst.g;
image.bitmap.data[dstIdx + 2] =
((srcColor.a * (srcColor.b - dst.b) - dst.b + 255) >> 8) + dst.b;
image.bitmap.data[dstIdx + 3] = limit255(dst.a + srcColor.a);
}
});

return image;
}

export default function blitPlugin() {
return {
blit,
};
}
8 changes: 8 additions & 0 deletions plugins/plugin-blit/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "@jimp/config-typescript/base.json",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
2 changes: 1 addition & 1 deletion plugins/plugin-crop/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function crop<I extends JimpClass>(
const bitmap = Buffer.allocUnsafe(w * h * 4);
let offset = 0;

scan(image, x, y, w, h, function (i, x, y, idx) {
scan(image, x, y, w, h, function (x, y, idx) {
const data = image.bitmap.data.readUInt32BE(idx);
bitmap.writeUInt32BE(data, offset);
offset += 4;
Expand Down
31 changes: 31 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 296d4b2

Please sign in to comment.