UNPKG

s2-tools

Version:

A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.

126 lines 4.9 kB
/* eslint-disable no-var */ import sharp from 'sharp'; /** Build a local ImageBitmap for reading the data */ class ImageBitmap { data; width; height; /** * @param data - the image data * @param width - the image width * @param height - the image height */ constructor(data, width, height) { this.data = data; this.width = width; this.height = height; } } /** * @param blob - the blob input data * @returns an ImageBitmap */ async function createImageBitmap(blob) { const imageBuffer = Buffer.from(await blob.arrayBuffer()); // Decode image using sharp const decodedImage = await sharp(imageBuffer).raw().toBuffer({ resolveWithObject: true }); const { data, info: { width, height }, } = decodedImage; return new ImageBitmap(new Uint8Array(data), width, height); } /** An offscreen canvas polyfill */ class OffscreenCanvasPolyfill { width; height; /** * @param width - the canvas width * @param height - the canvas height */ constructor(width, height) { this.width = width; this.height = height; } /** * @param type - expect '2d' or throw null * @returns the OffscreenCanvasRenderingContext2D */ getContext(type) { if (type !== '2d') return null; return new OffscreenCanvasRenderingContext2D(this.width, this.height); } } /** An offscreen canvas rendering context polyfill */ class OffscreenCanvasRenderingContext2D { width; height; data = new Uint8ClampedArray(); /** * @param width - the canvas width * @param height - the canvas height */ constructor(width, height) { this.width = width; this.height = height; } /** * Draw an ImageBitmap onto the canvas at position (dx, dy). * Copies the pixel data from the ImageBitmap to the canvas buffer. * @param image - the image to draw * @param dx - the x position on the canvas * @param dy - the y position on the canvas */ drawImage(image, dx, dy) { const { width: imgWidth, height: imgHeight, data: imgData } = image; const channels = imgData.length / (imgWidth * imgHeight); this.data = new Uint8ClampedArray(imgWidth * imgHeight * channels); for (let y = 0; y < imgHeight; y++) { for (let x = 0; x < imgWidth; x++) { const imgIndex = (y * imgWidth + x) * channels; // Index in the image data (RGBA) const canvasX = dx + x; const canvasY = dy + y; if (canvasX >= 0 && canvasX < this.width && canvasY >= 0 && canvasY < this.height) { const canvasIndex = (canvasY * this.width + canvasX) * channels; // Index in the canvas data // Copy RGBA values from the image to the canvas this.data[canvasIndex] = imgData[imgIndex]; // R this.data[canvasIndex + 1] = imgData[imgIndex + 1]; // G this.data[canvasIndex + 2] = imgData[imgIndex + 2]; // B if (channels === 4) this.data[canvasIndex + 3] = imgData[imgIndex + 3]; // A } } } } /** * Get the ImageData for a specific region of the canvas. * @param x - The x coordinate of the region's top-left corner * @param y - The y coordinate of the region's top-left corner * @param width - The width of the region * @param height - The height of the region * @returns the ImageData */ getImageData(x, y, width, height) { const channels = this.data.length / (this.width * this.height); const size = width * height * channels; if (this.data.length === size) return { data: this.data.slice(0, size), width, height }; const imageData = new Uint8ClampedArray(size); for (let row = 0; row < height; row++) { for (let col = 0; col < width; col++) { const canvasX = x + col; const canvasY = y + row; const canvasIndex = (canvasY * this.width + canvasX) * channels; const imageDataIndex = (row * width + col) * channels; // Copy RGBA values from the canvas to the imageData imageData[imageDataIndex] = this.data[canvasIndex]; // R imageData[imageDataIndex + 1] = this.data[canvasIndex + 1]; // G imageData[imageDataIndex + 2] = this.data[canvasIndex + 2]; // B if (channels === 4) imageData[imageDataIndex + 3] = this.data[canvasIndex + 3]; // A } } return { data: imageData, width, height }; } } globalThis.createImageBitmap ??= createImageBitmap; globalThis.OffscreenCanvas ??= OffscreenCanvasPolyfill; //# sourceMappingURL=image.js.map