one
Version:
One is a React framework for web, iOS, and Android apps.
70 lines (67 loc) • 3.57 kB
JavaScript
import { missingNativeBuild } from "../nativeError.mjs";
function pixels(value, zero = false) {
if (!Number.isInteger(value) || value < (zero ? 0 : 1) || value > 1e5) throw new Error("ImageManipulator.transform: expected a whole pixel count");
return value;
}
function size(width, height) {
if (width > 1e4 || height > 1e4 || width * height > 25e6) throw new Error("ImageManipulator.transform: output is limited to 25 megapixels and 10,000 pixels per side");
}
async function transform(uri, options = {}) {
if (typeof window === "undefined") throw missingNativeBuild("ImageManipulator.transform");
const { crop, resize, rotate = 0, flip, format = "jpeg", quality } = options;
if (![
"jpeg",
"png",
"webp"
].includes(format) || ![
0,
90,
180,
270
].includes(rotate)) throw new Error("ImageManipulator.transform: invalid format or rotation");
if (flip != null && flip !== "horizontal" && flip !== "vertical") throw new Error("ImageManipulator.transform: flip must be 'horizontal' or 'vertical'");
if (format === "png" && quality != null || quality != null && (!Number.isFinite(quality) || quality < 0 || quality > 1)) throw new Error("ImageManipulator.transform: quality applies only to JPEG or WebP and must be between 0 and 1");
const image = new window.Image();
image.crossOrigin = "anonymous";
image.src = uri;
await image.decode();
const x = pixels(crop?.x ?? 0, true), y = pixels(crop?.y ?? 0, true);
const cw = pixels(crop?.width ?? image.naturalWidth), ch = pixels(crop?.height ?? image.naturalHeight);
if (x + cw > image.naturalWidth || y + ch > image.naturalHeight) throw new Error("ImageManipulator.transform: crop must fit inside the source image");
if (resize && resize.width == null && resize.height == null) throw new Error("ImageManipulator.transform: resize needs a width or height");
let width = resize?.width == null ? cw : pixels(resize.width);
let height = resize?.height == null ? ch : pixels(resize.height);
if (resize?.width == null && resize?.height != null) width = Math.max(1, Math.round(cw * height / ch));
if (resize?.height == null && resize?.width != null) height = Math.max(1, Math.round(ch * width / cw));
size(width, height);
const canvas = document.createElement("canvas");
canvas.width = rotate === 90 || rotate === 270 ? height : width;
canvas.height = rotate === 90 || rotate === 270 ? width : height;
const context = canvas.getContext("2d");
if (!context) throw new Error("ImageManipulator.transform: canvas is unavailable");
context.translate(canvas.width / 2, canvas.height / 2);
if (flip === "horizontal") context.scale(-1, 1);
else if (flip === "vertical") context.scale(1, -1);
context.rotate(rotate * Math.PI / 180);
let source = image;
if (crop) {
const cropped = document.createElement("canvas");
cropped.width = cw;
cropped.height = ch;
const cropContext = cropped.getContext("2d");
if (!cropContext) throw new Error("ImageManipulator.transform: canvas is unavailable");
cropContext.drawImage(image, x, y, cw, ch, 0, 0, cw, ch);
source = cropped;
}
context.drawImage(source, -width / 2, -height / 2, width, height);
const blob = await new Promise((resolve, reject) => canvas.toBlob((value) => value ? resolve(value) : reject(new Error("ImageManipulator.transform: encoding failed")), `image/${format}`, quality ?? .9));
return {
uri: URL.createObjectURL(blob),
width: canvas.width,
height: canvas.height,
size: blob.size
};
}
const ImageManipulator = Object.freeze({ transform });
export { ImageManipulator };
//# sourceMappingURL=index.mjs.map