0

I'm loading an image into a canvas element. It's working fine in a normal web page:

<canvas id="canvas" width="50" height="50" style="border:1px solid #000000;">
</canvas>

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

ctx.lineWidth = 2;
ctx.strokeStyle = 'green';
ctx.strokeRect(1, 1, 40, 40);

const image = new Image();
image.onload = function() {
  ctx.drawImage(image, 0, 0);
};
image.src = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKCgsJCYlJx8fLTEtJSk9Lj0uIyszODMsNygtLisBCgoKDQwNGg8PGjAlHyU3Nzc3LSstKy0tNS03Ky0rNSstLSsrKysrKy0rLSs3KysrKysrKysrKystKysrKysrK//AABEIACgAKAMBIgACEQEDEQH/xAAbAAACAwADAAAAAAAAAAAAAAAABwQFBgECA//EACwQAAEDAwMCBQMFAAAAAAAAAAECAwQABREGITESQRMyUYGRB2FxFCKhsfD/xAAYAQADAQEAAAAAAAAAAAAAAAADBAUCAf/EACERAQACAQMEAwAAAAAAAAAAAAEAAhEDEjEhIkFhBBNR/9oADAMBAAIRAxEAPwBkOftBpa631DNFxNut7gQGgC6oKG5PAwQcf2c0y3k9W1YhjS8ebrK5uzUlbI6SEFWAolI5x2GDtQb4qZeJug2cRXSZbxdUk8jY9wR6D/dq0Wgb/IjahELBW1K2wnYJUBscfgYprHTNnZaPh2+MAeR4YOfmsRq20MQHm7jbkoiyWT1pW2MdWD5TjkHg0G/yASqYz5hzQUbDxGTDUFLQHBsVDNFRbNJTKYjvo4WlKwD6EAiijHEBJ4Tk1RS/1LM6XIhNdTqkpSU4BJwSBsSABwck8eu1X6DsKgTpTEOSpxTiAQ0XFpzkhI745x965rjtz4m9BN2HmQTMuItSDKCG5jp6AANhnOD/ABWQ1HGujkN8ziQhtJ82CCexBASR+CD23qVqLVanoZXCgPupQ6lQcW2UjA5I3ya637UES6WBEjxC0yD0vhaSCg4BORydjnbmkLi+/wAj4AdekudLPOLs0Z0I6Q2kITg+YAAZ98UV7abuFnetjEa2XCLI8NsDDagCTyT0ncb5O9FUqUdvdJmojbti2vv1IvVxBEDMCOT0gMnKycZAKud9uMd+ap7Lf5zWpo9xlzXXFuKCFuOkqy2Tg5z2HOAexoopy1K7GJUvbeRm6muao8xgB5wNEAuNNxwsK98bUvPqFd3JCVRgUhouZSlPdIHJ98fFFFS9KlXUrKupe31sxkYEKCgSkjfIzkff5rmiiqklq5n/2Q==';

https://codepen.io/adsfdsfhdsafkhdsafjkdhafskjds/pen/abBqLdQ

However when I try and use the same code to set the icon for my Chrome extension it has the rectangle but not the image. In the background script:

chrome.webNavigation.onCompleted.addListener(() => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = 50;
  canvas.height = 50;

  const image = new Image();
  image.onload = function() {
    ctx.drawImage(image, 0, 0);
  };
  image.src = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKCgsJCYlJx8fLTEtJSk9Lj0uIyszODMsNygtLisBCgoKDQwNGg8PGjAlHyU3Nzc3LSstKy0tNS03Ky0rNSstLSsrKysrKy0rLSs3KysrKysrKysrKystKysrKysrK//AABEIACgAKAMBIgACEQEDEQH/xAAbAAACAwADAAAAAAAAAAAAAAAABwQFBgECA//EACwQAAEDAwMCBQMFAAAAAAAAAAECAwQABREGITESQRMyUYGRB2FxFCKhsfD/xAAYAQADAQEAAAAAAAAAAAAAAAADBAUCAf/EACERAQACAQMEAwAAAAAAAAAAAAEAAhEDEjEhIkFhBBNR/9oADAMBAAIRAxEAPwBkOftBpa631DNFxNut7gQGgC6oKG5PAwQcf2c0y3k9W1YhjS8ebrK5uzUlbI6SEFWAolI5x2GDtQb4qZeJug2cRXSZbxdUk8jY9wR6D/dq0Wgb/IjahELBW1K2wnYJUBscfgYprHTNnZaPh2+MAeR4YOfmsRq20MQHm7jbkoiyWT1pW2MdWD5TjkHg0G/yASqYz5hzQUbDxGTDUFLQHBsVDNFRbNJTKYjvo4WlKwD6EAiijHEBJ4Tk1RS/1LM6XIhNdTqkpSU4BJwSBsSABwck8eu1X6DsKgTpTEOSpxTiAQ0XFpzkhI745x965rjtz4m9BN2HmQTMuItSDKCG5jp6AANhnOD/ABWQ1HGujkN8ziQhtJ82CCexBASR+CD23qVqLVanoZXCgPupQ6lQcW2UjA5I3ya637UES6WBEjxC0yD0vhaSCg4BORydjnbmkLi+/wAj4AdekudLPOLs0Z0I6Q2kITg+YAAZ98UV7abuFnetjEa2XCLI8NsDDagCTyT0ncb5O9FUqUdvdJmojbti2vv1IvVxBEDMCOT0gMnKycZAKud9uMd+ap7Lf5zWpo9xlzXXFuKCFuOkqy2Tg5z2HOAexoopy1K7GJUvbeRm6muao8xgB5wNEAuNNxwsK98bUvPqFd3JCVRgUhouZSlPdIHJ98fFFFS9KlXUrKupe31sxkYEKCgSkjfIzkff5rmiiqklq5n/2Q==';
 
  ctx.lineWidth = 2;
  ctx.strokeStyle = 'green';
  ctx.strokeRect(1, 1, 40, 40);

  chrome.browserAction.setIcon({
    imageData: ctx.getImageData(0, 0, 50, 50),
  });
});

So it looks like this: enter image description here

I don't see any errors in the webpage or background script's consoles. I also tried loading local and remove images (not base64 encoded) but nothing changes:

image.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSmuyeAhT_2puKqL7azw3al2li8Nd8gIvppig&usqp=CAU';
image.src = 'images/48-time.png';
Evanss
  • 23,390
  • 94
  • 282
  • 505
  • Duplicate of https://stackoverflow.com/questions/39583190/canvas-get-image-data-returning-0-always – Kaiido Mar 02 '21 at 05:31
  • If you are using a Chrome extension like Adblock or something, even they can have an impact on access to the canvas. Make sure you try by enabling your extension in incognito – Tarun Lalwani Mar 02 '21 at 10:08

2 Answers2

1

From your description (and the code) it looks like the image has not loaded when you are doing ctx.getImageData ... I would do the browserAction.setIcon in the same onload function after the ctx.drawImage, below is an example where we do all the drawing in the onload.

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const image = new Image();
image.onload = function() {
  ctx.lineWidth = 2;
  ctx.strokeStyle = 'green';
  ctx.strokeRect(1, 1, 40, 40);
  ctx.drawImage(image, 0, 0);
  // Add other browserAction.setIcon logic here
};
image.src = 'data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAOElEQVR42u3OQREAAAQAMILoH0ckUrjz2BIsu2risRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFLyxCZNRaZIFESsAAAAASUVORK5CYII=';
<canvas id="canvas" width="50" height="50" style="border:1px solid #000000;">
</canvas>

I did swap your image for a smaller one, just to reduce the code a bit.
You can change it back to yours


Another option would be to use putImageData instead of drawImage

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const arr = new Uint8ClampedArray([214,212,189,255,214,211,189,255,213,209,191,255,215,209,194,255,218,210,199,255,218,209,201,255,216,205,200,255,214,203,198,255,213,204,198,255,197,189,179,255,216,210,196,255,211,207,188,255,208,205,180,255,172,171,141,255,165,166,132,255,145,144,117,255,89,82,74,255,113,102,100,255,99,88,79,255,88,76,61,255,69,58,37,255,97,88,63,255,79,73,47,255,57,55,31,255,59,61,41,255,215,213,191,255,213,211,190,255,214,210,192,255,215,209,195,255,217,210,199,255,217,209,200,255,215,206,199,255,212,203,197,255,199,190,183,255,224,217,207,255,194,188,174,255,169,165,146,255,182,179,155,255,170,169,141,255,131,132,100,255,136,134,110,255,94,87,80,255,87,77,76,255,78,68,61,255,68,57,46,255,75,66,50,255,80,73,54,255,79,75,56,255,65,64,46,255,90,92,79,255,215,214,195,255,213,211,193,255,213,210,194,255,215,210,196,255,215,210,197,255,215,210,199,255,213,206,197,255,210,203,194,255,217,210,200,255,200,193,181,
  255,190,184,169,255,193,189,171,255,108,104,83,255,60,58,34,255,38,36,11,255,56,53,34,255,91,85,80,255,68,61,61,255,71,63,61,255,60,52,48,255,74,66,61,255,48,42,36,255,57,55,50,255,58,58,55,255,72,75,73,255,215,215,199,255,213,212,197,255,213,211,197,255,213,211,197,255,213,211,197,255,213,209,197,255,210,206,194,255,208,203,191,255,187,182,169,255,187,182,168,255,199,194,179,255,170,166,149,255,74,70,52,255,68,64,46,255,86,82,63,255,69,65,51,255,67,62,58,255,59,53,54,255,70,63,65,255,66,59,62,255,61,55,59,255,31,26,32,255,37,34,43,255,49,49,58,255,44,47,55,255,215,215,205,255,213,213,202,255,212,212,201,255,211,211,199,255,212,211,198,255,210,209,195,255,207,207,191,255,205,203,187,255,196,194,178,255,202,199,183,255,145,142,126,255,57,52,38,255,50,45,32,255,47,42,29,255,46,41,29,255,44,38,29,255,52,47,43,255,56,50,51,255,50,44,48,255,57,51,60,255,43,38,51,255,46,42,58,255,39,36,55,255,46,46,64,
  255,56,58,72,255,215,216,210,255,213,214,207,255,210,213,204,255,210,212,201,255,210,212,199,255,208,210,195,255,205,207,189,255,202,204,184,255,213,213,194,255,181,180,162,255,125,122,106,255,57,52,39,255,73,66,56,255,61,54,46,255,73,65,59,255,82,73,68,255,76,68,63,255,66,58,56,255,34,27,29,255,41,34,42,255,35,29,42,255,62,56,73,255,45,40,59,255,39,35,52,255,59,57,69,255,215,217,214,255,213,215,211,255,210,214,207,255,208,213,202,255,207,212,198,255,206,210,193,255,202,207,187,255,200,203,182,255,189,191,170,255,169,169,149,255,123,120,104,255,67,62,49,255,63,56,47,255,92,83,78,255,105,94,92,255,84,71,69,255,95,82,74,255,74,61,53,255,46,35,32,255,40,31,32,255,44,36,42,255,56,48,56,255,50,42,50,255,42,34,40,255,49,40,42,255,215,218,217,255,213,216,214,255,209,214,209,255,208,214,205,255,206,212,199,255,204,211,194,255,201,207,187,255,198,203,181,255,194,197,175,255,166,166,146,255,52,49,32,255,36,
  30,17,255,88,79,71,255,98,86,82,255,59,44,43,255,109,92,89,255,85,66,54,255,68,49,35,255,67,51,41,255,52,39,31,255,63,51,46,255,45,33,29,255,60,47,40,255,66,51,41,255,64,46,32,255,214,217,217,255,212,216,215,255,211,216,212,255,208,213,207,255,204,211,200,255,199,207,192,255,196,203,184,255,194,200,179,255,182,186,164,255,156,157,136,255,52,49,32,255,50,42,29,255,78,65,57,255,103,87,82,255,96,78,75,255,74,52,46,255,86,60,44,255,83,56,37,255,83,60,42,255,95,75,57,255,109,92,73,255,112,96,73,255,102,83,57,255,91,68,37,255,120,92,56,255,214,217,217,255,212,216,215,255,211,216,213,255,208,213,208,255,204,211,202,255,200,208,195,255,197,204,188,255,195,201,183,255,211,214,195,255,142,142,124,255,43,39,22,255,74,65,50,255,68,53,42,255,74,54,45,255,105,83,76,255,143,117,105,255,170,138,117,255,172,140,115,255,176,148,124,255,187,163,137,255,199,178,148,255,207,186,150,255,209,185,142,255,210,179,131,255,
  197,159,106,255,214,217,215,255,213,216,214,255,211,216,212,255,208,213,208,255,204,211,204,255,201,208,199,255,198,204,193,255,198,203,190,255,190,192,177,255,146,144,128,255,54,47,31,255,79,66,50,255,75,56,41,255,142,119,104,255,203,177,161,255,228,198,179,255,241,205,180,255,243,206,178,255,239,208,179,255,233,207,175,255,225,202,165,255,221,197,152,255,224,194,141,255,230,193,132,255,234,186,121,255,215,217,212,255,214,216,212,255,212,215,211,255,208,213,209,255,206,211,207,255,202,208,203,255,201,206,200,255,201,204,196,255,200,200,190,255,190,186,173,255,83,73,57,255,84,68,50,255,109,88,67,255,216,190,167,255,249,220,195,255,228,195,168,255,243,205,176,255,245,208,178,255,243,212,182,255,236,210,177,255,229,205,168,255,226,200,156,255,232,198,144,255,241,198,135,255,253,199,129,255,218,218,210,255,215,216,209,255,214,215,210,255,210,212,209,255,206,210,209,255,204,208,208,255,204,207,207,255,
  205,205,204,255,218,216,211,255,199,192,183,255,81,68,53,255,102,84,63,255,164,140,114,255,226,197,166,255,227,196,160,255,229,195,158,255,245,208,175,255,245,210,180,255,243,215,187,255,243,219,192,255,242,219,191,255,243,216,181,255,246,210,165,255,252,205,150,255,244,185,118,255,219,218,207,255,217,217,208,255,215,215,209,255,211,212,209,255,208,211,211,255,207,209,213,255,207,208,212,255,208,207,211,255,208,204,203,255,197,188,182,255,96,81,67,255,117,96,74,255,199,173,142,255,230,199,161,255,238,204,159,255,255,226,183,255,255,220,185,255,252,220,192,255,247,221,198,255,244,222,202,255,240,219,200,255,236,210,186,255,233,196,162,255,234,184,139,255,238,175,115,255,219,218,205,255,218,217,206,255,214,213,207,255,211,211,210,255,209,210,213,255,209,210,216,255,209,209,217,255,211,208,215,255,222,216,219,255,221,210,206,255,144,128,114,255,134,111,87,255,208,181,145,255,230,197,153,255,252,216,165,
  255,250,214,165,255,245,212,177,255,243,214,189,255,242,219,202,255,242,222,211,255,241,222,214,255,242,217,206,255,243,206,186,255,249,199,166,255,255,196,147,255,221,217,206,255,220,216,207,255,216,213,208,255,212,211,210,255,209,210,214,255,209,209,217,255,210,210,218,255,212,210,216,255,227,222,225,255,203,194,189,255,147,131,117,255,144,122,98,255,218,190,154,255,222,189,145,255,255,218,166,255,238,203,154,255,245,215,179,255,243,218,193,255,242,220,205,255,241,220,212,255,236,214,211,255,234,206,202,255,237,199,186,255,244,196,168,255,244,184,139,255,224,215,209,255,223,215,210,255,220,214,212,255,217,214,214,255,214,214,217,255,213,215,220,255,213,215,220,255,215,216,219,255,211,210,208,255,227,221,214,255,153,140,125,255,138,118,94,255,204,177,145,255,253,221,182,255,235,198,154,255,240,206,162,255,244,219,180,255,242,221,191,255,238,215,197,255,238,212,203,255,237,207,204,255,246,211,207,
  255,245,205,190,255,243,198,169,255,236,188,140,255,224,215,211,255,223,215,212,255,220,214,213,255,217,214,214,255,215,215,216,255,214,215,217,255,215,216,218,255,217,217,216,255,220,218,213,255,223,216,206,255,180,167,150,255,112,92,68,255,215,187,157,255,244,211,176,255,249,211,172,255,255,224,183,255,244,218,178,255,244,220,186,255,246,218,195,255,241,209,195,255,239,203,194,255,253,213,203,255,247,204,186,255,221,178,146,255,221,178,129,255,221,217,215,255,220,216,214,255,218,215,214,255,217,216,215,255,216,216,215,255,216,216,215,255,218,217,215,255,221,218,213,255,238,232,223,255,212,201,188,255,175,159,140,255,182,160,136,255,205,176,146,255,224,190,156,255,223,185,147,255,207,169,129,255,205,172,131,255,211,179,141,255,235,200,170,255,237,200,175,255,236,195,175,255,244,201,179,255,229,185,158,255,180,134,100,255,168,124,78,255,217,218,218,255,217,217,216,255,217,217,216,255,216,216,214,
  255,218,217,214,255,220,218,214,255,223,218,212,255,225,218,209,255,211,200,188,255,231,215,199,255,210,189,168,255,170,144,119,255,217,186,157,255,159,124,92,255,181,143,107,255,162,123,85,255,144,105,65,255,158,119,79,255,214,173,136,255,239,196,162,255,242,198,164,255,225,179,145,255,206,159,123,255,156,109,71,255,162,116,73,255,213,220,220,255,214,220,220,255,214,218,217,255,216,218,215,255,219,218,214,255,223,219,211,255,227,219,209,255,231,219,206,255,248,232,216,255,206,185,166,255,219,194,171,255,154,124,98,255,185,151,122,255,210,173,143,255,238,199,167,255,176,135,100,255,129,85,48,255,143,97,57,255,214,167,125,255,250,203,159,255,255,209,162,255,212,164,117,255,200,152,106,255,179,130,87,255,153,105,65,255,210,221,222,255,211,221,221,255,213,220,219,255,216,219,216,255,220,220,213,255,225,220,210,255,230,219,206,255,235,219,203,255,234,214,195,255,188,163,141,255,216,187,163,255,192,
  159,133,255,220,183,155,255,231,193,164,255,112,73,43,255,124,82,51,255,166,120,87,255,177,128,91,255,231,181,137,255,249,200,150,255,255,212,156,255,199,150,93,255,202,152,99,255,217,167,121,255,223,173,135,255,208,224,225,255,208,222,223,255,212,221,220,255,216,221,217,255,221,221,213,255,226,221,209,255,233,221,206,255,239,221,202,255,250,226,205,255,181,152,128,255,240,208,183,255,210,174,148,255,231,193,166,255,214,174,147,255,201,161,134,255,252,211,183,255,211,165,139,255,223,175,144,255,250,203,160,255,235,188,136,255,253,206,145,255,190,142,79,255,199,150,92,255,236,184,136,255,226,173,137,255,207,224,226,255,208,223,224,255,210,222,220,255,215,221,217,255,220,221,213,255,227,222,210,255,234,221,205,255,239,221,201,255,237,212,190,255,249,220,196,255,198,165,140,255,194,158,132,255,224,185,159,255,255,216,189,255,241,201,174,255,228,188,163,255,235,193,172,255,253,210,185,255,255,221,
  182,255,224,181,130,255,249,205,144,255,189,142,79,255,198,149,91,255,237,185,137,255,255,204,170,255,204,221,222,255,209,223,223,255,214,226,223,255,218,226,221,255,222,223,216,255,226,222,211,255,232,221,207,255,239,222,204,255,244,222,201,255,240,212,189,255,220,188,164,255,212,176,151,255,228,190,163,255,241,201,174,255,247,206,179,255,254,214,190,255,254,217,202,255,244,207,189,255,235,198,165,255,242,204,159,255,233,194,138,255,185,142,83,255,
  175,127,72,255,223,171,124,255,255,212,178,255])
const imageData = new ImageData(arr, 25, 25);

ctx.lineWidth = 2;
ctx.strokeStyle = 'green';
ctx.strokeRect(1, 1, 40, 40);
ctx.putImageData(imageData, 0, 0);
<canvas id="canvas" width="50" height="50" style="border:1px solid #000000;">
</canvas>

I did reduce your image to 25x25 to have less data in the array

Helder Sepulveda
  • 15,500
  • 4
  • 29
  • 56
1

JS Code execution is asynchronous

You are setting the icon before the you have drawn the image.

onLoad event runs asynchronous which means that the onload event will not fire until the current execution has completed.

The problem details

The comments describe what is happening

chrome.webNavigation.onCompleted.addListener(() => { 

  //-------------------------------------------------------------------
  // start of onComplete. JS is blocking and no events will fire while code is executing.

  const canvas = document.createElement('canvas');
  const ctx = ... set up canvas
  const image = new Image();

  image.onload = function() {   // << This will not be called until onCompleted has returned
    ctx.drawImage(image, 0, 0);
  };

  image.src = ... the data URL 

  // You call setIcon before onCompleted has returned and thus there is nothing in the canvas
  chrome.browserAction.setIcon({ imageData: ctx.getImageData(0, 0, 50, 50) });

  // end of. onComplete returns
  //-------------------------------------------------------------------

});

The fix

To fix simply move the setIcon function to the onload event so that it is called after the image has loaded and drawn onto the canvas.

chrome.webNavigation.onCompleted.addListener(() => { 
    const ctx = Object.assign(
             document.createElement('canvas'), {width: 50, height: 50}
        ).getContext("2d");
    const image = new Image();
    image.src = // ... the data URL 
    image.addEventListener("load", () => {
        ctx.drawImage(image, 0, 0);
        chrome.browserAction.setIcon({imageData: ctx.getImageData(0, 0, 50, 50)});
    };
});

You can set the image.src before or after setting the onload as onload will not fire until current execution has completed

Blindman67
  • 51,134
  • 11
  • 73
  • 136