I am learning chrome extension development and trying to create a tool to capture crosshair screenshot. I use chrome.tabs.captureVisibleTab API to get the screenshot of whole visible area.
Now, I want to crop that visible area to what user selected using crosshair cursor. To crop that, I use HTML5 Canvas’s drawImage method. But for some reason, drawImage gives me blurry output

This is my cropping function:
function cropImage(
src: string,
cropArea: { left: number; top: number; width: number; height: number }
): Promise<HTMLCanvasElement> {
return new Promise((resolve, reject) => {
const { left, top, width, height } = cropArea;
const img = document.createElement('img');
img.src = src;
img.onload = function () {
// TODO: remove this: just for testing
document.body.appendChild(img);
try {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
const devicePixelRatio = window.devicePixelRatio || 1;
ctx.drawImage(
img,
left * devicePixelRatio,
top * devicePixelRatio,
width * devicePixelRatio,
height * devicePixelRatio,
0,
0,
width,
height
);
resolve(canvas);
} catch (error) {
reject(error);
}
};
img.onerror = function (event, source, lineno, colno, error) {
reject(error);
};
});
}
This code is responsible for rendering the cropped Image:
const canvas = await cropImage(response.imgSrc, {
left: left - window.scrollX,
top: top - window.scrollY,
width,
height,
});
const croppedImg = new Image();
const croppedSrc = canvas.toDataURL('image/jpeg', 1.0);
croppedImg.src = croppedSrc;
document.body.appendChild(croppedImg);
Checking other stackoverflow questions with similar issues, I tried some suggestions:
ctx.imageSmoothingEnabled = false;
But it does not work.
I hereby agree that I have researched thoroughly before asking this question, so I don’t think this is a duplicate of some other question. Please feel free to reach out incase if you think that this question is 100% duplicate of some other question.
Note: I think it will be helpful to mention that I am using Macbook Pro on which I get window.devicePixelRatio = 2.