Skip to content

Commit

Permalink
Performance improvements (#512)
Browse files Browse the repository at this point in the history
  • Loading branch information
hipstersmoothie authored and edi9999 committed Aug 5, 2018
1 parent dc54d71 commit e4a629d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 44 deletions.
66 changes: 46 additions & 20 deletions src/image-manipulation/shape.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,57 @@ import Resize2 from '../modules/resize2';
import { isNodePattern, throwError } from '../utils/error-checking';
import * as constants from '../constants';

function rotate90degrees(bitmap, dstBuffer, clockwise) {
const dstOffsetStep = clockwise ? -4 : 4;
let dstOffset = clockwise ? dstBuffer.length - 4 : 0;

let tmp;
let x;
let y;
let srcOffset;

for (x = 0; x < bitmap.width; x++) {
for (y = bitmap.height - 1; y >= 0; y--) {
srcOffset = (bitmap.width * y + x) << 2;
tmp = bitmap.data.readUInt32BE(srcOffset, true);
dstBuffer.writeUInt32BE(tmp, dstOffset, true);
dstOffset += dstOffsetStep;
}
}
}

/**
* Rotates an image clockwise by a number of degrees rounded to the nearest 90 degrees. NB: 'this' must be a Jimp object.
* @param {number} deg the number of degrees to rotate the image by
*/
function simpleRotate(deg) {
let i = Math.round(deg / 90) % 4;
while (i < 0) i += 4;

while (i > 0) {
// https://github.com/ekulabuhov/jimp/commit/9a0c7cff88292d88c32a424b11256c76f1e20e46
const dstBuffer = Buffer.alloc(this.bitmap.data.length);
let dstOffset = 0;

for (let x = this.bitmap.width - 1; x >= 0; x--) {
for (let y = 0; y < this.bitmap.height; y++) {
const srcOffset = (this.bitmap.width * y + x) << 2;
const data = this.bitmap.data.readUInt32BE(srcOffset);
dstBuffer.writeUInt32BE(data, dstOffset);
dstOffset += 4;
}
}
let steps = Math.round(deg / 90) % 4;
steps += steps < 0 ? 4 : 0;

if (steps === 0) return;

const srcBuffer = this.bitmap.data;
const len = srcBuffer.length;
const dstBuffer = Buffer.allocUnsafe(len);

this.bitmap.data = Buffer.from(dstBuffer);
let tmp;

const tmp = this.bitmap.width;
if (steps === 2) {
// Upside-down
for (let srcOffset = 0; srcOffset < len; srcOffset += 4) {
tmp = srcBuffer.readUInt32BE(srcOffset, true);
dstBuffer.writeUInt32BE(tmp, len - srcOffset - 4, true);
}
} else {
// Clockwise or counter-clockwise rotation by 90 degree
rotate90degrees(this.bitmap, dstBuffer, steps === 1);

tmp = this.bitmap.width;
this.bitmap.width = this.bitmap.height;
this.bitmap.height = tmp;

i--;
}

this.bitmap.data = dstBuffer;
}

/**
Expand Down Expand Up @@ -208,6 +229,11 @@ function flipFn(horizontal, vertical, cb) {
cb
);

if (horizontal && vertical) {
// shortcut
return this.rotate(180, true, cb);
}

const bitmap = Buffer.alloc(this.bitmap.data.length);
this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
x,
Expand Down
12 changes: 9 additions & 3 deletions src/image-manipulation/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,15 @@ function xOffsetBasedOnAlignment(font, line, maxWidth, alignment) {

function drawCharacter(image, font, x, y, char) {
if (char.width > 0 && char.height > 0) {
const imageChar = font.pages[char.page]
.cloneQuiet()
.crop(char.x, char.y, char.width, char.height);
let imageChar = char.image;

if (!imageChar) {
imageChar = font.pages[char.page]
.cloneQuiet()
.crop(char.x, char.y, char.width, char.height);
char.image = imageChar;
}

return image.composite(imageChar, x + char.xoffset, y + char.yoffset);
}

Expand Down
39 changes: 18 additions & 21 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,20 +235,8 @@ class Jimp extends EventEmitter {
return throwError.call(this, 'cb must be a function', finish);
}

const bitmap = Buffer.alloc(original.bitmap.data.length);
original.scanQuiet(
0,
0,
original.bitmap.width,
original.bitmap.height,
(x, y, idx) => {
const data = original.bitmap.data.readUInt32BE(idx);
bitmap.writeUInt32BE(data, idx);
}
);

this.bitmap = {
data: bitmap,
data: Buffer.from(original.bitmap.data),
width: original.bitmap.width,
height: original.bitmap.height
};
Expand Down Expand Up @@ -1280,16 +1268,25 @@ jimpEvChange('crop', function(x, y, w, h, cb) {
w = Math.round(w);
h = Math.round(h);

const bitmap = Buffer.alloc(this.bitmap.data.length);
let offset = 0;
if (x === 0 && w === this.bitmap.width) {
// shortcut
const start = (w * y + x) << 2;
const end = (start + h * w) << (2 + 1);

this.scanQuiet(x, y, w, h, function(x, y, idx) {
const data = this.bitmap.data.readUInt32BE(idx);
bitmap.writeUInt32BE(data, offset);
offset += 4;
});
this.bitmap.data = this.bitmap.data.slice(start, end);
} else {
const bitmap = Buffer.allocUnsafe(w * h * 4);
let offset = 0;

this.scanQuiet(x, y, w, h, function(x, y, idx) {
const data = this.bitmap.data.readUInt32BE(idx, true);
bitmap.writeUInt32BE(data, offset, true);
offset += 4;
});

this.bitmap.data = bitmap;
}

this.bitmap.data = Buffer.from(bitmap);
this.bitmap.width = w;
this.bitmap.height = h;

Expand Down

0 comments on commit e4a629d

Please sign in to comment.