Skip to content

Commit

Permalink
Merge pull request #36 from robertknight/chrome-image-clone-workaround
Browse files Browse the repository at this point in the history
Convert ImageBitmap => ImageData on the main thread in all browsers
  • Loading branch information
robertknight committed Jun 4, 2022
2 parents f0c01bd + c5a8592 commit 42d7cc2
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 28 deletions.
26 changes: 10 additions & 16 deletions src/ocr-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import * as comlink from "comlink";
// @ts-ignore
import nodeEndpoint from "comlink/dist/esm/node-adapter.mjs";

import { imageDataFromBitmap } from "./utils";

/**
* @typedef {import('./ocr-engine').BoxItem} BoxItem
* @typedef {import('./ocr-engine').TextItem} TextItem
Expand Down Expand Up @@ -127,22 +129,14 @@ export class OCRClient {
* @param {ImageBitmap|ImageData} image
*/
async loadImage(image) {
// If the browser doesn't support OffscreenCanvas, we have to perform
// ImageBitmap => ImageData conversion on the main thread.
if (
typeof ImageBitmap !== "undefined" &&
image instanceof ImageBitmap &&
// @ts-expect-error - OffscreenCanvas is missing from TS types
typeof OffscreenCanvas === "undefined"
) {
const canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
const context = /** @type {CanvasRenderingContext2D} */ (
canvas.getContext("2d")
);
context.drawImage(image, 0, 0, image.width, image.height);
image = context.getImageData(0, 0, image.width, image.height);
// Convert ImageBitmap to ImageData. In browsers that don't support
// OffscreenCanvas (Firefox and Safari as of 2022-06) we have to do this
// on the main thread using a canvas. In Chrome, we still do this on the
// main thread but using OffscreenCanvas, to work around an issue with
// rotation information being lost. See
// https://bugs.chromium.org/p/chromium/issues/detail?id=1332947.
if (typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) {
image = imageDataFromBitmap(image);
}
const engine = await this._ocrEngine;
return engine.loadImage(image);
Expand Down
14 changes: 2 additions & 12 deletions src/ocr-engine.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// @ts-ignore - Don't error if library hasn't been built yet.
import initTesseractCore from "../build/tesseract-core";

import { imageDataFromBitmap } from "./utils";

/**
* JS interface to a `std::vector` returned from a C++ method wrapped by
* Embind.
Expand All @@ -11,18 +13,6 @@ import initTesseractCore from "../build/tesseract-core";
* @prop {(index: number) => T} get
*/

/**
* @param {ImageBitmap} bitmap
*/
function imageDataFromBitmap(bitmap) {
// @ts-expect-error - OffscreenCanvas API is missing
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
/** @type {CanvasRenderingContext2D} */
const context = canvas.getContext("2d");
context.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height);
return context.getImageData(0, 0, bitmap.width, bitmap.height);
}

/**
* Create a JS array from a std::vector wrapper created by Embind.
*
Expand Down
26 changes: 26 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @param {ImageBitmap} bitmap
* @return {ImageData}
*/
export function imageDataFromBitmap(bitmap) {
/** @type {HTMLCanvasElement} */
let canvas;
// @ts-expect-error - OffscreenCanvas API is missing
if (typeof OffscreenCanvas !== "undefined") {
// @ts-expect-error - OffscreenCanvas API is missing
canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
} else if (typeof HTMLCanvasElement !== "undefined") {
const canvasEl = document.createElement("canvas");
canvasEl.width = bitmap.width;
canvasEl.height = bitmap.height;
canvas = canvasEl;
} else {
throw new Error("No canvas implementation available");
}

const context = /** @type {CanvasRenderingContext2D} */ (
canvas.getContext("2d")
);
context.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height);
return context.getImageData(0, 0, bitmap.width, bitmap.height);
}

0 comments on commit 42d7cc2

Please sign in to comment.