61 lines
1.9 KiB
JavaScript
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;
|
|
};
|