import { internals, primordials } from "ext:core/mod.js";
import { ImageBitmap, op_create_image_bitmap } from "ext:core/ops";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import { createFilteredInspectProxy } from "ext:deno_web/01_console.js";
import { BlobPrototype } from "ext:deno_web/09_file.js";
import { sniffImage } from "ext:deno_web/01_mimesniff.js";
const {
ObjectDefineProperty,
ObjectPrototypeIsPrototypeOf,
SymbolFor,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetLength,
TypedArrayPrototypeGetSymbolToStringTag,
Uint8Array,
Uint8ClampedArray,
PromiseReject,
RangeError,
ArrayPrototypeJoin,
} = primordials;
import {
_data,
_height,
_width,
ImageDataPrototype,
} from "ext:deno_web/16_image_data.js";
webidl.converters["ImageOrientation"] = webidl.createEnumConverter(
"ImageOrientation",
[
"from-image",
"flipY",
],
);
webidl.converters["PremultiplyAlpha"] = webidl.createEnumConverter(
"PremultiplyAlpha",
[
"none",
"premultiply",
"default",
],
);
webidl.converters["ColorSpaceConversion"] = webidl.createEnumConverter(
"ColorSpaceConversion",
[
"none",
"default",
],
);
webidl.converters["ResizeQuality"] = webidl.createEnumConverter(
"ResizeQuality",
[
"pixelated",
"low",
"medium",
"high",
],
);
webidl.converters["ImageBitmapOptions"] = webidl.createDictionaryConverter(
"ImageBitmapOptions",
[
{
key: "imageOrientation",
converter: webidl.converters["ImageOrientation"],
defaultValue: "from-image",
},
{
key: "premultiplyAlpha",
converter: webidl.converters["PremultiplyAlpha"],
defaultValue: "default",
},
{
key: "colorSpaceConversion",
converter: webidl.converters["ColorSpaceConversion"],
defaultValue: "default",
},
{
key: "resizeWidth",
converter: (v, prefix, context, opts) =>
webidl.converters["unsigned long"](v, prefix, context, {
...opts,
enforceRange: true,
}),
},
{
key: "resizeHeight",
converter: (v, prefix, context, opts) =>
webidl.converters["unsigned long"](v, prefix, context, {
...opts,
enforceRange: true,
}),
},
{
key: "resizeQuality",
converter: webidl.converters["ResizeQuality"],
defaultValue: "low",
},
],
);
const ImageBitmapPrototype = ImageBitmap.prototype;
const privateCustomInspect = SymbolFor("Deno.privateCustomInspect");
ObjectDefineProperty(ImageBitmapPrototype, privateCustomInspect, {
__proto__: null,
value(inspect, inspectOptions) {
return inspect(
createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(ImageBitmapPrototype, this),
keys: [
"width",
"height",
],
}),
inspectOptions,
);
},
});
function float16ToUnorm8(data) {
const length = TypedArrayPrototypeGetLength(data);
const result = new Uint8ClampedArray(length);
for (let i = 0; i < length; i++) {
result[i] = data[i] * 255;
}
return result;
}
function createImageBitmap(
image,
sxOrOptions = undefined,
sy = undefined,
sw = undefined,
sh = undefined,
options = undefined,
) {
const prefix = "Failed to execute 'createImageBitmap'";
const imageBitmapSources = [
"Blob",
"ImageData",
"ImageBitmap",
];
if (arguments.length < 3) {
options = webidl.converters["ImageBitmapOptions"](
sxOrOptions,
prefix,
"Argument 2",
);
} else {
sxOrOptions = webidl.converters["long"](sxOrOptions, prefix, "Argument 2");
sy = webidl.converters["long"](sy, prefix, "Argument 3");
sw = webidl.converters["long"](sw, prefix, "Argument 4");
sh = webidl.converters["long"](sh, prefix, "Argument 5");
options = webidl.converters["ImageBitmapOptions"](
options,
prefix,
"Argument 6",
);
if (sw === 0) {
return PromiseReject(new RangeError("sw has to be greater than 0"));
}
if (sh === 0) {
return PromiseReject(new RangeError("sh has to be greater than 0"));
}
}
if (options.resizeWidth === 0) {
return PromiseReject(
new DOMException(
"options.resizeWidth has to be greater than 0",
"InvalidStateError",
),
);
}
if (options.resizeHeight === 0) {
return PromiseReject(
new DOMException(
"options.resizeHeight has to be greater than 0",
"InvalidStateError",
),
);
}
const isBlob = ObjectPrototypeIsPrototypeOf(BlobPrototype, image);
const isImageData = ObjectPrototypeIsPrototypeOf(ImageDataPrototype, image);
const isImageBitmap = ObjectPrototypeIsPrototypeOf(
ImageBitmapPrototype,
image,
);
if (!isBlob && !isImageData && !isImageBitmap) {
return PromiseReject(
new DOMException(
`${prefix}: The provided value for 'image' is not of type '(${
ArrayPrototypeJoin(imageBitmapSources, " or ")
})'`,
"InvalidStateError",
),
);
}
return (async () => {
let width = 0;
let height = 0;
let mimeType = 0;
let imageBitmapSource, buf;
if (isBlob) {
imageBitmapSource = 0;
buf = new Uint8Array(await image.arrayBuffer());
const mimeTypeString = sniffImage(null, buf);
if (mimeTypeString === "image/png") {
mimeType = 1;
} else if (mimeTypeString === "image/jpeg") {
mimeType = 2;
} else if (mimeTypeString === "image/gif") {
mimeType = 3;
return PromiseReject(
new DOMException(
"The MIME type of source image is not supported currently",
"InvalidStateError",
),
);
} else if (mimeTypeString === "image/bmp") {
mimeType = 4;
} else if (mimeTypeString === "image/x-icon") {
mimeType = 5;
} else if (mimeTypeString === "image/webp") {
mimeType = 6;
return PromiseReject(
new DOMException(
"The MIME type of source image is not supported currently",
"InvalidStateError",
),
);
} else {
return PromiseReject(
new DOMException(
`The the MIME type ${mimeTypeString} of source image is not a supported format\n
info: The following MIME types are supported.
docs: https://mimesniff.spec.whatwg.org/#image-type-pattern-matching-algorithm\n`,
"InvalidStateError",
),
);
}
} else if (isImageData) {
width = image[_width];
height = image[_height];
imageBitmapSource = 1;
let data = image[_data];
switch (TypedArrayPrototypeGetSymbolToStringTag(data)) {
case "Float16Array":
data = float16ToUnorm8(data);
break;
}
buf = new Uint8Array(
TypedArrayPrototypeGetBuffer(data),
TypedArrayPrototypeGetByteOffset(data),
TypedArrayPrototypeGetLength(data),
);
} else if (isImageBitmap) {
width = image.width;
height = image.height;
imageBitmapSource = 2;
buf = new Uint8Array(TypedArrayPrototypeGetBuffer(image[_bitmapData]()));
}
const _sx = typeof sxOrOptions === "number" ? sxOrOptions : 0;
const _sy = sy ?? 0;
const _sw = sw ?? 0;
const _sh = sh ?? 0;
const resizeWidth = options.resizeWidth ?? 0;
const resizeHeight = options.resizeHeight ?? 0;
const imageOrientation = options.imageOrientation === "flipY" ? 1 : 0;
let premultiplyAlpha = 0;
if (options.premultiplyAlpha === "premultiply") {
premultiplyAlpha = 1;
} else if (options.premultiplyAlpha === "none") {
premultiplyAlpha = 2;
}
const colorSpaceConversion = options.colorSpaceConversion === "none"
? 1
: 0;
let resizeQuality = 0;
if (options.resizeQuality === "pixelated") {
resizeQuality = 1;
} else if (options.resizeQuality === "medium") {
resizeQuality = 2;
} else if (options.resizeQuality === "high") {
resizeQuality = 3;
}
return op_create_image_bitmap(
buf,
width,
height,
_sx,
_sy,
_sw,
_sh,
imageOrientation,
premultiplyAlpha,
colorSpaceConversion,
resizeWidth,
resizeHeight,
resizeQuality,
imageBitmapSource,
mimeType,
);
})();
}
const _bitmapData = SymbolFor("Deno_bitmapData");
function getBitmapData(imageBitmap) {
return imageBitmap[_bitmapData]();
}
internals.getBitmapData = getBitmapData;
export { createImageBitmap, ImageBitmap };