"use strict"; /** * @module resample */ Object.defineProperty(exports, "__esModule", { value: true }); exports.resampleInterleaved = exports.resampleBilinearInterleaved = exports.resampleNearestInterleaved = exports.resample = exports.resampleBilinear = exports.resampleNearest = void 0; function copyNewSize(array, width, height, samplesPerPixel = 1) { return new (Object.getPrototypeOf(array).constructor)(width * height * samplesPerPixel); } /** * Resample the input arrays using nearest neighbor value selection. * @param {TypedArray[]} valueArrays The input arrays to resample * @param {number} inWidth The width of the input rasters * @param {number} inHeight The height of the input rasters * @param {number} outWidth The desired width of the output rasters * @param {number} outHeight The desired height of the output rasters * @returns {TypedArray[]} The resampled rasters */ function resampleNearest(valueArrays, inWidth, inHeight, outWidth, outHeight) { const relX = inWidth / outWidth; const relY = inHeight / outHeight; return valueArrays.map((array) => { const newArray = copyNewSize(array, outWidth, outHeight); for (let y = 0; y < outHeight; ++y) { const cy = Math.min(Math.round(relY * y), inHeight - 1); for (let x = 0; x < outWidth; ++x) { const cx = Math.min(Math.round(relX * x), inWidth - 1); const value = array[(cy * inWidth) + cx]; newArray[(y * outWidth) + x] = value; } } return newArray; }); } exports.resampleNearest = resampleNearest; // simple linear interpolation, code from: // https://en.wikipedia.org/wiki/Linear_interpolation#Programming_language_support function lerp(v0, v1, t) { return ((1 - t) * v0) + (t * v1); } /** * Resample the input arrays using bilinear interpolation. * @param {TypedArray[]} valueArrays The input arrays to resample * @param {number} inWidth The width of the input rasters * @param {number} inHeight The height of the input rasters * @param {number} outWidth The desired width of the output rasters * @param {number} outHeight The desired height of the output rasters * @returns {TypedArray[]} The resampled rasters */ function resampleBilinear(valueArrays, inWidth, inHeight, outWidth, outHeight) { const relX = inWidth / outWidth; const relY = inHeight / outHeight; return valueArrays.map((array) => { const newArray = copyNewSize(array, outWidth, outHeight); for (let y = 0; y < outHeight; ++y) { const rawY = relY * y; const yl = Math.floor(rawY); const yh = Math.min(Math.ceil(rawY), (inHeight - 1)); for (let x = 0; x < outWidth; ++x) { const rawX = relX * x; const tx = rawX % 1; const xl = Math.floor(rawX); const xh = Math.min(Math.ceil(rawX), (inWidth - 1)); const ll = array[(yl * inWidth) + xl]; const hl = array[(yl * inWidth) + xh]; const lh = array[(yh * inWidth) + xl]; const hh = array[(yh * inWidth) + xh]; const value = lerp(lerp(ll, hl, tx), lerp(lh, hh, tx), rawY % 1); newArray[(y * outWidth) + x] = value; } } return newArray; }); } exports.resampleBilinear = resampleBilinear; /** * Resample the input arrays using the selected resampling method. * @param {TypedArray[]} valueArrays The input arrays to resample * @param {number} inWidth The width of the input rasters * @param {number} inHeight The height of the input rasters * @param {number} outWidth The desired width of the output rasters * @param {number} outHeight The desired height of the output rasters * @param {string} [method = 'nearest'] The desired resampling method * @returns {TypedArray[]} The resampled rasters */ function resample(valueArrays, inWidth, inHeight, outWidth, outHeight, method = 'nearest') { switch (method.toLowerCase()) { case 'nearest': return resampleNearest(valueArrays, inWidth, inHeight, outWidth, outHeight); case 'bilinear': case 'linear': return resampleBilinear(valueArrays, inWidth, inHeight, outWidth, outHeight); default: throw new Error(`Unsupported resampling method: '${method}'`); } } exports.resample = resample; /** * Resample the pixel interleaved input array using nearest neighbor value selection. * @param {TypedArray} valueArrays The input arrays to resample * @param {number} inWidth The width of the input rasters * @param {number} inHeight The height of the input rasters * @param {number} outWidth The desired width of the output rasters * @param {number} outHeight The desired height of the output rasters * @param {number} samples The number of samples per pixel for pixel * interleaved data * @returns {TypedArray} The resampled raster */ function resampleNearestInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples) { const relX = inWidth / outWidth; const relY = inHeight / outHeight; const newArray = copyNewSize(valueArray, outWidth, outHeight, samples); for (let y = 0; y < outHeight; ++y) { const cy = Math.min(Math.round(relY * y), inHeight - 1); for (let x = 0; x < outWidth; ++x) { const cx = Math.min(Math.round(relX * x), inWidth - 1); for (let i = 0; i < samples; ++i) { const value = valueArray[(cy * inWidth * samples) + (cx * samples) + i]; newArray[(y * outWidth * samples) + (x * samples) + i] = value; } } } return newArray; } exports.resampleNearestInterleaved = resampleNearestInterleaved; /** * Resample the pixel interleaved input array using bilinear interpolation. * @param {TypedArray} valueArrays The input arrays to resample * @param {number} inWidth The width of the input rasters * @param {number} inHeight The height of the input rasters * @param {number} outWidth The desired width of the output rasters * @param {number} outHeight The desired height of the output rasters * @param {number} samples The number of samples per pixel for pixel * interleaved data * @returns {TypedArray} The resampled raster */ function resampleBilinearInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples) { const relX = inWidth / outWidth; const relY = inHeight / outHeight; const newArray = copyNewSize(valueArray, outWidth, outHeight, samples); for (let y = 0; y < outHeight; ++y) { const rawY = relY * y; const yl = Math.floor(rawY); const yh = Math.min(Math.ceil(rawY), (inHeight - 1)); for (let x = 0; x < outWidth; ++x) { const rawX = relX * x; const tx = rawX % 1; const xl = Math.floor(rawX); const xh = Math.min(Math.ceil(rawX), (inWidth - 1)); for (let i = 0; i < samples; ++i) { const ll = valueArray[(yl * inWidth * samples) + (xl * samples) + i]; const hl = valueArray[(yl * inWidth * samples) + (xh * samples) + i]; const lh = valueArray[(yh * inWidth * samples) + (xl * samples) + i]; const hh = valueArray[(yh * inWidth * samples) + (xh * samples) + i]; const value = lerp(lerp(ll, hl, tx), lerp(lh, hh, tx), rawY % 1); newArray[(y * outWidth * samples) + (x * samples) + i] = value; } } } return newArray; } exports.resampleBilinearInterleaved = resampleBilinearInterleaved; /** * Resample the pixel interleaved input array using the selected resampling method. * @param {TypedArray} valueArray The input array to resample * @param {number} inWidth The width of the input rasters * @param {number} inHeight The height of the input rasters * @param {number} outWidth The desired width of the output rasters * @param {number} outHeight The desired height of the output rasters * @param {number} samples The number of samples per pixel for pixel * interleaved data * @param {string} [method = 'nearest'] The desired resampling method * @returns {TypedArray} The resampled rasters */ function resampleInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples, method = 'nearest') { switch (method.toLowerCase()) { case 'nearest': return resampleNearestInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples); case 'bilinear': case 'linear': return resampleBilinearInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples); default: throw new Error(`Unsupported resampling method: '${method}'`); } } exports.resampleInterleaved = resampleInterleaved; //# sourceMappingURL=resample.js.map