From ea34d22d9be8af417f2ddb2102b1984d3b40215c Mon Sep 17 00:00:00 2001 From: Andrew Lisowski Date: Sun, 5 Aug 2018 00:48:45 -0700 Subject: [PATCH] rotate faster --- src/image-manipulation/shape.js | 61 ++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/image-manipulation/shape.js b/src/image-manipulation/shape.js index 66c3d66cc..c40e9da50 100644 --- a/src/image-manipulation/shape.js +++ b/src/image-manipulation/shape.js @@ -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; - this.bitmap.data = Buffer.from(dstBuffer); + const srcBuffer = this.bitmap.data; + const len = srcBuffer.length; + const dstBuffer = Buffer.allocUnsafe(len); - const tmp = this.bitmap.width; + let tmp; + + 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; } /**