Path: blob/master/node_modules/@jimp/plugin-crop/dist/index.js
1126 views
"use strict";12var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");34Object.defineProperty(exports, "__esModule", {5value: true6});7exports["default"] = pluginCrop;89var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));1011var _utils = require("@jimp/utils");1213/* eslint-disable no-labels */14function pluginCrop(event) {15/**16* Crops the image at a given point to a give size17* @param {number} x the x coordinate to crop form18* @param {number} y the y coordinate to crop form19* @param w the width of the crop region20* @param h the height of the crop region21* @param {function(Error, Jimp)} cb (optional) a callback for when complete22* @returns {Jimp} this for chaining of methods23*/24event('crop', function (x, y, w, h, cb) {25if (typeof x !== 'number' || typeof y !== 'number') return _utils.throwError.call(this, 'x and y must be numbers', cb);26if (typeof w !== 'number' || typeof h !== 'number') return _utils.throwError.call(this, 'w and h must be numbers', cb); // round input2728x = Math.round(x);29y = Math.round(y);30w = Math.round(w);31h = Math.round(h);3233if (x === 0 && w === this.bitmap.width) {34// shortcut35var start = w * y + x << 2;36var end = start + h * w << 2;37this.bitmap.data = this.bitmap.data.slice(start, end);38} else {39var bitmap = Buffer.allocUnsafe(w * h * 4);40var offset = 0;41this.scanQuiet(x, y, w, h, function (x, y, idx) {42var data = this.bitmap.data.readUInt32BE(idx, true);43bitmap.writeUInt32BE(data, offset, true);44offset += 4;45});46this.bitmap.data = bitmap;47}4849this.bitmap.width = w;50this.bitmap.height = h;5152if ((0, _utils.isNodePattern)(cb)) {53cb.call(this, null, this);54}5556return this;57});58return {59"class": {60/**61* Autocrop same color borders from this image62* @param {number} tolerance (optional): a percent value of tolerance for pixels color difference (default: 0.0002%)63* @param {boolean} cropOnlyFrames (optional): flag to crop only real frames: all 4 sides of the image must have some border (default: true)64* @param {function(Error, Jimp)} cb (optional): a callback for when complete (default: no callback)65* @returns {Jimp} this for chaining of methods66*/67autocrop: function autocrop() {68var w = this.bitmap.width;69var h = this.bitmap.height;70var minPixelsPerSide = 1; // to avoid cropping completely the image, resulting in an invalid 0 sized image7172var cb; // callback7374var leaveBorder = 0; // Amount of pixels in border to leave7576var tolerance = 0.0002; // percent of color difference tolerance (default value)7778var cropOnlyFrames = true; // flag to force cropping only if the image has a real "frame"79// i.e. all 4 sides have some border (default value)8081var cropSymmetric = false; // flag to force cropping top be symmetric.82// i.e. north and south / east and west are cropped by the same value8384var ignoreSides = {85north: false,86south: false,87east: false,88west: false89}; // parse arguments9091for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {92args[_key] = arguments[_key];93}9495for (var a = 0, len = args.length; a < len; a++) {96if (typeof args[a] === 'number') {97// tolerance value passed98tolerance = args[a];99}100101if (typeof args[a] === 'boolean') {102// cropOnlyFrames value passed103cropOnlyFrames = args[a];104}105106if (typeof args[a] === 'function') {107// callback value passed108cb = args[a];109}110111if ((0, _typeof2["default"])(args[a]) === 'object') {112// config object passed113var config = args[a];114115if (typeof config.tolerance !== 'undefined') {116tolerance = config.tolerance;117}118119if (typeof config.cropOnlyFrames !== 'undefined') {120cropOnlyFrames = config.cropOnlyFrames;121}122123if (typeof config.cropSymmetric !== 'undefined') {124cropSymmetric = config.cropSymmetric;125}126127if (typeof config.leaveBorder !== 'undefined') {128leaveBorder = config.leaveBorder;129}130131if (typeof config.ignoreSides !== 'undefined') {132ignoreSides = config.ignoreSides;133}134}135}136/**137* All borders must be of the same color as the top left pixel, to be cropped.138* It should be possible to crop borders each with a different color,139* but since there are many ways for corners to intersect, it would140* introduce unnecessary complexity to the algorithm.141*/142// scan each side for same color borders143144145var colorTarget = this.getPixelColor(0, 0); // top left pixel color is the target color146147var rgba1 = this.constructor.intToRGBA(colorTarget); // for north and east sides148149var northPixelsToCrop = 0;150var eastPixelsToCrop = 0;151var southPixelsToCrop = 0;152var westPixelsToCrop = 0; // north side (scan rows from north to south)153154colorTarget = this.getPixelColor(0, 0);155156if (!ignoreSides.north) {157north: for (var y = 0; y < h - minPixelsPerSide; y++) {158for (var x = 0; x < w; x++) {159var colorXY = this.getPixelColor(x, y);160var rgba2 = this.constructor.intToRGBA(colorXY);161162if (this.constructor.colorDiff(rgba1, rgba2) > tolerance) {163// this pixel is too distant from the first one: abort this side scan164break north;165}166} // this row contains all pixels with the same color: increment this side pixels to crop167168169northPixelsToCrop++;170}171} // east side (scan columns from east to west)172173174colorTarget = this.getPixelColor(w, 0);175176if (!ignoreSides.east) {177east: for (var _x = 0; _x < w - minPixelsPerSide; _x++) {178for (var _y = 0 + northPixelsToCrop; _y < h; _y++) {179var _colorXY = this.getPixelColor(_x, _y);180181var _rgba = this.constructor.intToRGBA(_colorXY);182183if (this.constructor.colorDiff(rgba1, _rgba) > tolerance) {184// this pixel is too distant from the first one: abort this side scan185break east;186}187} // this column contains all pixels with the same color: increment this side pixels to crop188189190eastPixelsToCrop++;191}192} // south side (scan rows from south to north)193194195colorTarget = this.getPixelColor(0, h);196197if (!ignoreSides.south) {198south: for (var _y2 = h - 1; _y2 >= northPixelsToCrop + minPixelsPerSide; _y2--) {199for (var _x2 = w - eastPixelsToCrop - 1; _x2 >= 0; _x2--) {200var _colorXY2 = this.getPixelColor(_x2, _y2);201202var _rgba2 = this.constructor.intToRGBA(_colorXY2);203204if (this.constructor.colorDiff(rgba1, _rgba2) > tolerance) {205// this pixel is too distant from the first one: abort this side scan206break south;207}208} // this row contains all pixels with the same color: increment this side pixels to crop209210211southPixelsToCrop++;212}213} // west side (scan columns from west to east)214215216colorTarget = this.getPixelColor(w, h);217218if (!ignoreSides.west) {219west: for (var _x3 = w - 1; _x3 >= 0 + eastPixelsToCrop + minPixelsPerSide; _x3--) {220for (var _y3 = h - 1; _y3 >= 0 + northPixelsToCrop; _y3--) {221var _colorXY3 = this.getPixelColor(_x3, _y3);222223var _rgba3 = this.constructor.intToRGBA(_colorXY3);224225if (this.constructor.colorDiff(rgba1, _rgba3) > tolerance) {226// this pixel is too distant from the first one: abort this side scan227break west;228}229} // this column contains all pixels with the same color: increment this side pixels to crop230231232westPixelsToCrop++;233}234} // decide if a crop is needed235236237var doCrop = false; // apply leaveBorder238239westPixelsToCrop -= leaveBorder;240eastPixelsToCrop -= leaveBorder;241northPixelsToCrop -= leaveBorder;242southPixelsToCrop -= leaveBorder;243244if (cropSymmetric) {245var horizontal = Math.min(eastPixelsToCrop, westPixelsToCrop);246var vertical = Math.min(northPixelsToCrop, southPixelsToCrop);247westPixelsToCrop = horizontal;248eastPixelsToCrop = horizontal;249northPixelsToCrop = vertical;250southPixelsToCrop = vertical;251} // make sure that crops are >= 0252253254westPixelsToCrop = westPixelsToCrop >= 0 ? westPixelsToCrop : 0;255eastPixelsToCrop = eastPixelsToCrop >= 0 ? eastPixelsToCrop : 0;256northPixelsToCrop = northPixelsToCrop >= 0 ? northPixelsToCrop : 0;257southPixelsToCrop = southPixelsToCrop >= 0 ? southPixelsToCrop : 0; // safety checks258259var widthOfRemainingPixels = w - (westPixelsToCrop + eastPixelsToCrop);260var heightOfRemainingPixels = h - (southPixelsToCrop + northPixelsToCrop);261262if (cropOnlyFrames) {263// crop image if all sides should be cropped264doCrop = eastPixelsToCrop !== 0 && northPixelsToCrop !== 0 && westPixelsToCrop !== 0 && southPixelsToCrop !== 0;265} else {266// crop image if at least one side should be cropped267doCrop = eastPixelsToCrop !== 0 || northPixelsToCrop !== 0 || westPixelsToCrop !== 0 || southPixelsToCrop !== 0;268}269270if (doCrop) {271// do the real crop272this.crop(eastPixelsToCrop, northPixelsToCrop, widthOfRemainingPixels, heightOfRemainingPixels);273}274275if ((0, _utils.isNodePattern)(cb)) {276cb.call(this, null, this);277}278279return this;280}281}282};283}284285module.exports = exports.default;286//# sourceMappingURL=index.js.map287288