You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

128 lines
4.6 KiB

function imageDataFromCanvas(image : CanvasImageSource, width : number, height : number) : ImageData {
const canvas = document.createElement("canvas");
const canvasCtx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
canvasCtx.drawImage(image, 0, 0, width, height);
return canvasCtx.getImageData(0, 0, width, height);
}
async function imageDataFromBlob(blob : Blob) : Promise<ImageData> {
// turn blob into an img element and pass back to imageDataFrom
const url = URL.createObjectURL(blob)
const image = new Image()
image.src = url
await new Promise((resolve, reject) => {
image.onload = resolve
image.onerror = reject
})
URL.revokeObjectURL(url)
return imageDataFrom(image)
}
export async function imageDataFrom(image : ImageBitmapSource) : Promise<ImageData> {
// spec quoted from:
// https://wicg.github.io/shape-detection-api/#image-sources-for-detection
// [TODO]
// If any ImageBitmapSource have an effective script origin (origin) which is
// not the same as the Document’s effective script origin, then reject the
// Promise with a new DOMException whose name is SecurityError.
if (image instanceof HTMLImageElement) {
// [TODO]
// When an ImageBitmapSource object represents an HTMLImageElement, the
// element’s image must be used as the source image. Specifically, when an
// ImageBitmapSource object represents an animated image in an
// HTMLImageElement, the user agent must use the default image of the
// animation (the one that the format defines is to be used when animation
// is not supported or is disabled), or, if there is no such image, the
// first frame of the animation.
// [SPEC]
// If the ImageBitmapSource is an HTMLImageElement object that is in the
// Broken (HTML Standard §img-error) state, then reject the Promise with a
// new DOMException whose name is InvalidStateError, and abort any further
// steps.
// [SPEC]
// If the ImageBitmapSource is an HTMLImageElement object that is not fully
// decodable then reject the Promise with a new DOMException whose name is
// InvalidStateError, and abort any further steps
try {
image.decode()
} catch (_) {
throw new DOMException("HTMLImageElement is not decodable", "InvalidStateError")
}
return imageDataFromCanvas(image, image.naturalWidth, image.naturalHeight)
} else if (image instanceof SVGImageElement) {
// TODO width/height is a little bit arbitrary
return imageDataFromCanvas(image, 640, 480)
} else if (image instanceof HTMLVideoElement) {
// [SPEC]
// If the ImageBitmapSource is an HTMLVideoElement object whose readyState
// attribute is either HAVE_NOTHING or HAVE_METADATA then reject the Promise
// with a new DOMException whose name is InvalidStateError, and abort any
// further steps.
const HAVE_NOTHING = 0, HAVE_METADATA = 1;
if (image.readyState === HAVE_NOTHING || image.readyState === HAVE_METADATA) {
throw new DOMException("", "InvalidStateError")
}
// [SPEC]
// When an ImageBitmapSource object represents an HTMLVideoElement, then
// the frame at the current playback position when the method with the
// argument is invoked must be used as the source image when processing the
// image, and the source image’s dimensions must be the intrinsic dimensions
// of the media resource (i.e. after any aspect-ratio correction has been applied).
return imageDataFromCanvas(image, image.videoWidth, image.videoHeight)
} else if (image instanceof HTMLCanvasElement) {
// [TODO]
// When an ImageBitmapSource object represents an HTMLCanvasElement, the
// element’s bitmap must be used as the source image.
// [TODO]
// If the ImageBitmapSource argument is an HTMLCanvasElement whose bitmap’s
// origin-clean (HTML Standard §concept-canvas-origin-clean) flag is false,
// then reject the Promise with a new DOMException whose name is
// SecurityError, and abort any further steps.
const canvasCtx = image.getContext("2d")
return canvasCtx.getImageData(0, 0, image.width, image.height)
} else if (image instanceof ImageBitmap) {
return imageDataFromCanvas(image, image.width, image.height)
} else if (image instanceof OffscreenCanvas) {
const canvasCtx = image.getContext("2d")
return canvasCtx.getImageData(0, 0, image.width, image.height)
} else if (image instanceof Blob) {
return imageDataFromBlob(image)
} else if (image instanceof ImageData) {
return image
} else {
// TODO TypeError?
}
}