mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-14 23:32:20 +00:00
feat(weather): a host can supply decoded frames to the weather layers
A weather feed may also be a frame source. With an optional
getFrameImage({ product, time, size, bbox, signal }) the layers take
whole-extent images, detail windows and the global mosaic from it; with an
optional getFrameTile({ product, time, z, x, y, size, signal }) regional
tiles and their prefetch come from it, null being a transparent tile. Pixels
may be an ImageBitmap, ImageData, canvas or VideoFrame of exactly the
requested size; the layer draws them once and closes them. Cancellation
reaches the source, and a feed without these methods reads the image and
tile routes as before.
This commit is contained in:
1 parent
aff5ce7f17
commit
e18353f769
12 files changed
+1068
-31
No files matched your search
@@ -1,6 +1,11 @@
|
||||
import { readResponseBytesCapped } from '../../sources/httpBody.js';
|
||||
import { msg } from '../../i18n/index.js';
|
||||
import { weatherImageUrl } from './source.js';
|
||||
import {
|
||||
weatherImageUrl,
|
||||
weatherPixelSize,
|
||||
drawWeatherPixels,
|
||||
closeWeatherPixels,
|
||||
} from './source.js';
|
||||
import { infraredAlpha } from './infraredAlpha.js';
|
||||
|
||||
export const MAX_MOSAIC_BYTES = 4 * 1024 * 1024;
|
||||
@@ -20,10 +25,35 @@ export function processInfraredImage(
|
||||
if (flipY) context.setTransform(1, 0, 0, -1, 0, image.height);
|
||||
context.drawImage(image, 0, 0);
|
||||
if (flipY) context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
applyInfraredTransfer(context, canvas, mode);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function applyInfraredTransfer(context, canvas, mode) {
|
||||
const pixels = context.getImageData(0, 0, canvas.width, canvas.height);
|
||||
pixels.data.set(infraredAlpha(pixels.data, mode));
|
||||
context.putImageData(pixels, 0, 0);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
/** Draw pixels a frame source supplied into a new canvas, with the display
|
||||
* transfer for infrared products, and release them. They must be `size`. */
|
||||
function drawSuppliedImage(pixels, product, mode, size, signal, createCanvas) {
|
||||
try {
|
||||
signal.throwIfAborted();
|
||||
const { width, height } = weatherPixelSize(pixels);
|
||||
if (width !== size.width || height !== size.height)
|
||||
throw new Error('Invalid weather image dimensions');
|
||||
const texture = createCanvas();
|
||||
texture.width = width;
|
||||
texture.height = height;
|
||||
const context = texture.getContext('2d');
|
||||
drawWeatherPixels(context, pixels);
|
||||
if (product === 'clouds' || product === 'clouds-regional')
|
||||
applyInfraredTransfer(context, texture, mode);
|
||||
return texture;
|
||||
} finally {
|
||||
closeWeatherPixels(pixels);
|
||||
}
|
||||
}
|
||||
|
||||
/** Decode locally, releasing the object URL on success, failure or cancellation. */
|
||||
@@ -60,7 +90,8 @@ export function decodeInfraredImage(blob, signal) {
|
||||
/** Fetch one capped whole-extent frame, or a `bbox` detail window of it, and draw
|
||||
* it into a canvas. Infrared frames get the display transfer; a canvas also keeps
|
||||
* Cesium's texture row order, which an ImageBitmap upload would not. The decoded
|
||||
* image is always released. */
|
||||
* image is always released. With a `frameSource` that has `getImage`, the host
|
||||
* supplies the decoded pixels instead and nothing is fetched or decoded here. */
|
||||
export async function acquireWeatherImage(
|
||||
product,
|
||||
time,
|
||||
@@ -75,8 +106,30 @@ export async function acquireWeatherImage(
|
||||
decodeImage = decodeInfraredImage,
|
||||
now = () => performance.now(),
|
||||
onFetched = () => {},
|
||||
frameSource = null,
|
||||
},
|
||||
) {
|
||||
if (frameSource?.getImage) {
|
||||
signal.throwIfAborted();
|
||||
const started = now();
|
||||
const pixels = await frameSource.getImage({
|
||||
product,
|
||||
time,
|
||||
size,
|
||||
bbox,
|
||||
signal,
|
||||
});
|
||||
onFetched();
|
||||
const texture = drawSuppliedImage(
|
||||
pixels,
|
||||
product,
|
||||
mode,
|
||||
size,
|
||||
signal,
|
||||
createCanvas,
|
||||
);
|
||||
return { texture, decodeMs: now() - started };
|
||||
}
|
||||
const response = await fetchImpl(weatherImageUrl(product, time, size, bbox), {
|
||||
signal,
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user