Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 31 additions & 24 deletions tfjs-core/src/ops/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ function fromPixels_(
} else if ((pixels as any).getContext != null) {
isCanvasLike = true;
} else if (
typeof (ImageBitmap) !== 'undefined' &&
pixels instanceof ImageBitmap) {
typeof (ImageBitmap) !== 'undefined' && pixels instanceof ImageBitmap) {
isImageBitmap = true;
} else {
throw new Error(
Expand Down Expand Up @@ -165,26 +164,27 @@ function fromPixels_(
// Helper functions for |fromPixelsAsync| to check whether the input can
// be wrapped into imageBitmap.
function isPixelData(pixels: PixelData|ImageData|HTMLImageElement|
HTMLCanvasElement|HTMLVideoElement|ImageBitmap): pixels is PixelData {
HTMLCanvasElement|HTMLVideoElement|
ImageBitmap): pixels is PixelData {
return (pixels != null) && ((pixels as PixelData).data instanceof Uint8Array);
}

function isImageBitmapFullySupported() {
return typeof window !== 'undefined' &&
typeof (ImageBitmap) !== 'undefined' &&
window.hasOwnProperty('createImageBitmap');
typeof (ImageBitmap) !== 'undefined' &&
window.hasOwnProperty('createImageBitmap');
}

function isNonEmptyPixels(pixels: PixelData|ImageData|HTMLImageElement|
HTMLCanvasElement|HTMLVideoElement|ImageBitmap) {
HTMLCanvasElement|HTMLVideoElement|ImageBitmap) {
return pixels != null && pixels.width !== 0 && pixels.height !== 0;
}

function canWrapPixelsToImageBitmap(pixels: PixelData|ImageData|
HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|ImageBitmap) {
return isImageBitmapFullySupported() &&
!(pixels instanceof ImageBitmap) &&
isNonEmptyPixels(pixels) && !isPixelData(pixels);
HTMLImageElement|HTMLCanvasElement|
HTMLVideoElement|ImageBitmap) {
return isImageBitmapFullySupported() && !(pixels instanceof ImageBitmap) &&
isNonEmptyPixels(pixels) && !isPixelData(pixels);
}

/**
Expand All @@ -202,7 +202,7 @@ function canWrapPixelsToImageBitmap(pixels: PixelData|ImageData|
* This API is the async version of fromPixels. The API will first
* check |WRAP_TO_IMAGEBITMAP| flag, and try to wrap the input to
* imageBitmap if the flag is set to true.
*
*
* @param pixels The input image to construct the tensor from. The
* supported image types are all 4-channel. You can also pass in an image
* object with following attributes:
Expand All @@ -214,41 +214,48 @@ function canWrapPixelsToImageBitmap(pixels: PixelData|ImageData|
* @doc {heading: 'Browser', namespace: 'browser', ignoreCI: true}
*/
export async function fromPixelsAsync(
pixels: PixelData|ImageData|HTMLImageElement|HTMLCanvasElement|
HTMLVideoElement|ImageBitmap,
numChannels = 3) {
pixels: PixelData|ImageData|HTMLImageElement|HTMLCanvasElement|
HTMLVideoElement|ImageBitmap,
numChannels = 3) {
let inputs: PixelData|ImageData|HTMLImageElement|HTMLCanvasElement|
HTMLVideoElement|ImageBitmap = null;
HTMLVideoElement|ImageBitmap = null;

// Check whether the backend needs to wrap |pixels| to imageBitmap and
// whether |pixels| can be wrapped to imageBitmap.
if (env().getBool('WRAP_TO_IMAGEBITMAP') &&
canWrapPixelsToImageBitmap(pixels)) {
// Force the imageBitmap creation to not do any premultiply alpha
// ops.
const imageBitmap =
// tslint:disable-next-line: no-any
await (createImageBitmap as any)(pixels as ImageBitmapSource,
{premultiplyAlpha: 'none'});
let imageBitmap;

try {
// wrap in try-catch block, because createImageBitmap may not work
// properly in some browsers, e.g.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1335594
// tslint:disable-next-line: no-any
imageBitmap = await (createImageBitmap as any)(
pixels as ImageBitmapSource, {premultiplyAlpha: 'none'});
} catch (e) {
imageBitmap = null;
}

// createImageBitmap will clip the source size.
// In some cases, the input will have larger size than its content.
// E.g. new Image(10, 10) but with 1 x 1 content. Using
// createImageBitmap will clip the size from 10 x 10 to 1 x 1, which
// is not correct. We should avoid wrapping such resouce to
// imageBitmap.
if (imageBitmap != null &&
imageBitmap.width === pixels.width &&
if (imageBitmap != null && imageBitmap.width === pixels.width &&
imageBitmap.height === pixels.height) {
inputs = imageBitmap;
} else {
inputs = pixels;
inputs = pixels;
}
} else {
inputs = pixels;
}
}

return fromPixels_(inputs, numChannels);
return fromPixels_(inputs, numChannels);
}

/**
Expand Down