Creating artwork: How to resize images without losing clarity

Struggling to display an image in a canvas element that needs to be a certain percentage of its parent container's width. Despite my efforts, the image seems to blur once added to the canvas, which is not the desired effect.

I attempted to disable the blurring by setting

ctx.imageSmoothingEnabled = false
, but unfortunately, it did not solve the issue.

If anyone has suggestions on how to prevent image blurring within this canvas, I would greatly appreciate any insights!

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>

Answer №1

Understanding the Difference Between Canvas Resolution and Display Size

Upon examining the image, it appears to be 444px by 800px in size, indicating a low resolution. The actual display of the image will vary depending on the device used.

In your query, you have specified the canvas display width as 60% of the container's size, while setting the canvas resolution to 444px by 800px.

It is probable that the display width and the canvas resolution do not align.

Distinguishing Canvas Display Size and Resolution

  • canvas.style.width and canvas.style.height define the area on the page that the image occupies and are unrelated to the canvas resolution.

Understanding Canvas Resolution

  • The properties canvas.width and canvas.height indicate the pixel resolution of the canvas, representing the actual number of pixels used to store the image data.

Dealing with Browser-Induced Blur

If the canvas is stretched over a larger area than its resolution, browsers may introduce blurring effects due to the scaling discrepancy.

To prevent this blur, apply the CSS attribute image-rendering: pixelated; as shown in the example below.

// JavaScript code for handling image rendering
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.drawImage(this, 0, 0);
}
.big {
  width:100%;
  image-rendering: pixelated;
}
<canvas class="big" id="canvas"></canvas>

Enhancing Two-Tone Black & White Images

For low-resolution two-tone images, improving quality can be challenging. However, you can increase contrast to reduce blurriness caused during rendering.

Utilize screen and color-burn composite operations to enhance the left half of the image with better contrast while maintaining a less pixelated appearance.

// JavaScript code for enhancing contrast in B/W images
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 the image to canvas 
  ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
  // Apply composite operations to improve contrast
  // Additional processing steps omitted here for brevity
}
.big {
  width:100%;
}
<canvas class="big" id="canvas"></canvas>

Answer №2

It's hard to say if this is exactly what you're looking for, but I was taken aback by the top: -1000% value. In this scenario, when the container has a "position: relative" property, the percentage-based properties of its children will be relative to the parent element.

let image = new Image();
image.src = 'https://example.com/image.jpg';

image.onload = function() { 
  let canvas = document.querySelector('canvas');
  canvas.width = hidden.clientWidth;
  canvas.height = hidden.clientHeight;
  let 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://example.com/image.jpg' id='hidden'>
  <canvas></canvas>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be causing my callback function to fail when used within a nested function?

I am currently utilizing the callback function in conjunction with Socket.io as shown below: loadData(callback) { var client = new SyncClient(this.socket, this.project); this.client = client; //From my data function client.on("connected", () => { ...

Retrieve a result by utilizing a nested function in conjunction with the request NPM module

Hello there! I'm currently working on scraping data from the ghost blogging platform using the request package. However, I've run into a bit of a roadblock when trying to return a value of a nested request. I've pinpointed the area that seem ...

Configuring timezone for 'date' type in Plotly.js

I'm currently working on a graph to showcase the trend over time. The data I have is in Unix format and I use JavaScript code (new Date(data)).toUTCString to display it in my title. Surprisingly, while the data for the graph and the title is the same, ...

Customize Your Greasemonkey Script Timeout

At our organization, we utilize the Firefox Greasemonkey addon to automatically enter login credentials on a specific webpage upon opening it. Here is an example of what the script consists of: // ==UserScript== // @name logon // @namespace http ...

Tips for successfully passing an object as a prop in nextjs

Struggling to understand how to pass an object as a prop using useState in Next JS. My javascript functions include a lorem ipsum generator, housed in a component called Paragraphs. This component requires two properties: Number of paragraphs Sentence le ...

The same size background effect

I am looking to create a list of names that are all the same size. How can I achieve this using Bootstrap? <ul class="list-unstyled"> <li> <a class="btn btn-xs btn-warning"> <span >Loren ipsum</span> </a> ...

Is the first child component of Material UI Stack not properly aligned?

Is there a CSS issue that needs fixing? I am working on creating a vertical list of checkboxes with labels using the <Stack /> component from Material UI. I have tried implementing this in the sandbox provided (check out demo.tsx): https://codesandb ...

The collapse of HTML elements converging inwards within the Bulma Framework and customized with SASS

Messy Screen Recently delving into the world of Bulma, I decided to take a shot at customizing my CSS. Unfortunately, it seems that after some tweaking, my screen layout has gone haywire. Can anyone shed light on why two elements might refuse to maintain ...

Tips for hiding a soft keyboard with jQuery

Here is a text button: <input type="text" class="field" id="something" name="something" placeholder="text" autofocus /> I want to prevent the android soft keyboard from popping up and keep the focus on this field. I only want to do this for this ...

Iterate through an HTML table and transfer matching items along with their corresponding calculated amounts to a separate table

<html> <body> <div> <table border="1" id="topTable"> <thead> <th>Item</th> <th>Sold</th> </thead> <tbody id="topTableBody"> <tr> ...

"Encountering an error of undefined index when dealing with multiple file

I've encounter an issue with this code but can't seem to figure out what's wrong. Any help would be greatly appreciated. Kindly refrain from marking it as a duplicate too quickly; I've already gone through similar questions without find ...

React Navigation Item Toolbar Misplacement

I've been trying to align the navigation item with the logo on the same line within the toolbar, but I'm facing an issue where they keep appearing in different rows. To see the error for yourself, check out the code sandbox here. This is how I s ...

What is the best way to pass a module from the controller to a Jade/Pug template and then use it as an argument in an event handler within the template?

I passed the module 'naija' to a template from the controller in this way: res.render('testing', {title:"filter setting page", nigeria:naija }); The func ...

What is the best way to reset the column filter cell in Material-Table?

Within my Material-Table, I am utilizing this unique TextField to craft a specialized filter cell for each column. My goal is to employ the endAdornment as a button that will reset the filter, but I am struggling with removing the current value. filterCom ...

Discovering the top method to locate an Error Modal Message using Selenium

I am looking to automate a specific process that involves an Error modal popping up. I am trying to use Selenium to capture this modal which appears in multiple instances. So far, I have attempted to locate it by XPath without success. Using CSS selector o ...

What could be causing my Vue component to not refresh?

Can anyone help me figure out why this component isn't re-rendering after changing the value? I'm attempting to create a dynamic filter similar to Amazon using only checkboxes. Here are the 4 components I have: App.vue, test-filter.vue, filtersIn ...

Having trouble with the sx selector not functioning properly with the Material UI DateTimePicker component

I'm currently working with a DateTimePicker component and I want to customize the color of all the days in the calendar to match the theme color: <DateTimePicker sx={{ "input": { color: "primary.main&quo ...

What is the best way to convert a Nextjs page into a PDF file?

I am currently working on a page structure that looks like this: export default function FichaTecnica(props) { const data = props.data; return ( <> <Container> <TopData info={data} /> <DataSheet datasheet= ...

Conflicts in SwiperJS Timeline Management

Having a Timeline on my Website using SwiperJS presents challenges with conflicting functions. The goal is to navigate swiper-slides by clicking on timespans in the timeline. The desired functionality for the timeline includes: Sliding to the correspondi ...