Tips for enlarging small ImageData onto a larger HTML canvas

I am facing an issue with placing image data of size 100x100 onto a canvas of size 1000x1000. Despite my efforts, I have not been able to achieve the desired result.

let width=1000;      //canvas width
let height=1000;    //canvas height
let img_w=100;      //image width
let img_h=100;      //image height
let img=new Image();
img.width=img_w
img.height=img_h
img.src="./flower.jpg"
var canvas = document.getElementById('mycanvas');
var context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
let pixels,scannedimg;
img.onload=()=>{
context.drawImage(img, 0, 0,width,height );
scannedimg = context.getImageData(0, 0, img.width, img.height);
pixels=scannedimg.data
console.log(pixels)
redraw();
}

let row=4*img_w;
let col=img_h;

function redraw(){
    for(let i=0;i<row;i+=4){
        for(let j=0;j<col;j++){
            pixels[i+j*row]=0;
            pixels[i+j*row+1]=0;
            pixels[i+j*row+2]=0;
            //pixels[i+j*400+3]=0;
        }
    }
   scannedimg.data=pixels;
    console.log(scannedimg);
    context.putImageData(scannedimg,0,0,0,0,width,height);
}

Although I managed to transform the original array into a black image array (an array of zeros), when placed on the canvas, it remains as 100x100. How can I scale it to 1000x1000 without manually iterating through each pixel?

Answer №1

Opting to delegate the pixel calculations to a WebAssembly module could significantly improve the performance when working with large images, as relying solely on JavaScript may result in slower processing.

I am unclear about the functionalities present in your code.

Initially, you are rendering an unknown-sized .jpg onto a 1000x1000 canvas, which may lead to scaling and distortion of the image if the .jpg is not also 1000x1000 in size.

let width=1000;
let height=1000; 
context.drawImage(img, 0, 0, width, height);

Subsequently, you are extracting pixel data from a 100x100 area at the top-left corner of your 1000x1000 canvas.

let img_w=100;
let img_h=100;
img.width=img_w;
img.height=img_h;
scannedimg = context.getImageData(0, 0, img.width, img.height);

Lastly, within your redraw() function, you are randomly setting some pixels to black and attempting to draw it back to the canvas at 1000x1000, which needs a different approach (to be discussed later).

Let's consider an alternative approach. For instance, assuming we have a 300x200 image, the initial step would involve drawing it onto a 100x100 canvas while preserving its aspect ratio to obtain the 100x100 imagedata. This can be achieved using an off-screen dynamically created <canvas> element that does not necessitate display.

The challenging aspect lies in the CanvasRenderingContext2D putImageData() method. It seems like you assumed that the last pair of parameters specifying the width & height would stretch the existing pixel data to fill the specified region (x, y, width, height). However, this is not the case. Instead, we must once again paint the 100x100 pixel data onto a same-sized off-screen canvas (or reuse the existing one for simplicity) and then draw it onto the final canvas using the drawImage() method.

All these steps can be combined as follows:

let pixelsWidth = 100;
let pixelsHeight = 100;
let finalWidth = 500;
let finalHeight = 500;
let tempCanvas = document.createElement('canvas');
let tempContext = tempCanvas.getContext('2d');
tempCanvas.width = pixelsWidth;
tempCanvas.height = pixelsHeight;
let pixelData;
let img = new Image();
img.crossOrigin = 'anonymous';
img.onload = (e) => {
  let scale = e.target.naturalWidth >= e.target.naturalHeight ? pixelsWidth / e.target.naturalWidth : pixelsHeight / e.target.naturalHeight;
  let tempWidth = e.target.naturalWidth * scale;
  let tempHeight = e.target.naturalHeight * scale;
  tempContext.drawImage(e.target, pixelsWidth / 2 - tempWidth / 2, pixelsHeight / 2 - tempHeight / 2, tempWidth, tempHeight);
  pixelData = tempContext.getImageData(0, 0, pixelsWidth, pixelsHeight);
  redraw();
}
img.src = 'https://picsum.photos/id/237/300/200';

function redraw() {
  let canvas = document.getElementById('canvas');
  let context = canvas.getContext('2d');
  canvas.width = finalWidth;
  canvas.height = finalHeight;
  tempContext.putImageData(pixelData, 0, 0);
  context.drawImage(tempCanvas, 0, 0, finalWidth, finalHeight);
}
canvas {
  background: #cccccc;
}
<canvas id="canvas"></canvas>

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

Is it possible to align a div on the same line with an h1 header that spans multiple lines using CSS?

I am currently working on the following code: <h1><span>Test Heading This is the text that I want to display on the right side. This is the text that I want to display on the right side. This is the text that I want</span></h1> < ...

Ways to activate the built-in HTML5 form validation without actually submitting the form

I have a form in my application that I plan to submit using AJAX. However, I would like to implement HTML5 for client-side validation. Is it possible to trigger form validation without actually submitting the form? Here is an example of the HTML code: &l ...

Inability to successfully upload batch data within specified criteria using a keyword and conditional statement

My goal is to batch the data, using "Repair" as a separator for the data. Splitting criteria = Repair Copper limit = 2.5 [ {"engineSN":"20","timeRun":"30","Cu":"2"}, {"engineSN": ...

The function causes changes to an object parameter once it has been executed

I've encountered an issue with a function that is supposed to generate a string value from an object argument. When I call this function and then try to use the argument in another function, it seems to be getting changed somehow. Here is the code fo ...

Tips for sorting data based on duplicate dates within a single array element

Here is the existing Object Array structure: [ { "date":"12-09-2019 12:00 PM", "id":"1", "name":"hello1" }, { "date":"12-09-2019 03:00 PM", "id":"2", "name":"hello2" }, { "date":"12- ...

SVG fails to render in the browser upon page initialization

I am experiencing difficulties with rendering SVG icons in Google Chrome and other browsers when added through CSS on my website, specifically in a custom dropdown background. Here is a sample of the SVG code: background: #fff url("data:image/svg+xml ...

Tips for extracting data from a PHP loop and displaying it in a div element

When I click on a PHP while loop, I want to change the value of a div. Here is my PHP code: <?php $query = mysql_query("select * from tbl_sub_product where product_id='$id'"); while($row=mysql_fetch_array($query)) { ?> <div>< ...

jQuery fails to fetch information

I am currently working with a straightforward script as shown below: $(function() { var url = theme_directory + '/func/api.php'; $.get( url, function(data) { alert("Data Loaded: " + data); }); }); Here is the code for api ...

Accept only hexadecimal color codes as user input

How can I create a variable in JavaScript that only accepts color codes such as rgba, hashcode, and rgb? I need a solution specifically in javascript. ...

Make an ajax request to a method in YII framework

I need to send an AJAX call to a function within the directory structure outlined below: Yii::$app->request->absoluteUrl."protected/humhub/modules/post/controllers/PostController/UploadMusicFile"; Here is my view function: function uploadImage ...

Any modifications made to a copied object will result in changes to the original object

The original object is being affected when changes are made to the cloned object. const original = { "appList": [{ "appId": "app-1", "serviceList": [{ "service": "servic ...

The jsonGenerator is unable to process strings containing spaces

Hey, I'm having trouble passing a string with whitespaces to my JavaScript function using jsonGenerator. Here's the code snippet: jGenerator.writeStringField(cols[8], ap.getContentId() != null ? "<img src='img/active.png' onclick=au ...

Information displays instantly in the initial milliseconds

When developing dynamic web pages with Nuxt, I encountered an issue in the pages directory where a file named _url.vue is located. The contents of this file are as follows: <template lang="pug"> div component( v-for= ...

Utilizing Mysql Joins with parameterized queries in Node.js: A Comprehensive Guide

Currently, I am utilizing Node.js and Express.js for my project. In particular, I am incorporating the "mysql2 library" into my development process. My current task involves concatenating and joining queries with parameters in a secure manner. How can I ...

JavaScript and HTML with Node.js

Exploring the world of HTML, running smoothly with a static IP address 192.168.56.152 using apache on the host computer. <!DOCTYPE html> <html > <head> <title>OnlinePage</title> <meta charset="utf-8"& ...

What is the best way to choose an item from a dropdown menu using JavaScript?

Is there a way to set the dropdown value from the client side? Currently, I am loading countries and states using a countries.js file on grid row selection for updating. However, because it is loaded from the client side, I am unable to load country and st ...

Error occurred due to an unexpected end of JSON input following a pending promise

I am currently developing a data handler that requires downloading a file for parsing and processing within the handler. To handle this, I have implemented the file request within a promise and called it asynchronously from other methods. Including the h ...

Ensure that clicking on an element closes any currently visible elements before opening a new element

Take a look at my code snippet below. I am working on creating multiple clickable divs that reveal different content when clicked. However, the issue I am facing is that currently, both content blocks can be displayed simultaneously. My goal is to have onl ...

Maintain Vue Router Query Parameters Across Parent Components

In my application, I have a component named Foo, which serves as the template for a route called app/foo. Within this component, there are child components that also act as templates for routes such as app/foo/bar and app/foo/baz. I've implemented a ...

Ways to personalize Angular's toaster notifications

I am currently utilizing angular-file-upload for batch file uploads, where I match file names to properties in a database. The structure of the files should follow this format: 01-1998 VRF RD678.pdf VRF represents the pipeline name RD represents the lo ...