Test/node_modules/pica/lib/stepper.js
2026-04-09 22:54:00 +07:00

61 lines
1.9 KiB
JavaScript

// Add intermediate resizing steps when scaling down by a very large factor.
//
// For example, when resizing 10000x10000 down to 10x10, it'll resize it to
// 300x300 first.
//
// It's needed because tiler has issues when the entire tile is scaled down
// to a few pixels (1024px source tile with border size 3 should result in
// at least 3+3+2 = 8px target tile, so max scale factor is 128 here).
//
// Also, adding intermediate steps can speed up processing if we use lower
// quality algorithms for first stages.
//
'use strict';
// min size = 0 results in infinite loop,
// min size = 1 can consume large amount of memory
const MIN_INNER_TILE_SIZE = 2;
module.exports = function createStages(fromWidth, fromHeight, toWidth, toHeight, srcTileSize, destTileBorder) {
let scaleX = toWidth / fromWidth;
let scaleY = toHeight / fromHeight;
// derived from createRegions equation:
// innerTileWidth = pixelFloor(srcTileSize * scaleX) - 2 * destTileBorder;
let minScale = (2 * destTileBorder + MIN_INNER_TILE_SIZE + 1) / srcTileSize;
// refuse to scale image multiple times by less than twice each time,
// it could only happen because of invalid options
if (minScale > 0.5) return [ [ toWidth, toHeight ] ];
let stageCount = Math.ceil(Math.log(Math.min(scaleX, scaleY)) / Math.log(minScale));
// no additional resizes are necessary,
// stageCount can be zero or be negative when enlarging the image
if (stageCount <= 1) return [ [ toWidth, toHeight ] ];
let result = [];
for (let i = 0; i < stageCount; i++) {
let width = Math.round(
Math.pow(
Math.pow(fromWidth, stageCount - i - 1) * Math.pow(toWidth, i + 1),
1 / stageCount
)
);
let height = Math.round(
Math.pow(
Math.pow(fromHeight, stageCount - i - 1) * Math.pow(toHeight, i + 1),
1 / stageCount
)
);
result.push([ width, height ]);
}
return result;
};