Path: blob/master/node_modules/@jimp/plugin-resize/dist/modules/resize2.js
1129 views
"use strict";12/**3* Copyright (c) 2015 Guyon Roche4*5* Permission is hereby granted, free of charge, to any person obtaining a copy6* of this software and associated documentation files (the "Software"), to deal7* in the Software without restriction, including without limitation the rights8* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell9* copies of the Software, and to permit persons to whom the Software is10* furnished to do so, subject to the following conditions:</p>11*12* The above copyright notice and this permission notice shall be included in13* all copies or substantial portions of the Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE18* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,20* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN21* THE SOFTWARE.22*/23module.exports = {24nearestNeighbor: function nearestNeighbor(src, dst) {25var wSrc = src.width;26var hSrc = src.height;27var wDst = dst.width;28var hDst = dst.height;29var bufSrc = src.data;30var bufDst = dst.data;3132for (var i = 0; i < hDst; i++) {33for (var j = 0; j < wDst; j++) {34var posDst = (i * wDst + j) * 4;35var iSrc = Math.floor(i * hSrc / hDst);36var jSrc = Math.floor(j * wSrc / wDst);37var posSrc = (iSrc * wSrc + jSrc) * 4;38bufDst[posDst++] = bufSrc[posSrc++];39bufDst[posDst++] = bufSrc[posSrc++];40bufDst[posDst++] = bufSrc[posSrc++];41bufDst[posDst++] = bufSrc[posSrc++];42}43}44},45bilinearInterpolation: function bilinearInterpolation(src, dst) {46var wSrc = src.width;47var hSrc = src.height;48var wDst = dst.width;49var hDst = dst.height;50var bufSrc = src.data;51var bufDst = dst.data;5253var interpolate = function interpolate(k, kMin, vMin, kMax, vMax) {54// special case - k is integer55if (kMin === kMax) {56return vMin;57}5859return Math.round((k - kMin) * vMax + (kMax - k) * vMin);60};6162var assign = function assign(pos, offset, x, xMin, xMax, y, yMin, yMax) {63var posMin = (yMin * wSrc + xMin) * 4 + offset;64var posMax = (yMin * wSrc + xMax) * 4 + offset;65var vMin = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]); // special case, y is integer6667if (yMax === yMin) {68bufDst[pos + offset] = vMin;69} else {70posMin = (yMax * wSrc + xMin) * 4 + offset;71posMax = (yMax * wSrc + xMax) * 4 + offset;72var vMax = interpolate(x, xMin, bufSrc[posMin], xMax, bufSrc[posMax]);73bufDst[pos + offset] = interpolate(y, yMin, vMin, yMax, vMax);74}75};7677for (var i = 0; i < hDst; i++) {78for (var j = 0; j < wDst; j++) {79var posDst = (i * wDst + j) * 4; // x & y in src coordinates8081var x = j * wSrc / wDst;82var xMin = Math.floor(x);83var xMax = Math.min(Math.ceil(x), wSrc - 1);84var y = i * hSrc / hDst;85var yMin = Math.floor(y);86var yMax = Math.min(Math.ceil(y), hSrc - 1);87assign(posDst, 0, x, xMin, xMax, y, yMin, yMax);88assign(posDst, 1, x, xMin, xMax, y, yMin, yMax);89assign(posDst, 2, x, xMin, xMax, y, yMin, yMax);90assign(posDst, 3, x, xMin, xMax, y, yMin, yMax);91}92}93},94_interpolate2D: function _interpolate2D(src, dst, options, interpolate) {95var bufSrc = src.data;96var bufDst = dst.data;97var wSrc = src.width;98var hSrc = src.height;99var wDst = dst.width;100var hDst = dst.height; // when dst smaller than src/2, interpolate first to a multiple between 0.5 and 1.0 src, then sum squares101102var wM = Math.max(1, Math.floor(wSrc / wDst));103var wDst2 = wDst * wM;104var hM = Math.max(1, Math.floor(hSrc / hDst));105var hDst2 = hDst * hM; // ===========================================================106// Pass 1 - interpolate rows107// buf1 has width of dst2 and height of src108109var buf1 = Buffer.alloc(wDst2 * hSrc * 4);110111for (var i = 0; i < hSrc; i++) {112for (var j = 0; j < wDst2; j++) {113// i in src coords, j in dst coords114// calculate x in src coords115// this interpolation requires 4 sample points and the two inner ones must be real116// the outer points can be fudged for the edges.117// therefore (wSrc-1)/wDst2118var x = j * (wSrc - 1) / wDst2;119var xPos = Math.floor(x);120var t = x - xPos;121var srcPos = (i * wSrc + xPos) * 4;122var buf1Pos = (i * wDst2 + j) * 4;123124for (var k = 0; k < 4; k++) {125var kPos = srcPos + k;126var x0 = xPos > 0 ? bufSrc[kPos - 4] : 2 * bufSrc[kPos] - bufSrc[kPos + 4];127var x1 = bufSrc[kPos];128var x2 = bufSrc[kPos + 4];129var x3 = xPos < wSrc - 2 ? bufSrc[kPos + 8] : 2 * bufSrc[kPos + 4] - bufSrc[kPos];130buf1[buf1Pos + k] = interpolate(x0, x1, x2, x3, t);131}132}133} // this._writeFile(wDst2, hSrc, buf1, "out/buf1.jpg");134// ===========================================================135// Pass 2 - interpolate columns136// buf2 has width and height of dst2137138139var buf2 = Buffer.alloc(wDst2 * hDst2 * 4);140141for (var _i = 0; _i < hDst2; _i++) {142for (var _j = 0; _j < wDst2; _j++) {143// i&j in dst2 coords144// calculate y in buf1 coords145// this interpolation requires 4 sample points and the two inner ones must be real146// the outer points can be fudged for the edges.147// therefore (hSrc-1)/hDst2148var y = _i * (hSrc - 1) / hDst2;149var yPos = Math.floor(y);150151var _t = y - yPos;152153var _buf1Pos = (yPos * wDst2 + _j) * 4;154155var buf2Pos = (_i * wDst2 + _j) * 4;156157for (var _k = 0; _k < 4; _k++) {158var _kPos = _buf1Pos + _k;159160var y0 = yPos > 0 ? buf1[_kPos - wDst2 * 4] : 2 * buf1[_kPos] - buf1[_kPos + wDst2 * 4];161var y1 = buf1[_kPos];162var y2 = buf1[_kPos + wDst2 * 4];163var y3 = yPos < hSrc - 2 ? buf1[_kPos + wDst2 * 8] : 2 * buf1[_kPos + wDst2 * 4] - buf1[_kPos];164buf2[buf2Pos + _k] = interpolate(y0, y1, y2, y3, _t);165}166}167} // this._writeFile(wDst2, hDst2, buf2, "out/buf2.jpg");168// ===========================================================169// Pass 3 - scale to dst170171172var m = wM * hM;173174if (m > 1) {175for (var _i2 = 0; _i2 < hDst; _i2++) {176for (var _j2 = 0; _j2 < wDst; _j2++) {177// i&j in dst bounded coords178var r = 0;179var g = 0;180var b = 0;181var a = 0;182var realColors = 0;183184for (var _y = 0; _y < hM; _y++) {185var _yPos = _i2 * hM + _y;186187for (var _x = 0; _x < wM; _x++) {188var _xPos = _j2 * wM + _x;189190var xyPos = (_yPos * wDst2 + _xPos) * 4;191var pixelAlpha = buf2[xyPos + 3];192193if (pixelAlpha) {194r += buf2[xyPos];195g += buf2[xyPos + 1];196b += buf2[xyPos + 2];197realColors++;198}199200a += pixelAlpha;201}202}203204var pos = (_i2 * wDst + _j2) * 4;205bufDst[pos] = realColors ? Math.round(r / realColors) : 0;206bufDst[pos + 1] = realColors ? Math.round(g / realColors) : 0;207bufDst[pos + 2] = realColors ? Math.round(b / realColors) : 0;208bufDst[pos + 3] = Math.round(a / m);209}210}211} else {212// replace dst buffer with buf2213dst.data = buf2;214}215},216bicubicInterpolation: function bicubicInterpolation(src, dst, options) {217var interpolateCubic = function interpolateCubic(x0, x1, x2, x3, t) {218var a0 = x3 - x2 - x0 + x1;219var a1 = x0 - x1 - a0;220var a2 = x2 - x0;221var a3 = x1;222return Math.max(0, Math.min(255, a0 * (t * t * t) + a1 * (t * t) + a2 * t + a3));223};224225return this._interpolate2D(src, dst, options, interpolateCubic);226},227hermiteInterpolation: function hermiteInterpolation(src, dst, options) {228var interpolateHermite = function interpolateHermite(x0, x1, x2, x3, t) {229var c0 = x1;230var c1 = 0.5 * (x2 - x0);231var c2 = x0 - 2.5 * x1 + 2 * x2 - 0.5 * x3;232var c3 = 0.5 * (x3 - x0) + 1.5 * (x1 - x2);233return Math.max(0, Math.min(255, Math.round(((c3 * t + c2) * t + c1) * t + c0)));234};235236return this._interpolate2D(src, dst, options, interpolateHermite);237},238bezierInterpolation: function bezierInterpolation(src, dst, options) {239// between 2 points y(n), y(n+1), use next points out, y(n-1), y(n+2)240// to predict control points (a & b) to be placed at n+0.5241// ya(n) = y(n) + (y(n+1)-y(n-1))/4242// yb(n) = y(n+1) - (y(n+2)-y(n))/4243// then use std bezier to interpolate [n,n+1)244// 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^3245// note the 3* factor for the two control points246// for edge cases, can choose:247// y(-1) = y(0) - 2*(y(1)-y(0))248// y(w) = y(w-1) + 2*(y(w-1)-y(w-2))249// but can go with y(-1) = y(0) and y(w) = y(w-1)250var interpolateBezier = function interpolateBezier(x0, x1, x2, x3, t) {251// x1, x2 are the knots, use x0 and x3 to calculate control points252var cp1 = x1 + (x2 - x0) / 4;253var cp2 = x2 - (x3 - x1) / 4;254var nt = 1 - t;255var c0 = x1 * nt * nt * nt;256var c1 = 3 * cp1 * nt * nt * t;257var c2 = 3 * cp2 * nt * t * t;258var c3 = x2 * t * t * t;259return Math.max(0, Math.min(255, Math.round(c0 + c1 + c2 + c3)));260};261262return this._interpolate2D(src, dst, options, interpolateBezier);263}264};265//# sourceMappingURL=resize2.js.map266267