简体   繁体   中英

Canvas: Resizing image without blurring

I'm trying to represent an image in a canvas, and wish for the canvas to be a certain percent of its parent container's width. The trouble is I'm somehow blurring the image when adding it to the canvas, and I don't want to blur the image.

I thought adding ctx.imageSmoothingEnabled = false would disable the blurring, but it doesn't appear to be helping.

Does anyone know how I can prevent the image below from blurring in this canvas? Any thoughts would be greatly appreciated!

 var img = new Image(); img.src = 'https://gist.githubusercontent.com/duhaime/019f2ccb98391adbf460a10463059683/raw/c4c2bc1fa923d905aba0ef88e05c0760823d2cca/000630070000650.jpg'; img.onload = function() { var canvas = document.querySelector('canvas'); canvas.width = hidden.clientWidth; canvas.height = hidden.clientHeight; var ctx = canvas.getContext('2d'); ctx.webkitImageSmoothingEnabled = false; ctx.mozImageSmoothingEnabled = false; ctx.imageSmoothingEnabled = false; ctx.drawImage(hidden, 0, 0, this.naturalWidth, this.naturalHeight, 0, 0, hidden.clientWidth, hidden.clientHeight) } 
 #container { width: 800px; background: #efefef; } #hidden { position: absolute; top: -1000%; } #hidden, #canvas { width: 60%; } 
 <div id='container'> <img src='https://gist.githubusercontent.com/duhaime/019f2ccb98391adbf460a10463059683/raw/c4c2bc1fa923d905aba0ef88e05c0760823d2cca/000630070000650.jpg' id='hidden'> <canvas></canvas> </div> 

Canvas resolution and display size are not the same.

Looking at the image I see it is 444px by 800px in size which is very low resolution. How it displays will very much depend on the display device.

You have in your question, set the canvas display width to 60% of the containers size and the canvas resolution you have set to the image (444by800).

It is very likely that the display width and the canvas resolution do not match.

Canvas display size

  • canvas.style.width and canvas.style.height represent the area on the page the image will fill and have nothing to do with the canvas resolution.

Canvas resolution

  • canvas.width and canvas.height properties represent the resolution of the canvas in pixels, the actual number of pixels used to store the image content

Browser is adding the blur.

Assuming the 60% (for #hidden {width : 60%} ) is of a HD display 1920px wide the canvas will be stretched over 60% * 1920 = 1152px which is 2.6 times larger than the canvas.

The canvas content is not blurred, you have drawn the image correctly. It is the browser that is rendering the canvas onto the page at a size larger than the the canvas resolution that is adding the blurring.

Simple fix

To stop the browser from blurring the content of the canvas use the CSS attribute image-rendering: pixelated; as in the example below.

 var img = new Image(); img.src = 'https://gist.githubusercontent.com/duhaime/019f2ccb98391adbf460a10463059683/raw/c4c2bc1fa923d905aba0ef88e05c0760823d2cca/000630070000650.jpg'; img.onload = function() { canvas.width = this.naturalWidth canvas.height = this.naturalHeight var ctx = canvas.getContext('2d'); // ctx.imageSmoothingEnabled = false; // not needed as you are not streaching the image ctx.drawImage(this, 0, 0); } 
 .big { width:100%; image-rendering: pixelated; } 
 <canvas class="big" id="canvas"></canvas> 

Simple sharpen two tone B/W.

The image is very low resolution so there is not much you can do to improve the quality in most cases.

But as it is a two tone Black & White (not black, grays, and white) you can stretch it out on a larger canvas and increase the contrast to remove some of the blurring introduced when rendered to the canvas.

It is done by using the screen and color-burn composite operations to render the canvas on top of itself several times. Contrast is increase to reduce the blur yet keeping a less pixelated look.

To highlight the difference Only the left half of the image has been sharpened using this method.

 var img = new Image(); img.src = 'https://gist.githubusercontent.com/duhaime/019f2ccb98391adbf460a10463059683/raw/c4c2bc1fa923d905aba0ef88e05c0760823d2cca/000630070000650.jpg'; img.onload = function() { const bounds = canvas.getBoundingClientRect(); //Get the canvas display sise canvas.width = bounds.width; canvas.height = this.naturalHeight * (bounds.width / this.naturalWidth); var ctx = canvas.getContext('2d'); // draw to canvas ctx.drawImage(this, 0, 0,canvas.width,canvas.height); // draw again using screen to up white areas ctx.globalCompositeOperation = "screen"; ctx.drawImage(canvas, 0, 0,canvas.width/ 2,canvas.height,0, 0,canvas.width/ 2,canvas.height); // draw again to pukl grays down some ctx.globalCompositeOperation = "color-burn"; ctx.drawImage(canvas, 0, 0,canvas.width/ 2,canvas.height,0, 0,canvas.width/ 2,canvas.height); // draw again using screen to up white areas ctx.globalCompositeOperation = "screen"; ctx.globalAlpha = 0.5; ctx.drawImage(canvas, 0, 0,canvas.width/ 2,canvas.height,0, 0,canvas.width/ 2,canvas.height); // draw again to pukl grays down some ctx.globalAlpha = 1; ctx.globalCompositeOperation = "color-burn"; ctx.drawImage(canvas, 0, 0,canvas.width/ 2,canvas.height,0, 0,canvas.width/ 2,canvas.height); } 
 .big { width:100%; } 
 <canvas class="big" id="canvas"></canvas> 

I'm not sure this is what you need, but I was surprised by the top: -1000%. If, for example, in this case, the container gives "position: relative" the properties of the children with% will be relative to the parent.

 var img = new Image(); img.src = 'https://gist.githubusercontent.com/duhaime/019f2ccb98391adbf460a10463059683/raw/c4c2bc1fa923d905aba0ef88e05c0760823d2cca/000630070000650.jpg'; img.onload = function() { var canvas = document.querySelector('canvas'); canvas.width = hidden.clientWidth; canvas.height = hidden.clientHeight; var ctx = canvas.getContext('2d'); ctx.webkitImageSmoothingEnabled = false; ctx.mozImageSmoothingEnabled = false; ctx.imageSmoothingEnabled = false; ctx.drawImage(hidden, 0, 0, this.naturalWidth, this.naturalHeight, 0, 0, hidden.clientWidth, hidden.clientHeight) } 
 #container { width: 800px; background: #efefef; position:relative; } #hidden { position: absolute; top: 0; right: 0; } #hidden, canvas { width: 50%; } 
 <div id='container'> <img src='https://gist.githubusercontent.com/duhaime/019f2ccb98391adbf460a10463059683/raw/c4c2bc1fa923d905aba0ef88e05c0760823d2cca/000630070000650.jpg' id='hidden'> <canvas></canvas> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM