summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/web/16_image_data.js215
-rw-r--r--ext/web/internal.d.ts4
-rw-r--r--ext/web/lib.deno_web.d.ts28
-rw-r--r--ext/web/lib.rs1
4 files changed, 248 insertions, 0 deletions
diff --git a/ext/web/16_image_data.js b/ext/web/16_image_data.js
new file mode 100644
index 000000000..a753a34cf
--- /dev/null
+++ b/ext/web/16_image_data.js
@@ -0,0 +1,215 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+
+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_console/01_console.js";
+const primordials = globalThis.__bootstrap.primordials;
+const {
+ ObjectPrototypeIsPrototypeOf,
+ SymbolFor,
+ TypedArrayPrototypeGetLength,
+ TypedArrayPrototypeGetSymbolToStringTag,
+ Uint8ClampedArray,
+} = primordials;
+
+webidl.converters["PredefinedColorSpace"] = webidl.createEnumConverter(
+ "PredefinedColorSpace",
+ [
+ "srgb",
+ "display-p3",
+ ],
+);
+
+webidl.converters["ImageDataSettings"] = webidl.createDictionaryConverter(
+ "ImageDataSettings",
+ [
+ { key: "colorSpace", converter: webidl.converters["PredefinedColorSpace"] },
+ ],
+);
+
+class ImageData {
+ /** @type {number} */
+ #width;
+ /** @type {height} */
+ #height;
+ /** @type {Uint8Array} */
+ #data;
+ /** @type {'srgb' | 'display-p3'} */
+ #colorSpace;
+
+ constructor(arg0, arg1, arg2 = undefined, arg3 = undefined) {
+ webidl.requiredArguments(
+ arguments.length,
+ 2,
+ 'Failed to construct "ImageData"',
+ );
+ this[webidl.brand] = webidl.brand;
+
+ let sourceWidth;
+ let sourceHeight;
+ let data;
+ let settings;
+ const prefix = "Failed to construct 'ImageData'";
+
+ // Overload: new ImageData(data, sw [, sh [, settings ] ])
+ if (
+ arguments.length > 3 ||
+ TypedArrayPrototypeGetSymbolToStringTag(arg0) === "Uint8ClampedArray"
+ ) {
+ data = webidl.converters.Uint8ClampedArray(arg0, prefix, "Argument 1");
+ sourceWidth = webidl.converters["unsigned long"](
+ arg1,
+ prefix,
+ "Argument 2",
+ );
+ const dataLength = TypedArrayPrototypeGetLength(data);
+
+ if (webidl.type(arg2) !== "Undefined") {
+ sourceHeight = webidl.converters["unsigned long"](
+ arg2,
+ prefix,
+ "Argument 3",
+ );
+ }
+
+ settings = webidl.converters["ImageDataSettings"](
+ arg3,
+ prefix,
+ "Argument 4",
+ );
+
+ if (dataLength === 0) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The input data has zero elements.",
+ "InvalidStateError",
+ );
+ }
+
+ if (dataLength % 4 !== 0) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The input data length is not a multiple of 4.",
+ "InvalidStateError",
+ );
+ }
+
+ if (sourceWidth < 1) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The source width is zero or not a number.",
+ "IndexSizeError",
+ );
+ }
+
+ if (webidl.type(sourceHeight) !== "Undefined" && sourceHeight < 1) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The source height is zero or not a number.",
+ "IndexSizeError",
+ );
+ }
+
+ if (dataLength / 4 % sourceWidth !== 0) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The input data length is not a multiple of (4 * width).",
+ "IndexSizeError",
+ );
+ }
+
+ if (
+ webidl.type(sourceHeight) !== "Undefined" &&
+ (sourceWidth * sourceHeight * 4 !== dataLength)
+ ) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The input data length is not equal to (4 * width * height).",
+ "IndexSizeError",
+ );
+ }
+
+ if (webidl.type(sourceHeight) === "Undefined") {
+ this.#height = dataLength / 4 / sourceWidth;
+ } else {
+ this.#height = sourceHeight;
+ }
+
+ this.#colorSpace = settings.colorSpace ?? "srgb";
+ this.#width = sourceWidth;
+ this.#data = data;
+ return;
+ }
+
+ // Overload: new ImageData(sw, sh [, settings])
+ sourceWidth = webidl.converters["unsigned long"](
+ arg0,
+ prefix,
+ "Argument 1",
+ );
+ sourceHeight = webidl.converters["unsigned long"](
+ arg1,
+ prefix,
+ "Argument 2",
+ );
+
+ settings = webidl.converters["ImageDataSettings"](
+ arg2,
+ prefix,
+ "Argument 3",
+ );
+
+ if (sourceWidth < 1) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The source width is zero or not a number.",
+ "IndexSizeError",
+ );
+ }
+
+ if (sourceHeight < 1) {
+ throw new DOMException(
+ "Failed to construct 'ImageData': The source height is zero or not a number.",
+ "IndexSizeError",
+ );
+ }
+
+ this.#colorSpace = settings.colorSpace ?? "srgb";
+ this.#width = sourceWidth;
+ this.#height = sourceHeight;
+ this.#data = new Uint8ClampedArray(sourceWidth * sourceHeight * 4);
+ }
+
+ get width() {
+ webidl.assertBranded(this, ImageDataPrototype);
+ return this.#width;
+ }
+
+ get height() {
+ webidl.assertBranded(this, ImageDataPrototype);
+ return this.#height;
+ }
+
+ get data() {
+ webidl.assertBranded(this, ImageDataPrototype);
+ return this.#data;
+ }
+
+ get colorSpace() {
+ webidl.assertBranded(this, ImageDataPrototype);
+ return this.#colorSpace;
+ }
+
+ [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) {
+ return inspect(
+ createFilteredInspectProxy({
+ object: this,
+ evaluate: ObjectPrototypeIsPrototypeOf(ImageDataPrototype, this),
+ keys: [
+ "data",
+ "width",
+ "height",
+ "colorSpace",
+ ],
+ }),
+ inspectOptions,
+ );
+ }
+}
+
+const ImageDataPrototype = ImageData.prototype;
+
+export { ImageData };
diff --git a/ext/web/internal.d.ts b/ext/web/internal.d.ts
index a07f4b814..e151806a1 100644
--- a/ext/web/internal.d.ts
+++ b/ext/web/internal.d.ts
@@ -111,3 +111,7 @@ declare module "ext:deno_web/13_message_port.js" {
transferables: Transferable[];
}
}
+
+declare module "ext:deno_web/16_image_data.js" {
+ const ImageData: typeof ImageData;
+}
diff --git a/ext/web/lib.deno_web.d.ts b/ext/web/lib.deno_web.d.ts
index 9b9a55c23..9a70e1501 100644
--- a/ext/web/lib.deno_web.d.ts
+++ b/ext/web/lib.deno_web.d.ts
@@ -1237,3 +1237,31 @@ declare var DecompressionStream: {
declare function reportError(
error: any,
): void;
+
+/** @category Web APIs */
+type PredefinedColorSpace = "srgb" | "display-p3";
+
+/** @category Web APIs */
+interface ImageDataSettings {
+ readonly colorSpace?: PredefinedColorSpace;
+}
+
+/** @category Web APIs */
+interface ImageData {
+ readonly colorSpace: PredefinedColorSpace;
+ readonly data: Uint8ClampedArray;
+ readonly height: number;
+ readonly width: number;
+}
+
+/** @category Web APIs */
+declare var ImageData: {
+ prototype: ImageData;
+ new (sw: number, sh: number, settings?: ImageDataSettings): ImageData;
+ new (
+ data: Uint8ClampedArray,
+ sw: number,
+ sh?: number,
+ settings?: ImageDataSettings,
+ ): ImageData;
+};
diff --git a/ext/web/lib.rs b/ext/web/lib.rs
index a68b6344e..a5b77d6b8 100644
--- a/ext/web/lib.rs
+++ b/ext/web/lib.rs
@@ -117,6 +117,7 @@ deno_core::extension!(deno_web,
"13_message_port.js",
"14_compression.js",
"15_performance.js",
+ "16_image_data.js",
],
options = {
blob_store: Arc<BlobStore>,