Image() does not accept width and height - javascript

I ran into a very strange problem. I use the promises method to load images asynchronously and stuff.
loadImage(name, src, width, height) {
return new Promise((resolve, reject) => {
const image = new Image();
this._Assets[name] = image;
image.onload = () => resolve(name);
image.onerror = () => reject(`failed to load ${name}`);
image.src = src;
if (width != void 0) image.width = width;
if (height != void 0) image.height = height;
});
}
As you can see, I am assigning width and height parameters to the image, but it doesn't work. The image has width and height in properties, however the image itself is displayed through the context.drawimage using naturalwidth and naturalheight. However when I try to assign to the image already after the image is loaded. it gives me an error: cannot set property width, but the image itself is cropped. I've tried passing parameters right away to new Image (width, height), but it didn't get anywhere.
If we try to pass parameters in drawimage
assets[`bg`].width
assets[`bg`].height
then everything works

That's normal, CanvasRenderingContext2d.drawImage won't look at all at the width and height attributes of your HTMLImageElement, with only x and y params, it will use the intrinsic dimensions of the source image.
However this method comes with a few different signatures which allow you to set different dimensions:
const image = new Image();
image.src = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
image.onload = e => {
const ctx = document.querySelector( "canvas" ).getContext( "2d" );
ctx.drawImage( image, 0, 0 ); // use intrinsic dimensions
ctx.drawImage( image, 0, 0, 150, 150 ); // take the full source and resize to 150x150
ctx.drawImage( image, 0, 0, 350, 350, 160, 0, 50, 50 ); // take the source rectangle at 0,0,350,350 and draw it in a 50x50 rectangle
}
<canvas id="canvas" width="500" height="500"></canvas>
Note that if you plan to use this Image only for drawing on a canvas, there exists the ImageBitmap interface, which allows you to set the dimensions at construction, but this option is currently only available in Chrome browser, though you could easily write a polyfill returning a resized canvas for other browsers.
(async () => {
const blob = await fetch( "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png" )
.then( (resp) => resp.blob() );
const image = await createImageBitmap( blob, { resizeWidth: 150, resizeHeight: 150 } );
const ctx = document.querySelector( "canvas" ).getContext( "2d" );
ctx.drawImage( image, 0, 0 ); // resized
})().catch( console.error );
<canvas id="canvas" width="500" height="500"></canvas>

Related

Resize image based on X and Y coordinates

I have a Gatsby application using the CMS Contentful. I have implemented Image Focal Point on Contentful which returns x and y coordinates for image cropping. I have tried using HTML Canvas to resize the image based on the coordinates from Image Focal Point but with no luck.
Here is what I have tried:
const resizeImage = (url, width, height, x, y, callback) => {
const canvas = document.createElement("canvas")
const context = canvas.getContext("2d")
const imageObj = new Image()
canvas.width = width
canvas.height = height
imageObj.src = url
imageObj.setAttribute("crossorigin", "anonymous")
imageObj.onload = function () {
context.drawImage(imageObj, x, y, width, height, x, y, width, height)
callback(canvas.toDataURL())
}
return imageObj.src
}
I pass in the url for the image, the width and height of said image, the x and y coordinates from Image Focal Point and a callback:
resizeImage("my-image.png", 1000, 500, 300, 600, (url) => {url})
This returns the same src url as I inputted and does not crop the image to the desired xy coordinates. Any guidance is greatly appreciated!
You may have had security issues, specifically this: for security reasons, your local drive is declared as "other domain" and it will stain the canvas. and for this reason his image was not cropped. I ran into this problem with an image of a server while replicating your code, so be careful.
I generated a codesandbox with your code, let me know if you want to cut the image in this way
const resizeImage = (url, width, height, x, y, callback) => {
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
const imageObj = new Image();
canvas.width = width;
canvas.height = height;
imageObj.src = url;
imageObj.crossOrigin = "anonymous"; //WARNING!
imageObj.onload = () => {
context.drawImage(imageObj, x, y, width, height, 0, 0, width, height);
const url = canvas.toDataURL();
callback(url);
};
};

How to render image on canvas in reactjs

I have added crop image function in my app using react-image-crop but the problem is when i try to crop the image it does not render the right image position on preview I have no idea why. I don't have any experience using canvas before.
This is how My image looks like.
My code to render image on canvas looks something like this.
export function image64toCanvasRef (canvasRef, image64, pixelCrop) {
console.log('imagePixelCrop', pixelCrop);
let canvas = canvasRef // document.createElement('canvas');
canvas.width = pixelCrop.width
canvas.height = pixelCrop.height
const ctx = canvas.getContext('2d')
const image = new Image()
image.src = image64
image.onload = function () {
ctx.drawImage(
image,
pixelCrop.x,
pixelCrop.y,
pixelCrop.width,
pixelCrop.height,
0,
0,
pixelCrop.width,
pixelCrop.height
)
}
}
Here this is i m getting in pixel crop.
aspect: undefined
height: 92.5
unit: "px"
width: 164.5
x: 70
y: 71
https://github.com/DominicTobias/react-image-crop
shows a demo of the same you are trying to acheive have a look
https://codesandbox.io/s/72py4jlll6?file=/src/index.js:1086-1099

Javascript crop image stored in buffer from coordinates

I found code that crops images in javascript using canvas but I need to crop an image that is never actually displayed anywhere since all I need is to get data from the image. There is a screenshot and then the buffered screenshot image needs to be cropped from specific coordinates.
The image is simply stored in a variable to begin with let img = new Image(). How could this code be modified to crop an image stored in the buffer only?
function resizeImage(url, width, height, x, y, callback) {
var canvas = document.createElement("canvas");
var context = canvas.getContext('2d');
var imageObj = new Image();
// set canvas dimensions
canvas.width = width;
canvas.height = height;
imageObj.onload = function () {
context.drawImage(imageObj, x, y, width, height, 0, 0, width, height);
callback(canvas.toDataURL());
};
imageObj.src = url;
}
Since no one answered I will post what I found. In the end I achieved what I needed using the library Sharp's extract feature.
img.onload = resizeImg;
img.src = 'image.png';
function resizeImg() {
this.path = this.path = 'image.png';
sharp(this.path)
.resize(this.width * 2, this.height * 2)
.extract({ width: 100, height: 20, left: 250, top: 100 })
.toBuffer({ resolveWithObject: true })
.then(({ data, info }) => {
//process data
})
}

To cut out the image in Canvas

I have image in Canvas.
const canvas = document.createElement('canvas')
canvas.width = 640
canvas.height = 480
const context = canvas.getContext('2d')
element.appendChild(canvas)
const imageData = context.createImageData(640, 480)
imageData.data.set(new Uint8ClampedArray(data.frame))
context.putImageData(imageData, 0, 0)
I receive data (height, width, x, y).
I want to cut an image from the canvas according to this data and save it as a blob-file.
How can I do this?
You question is unclear. The code example does not match the problem descriptions. As the code example does not work (undefined variable data) I can only go by the description of the problem.
I receive data (height, width, x, y). I want to cut an image from the canvas according to this data and save it as a blob-file. How can I do this?
To cut from Image
To cut a rectangular area from a canvas
function cutArea(fromImage, x, y, width, height) {
const cut = document.createElement("canvas");
cut.width = width;
cut.height = height;
const ctx = cut.getContext("2d");
ctx.drawImage(fromImage, -x, -y);
return cut;
}
You should use an offscreenCanvas but support is limited so add it if you know what your targets are. To create an offscreenCanvas cut
function cutArea(fromImage, x, y, width, height) {
const cut = new OffscreenCanvas(width, height);
const ctx = cut.getContext("2d");
ctx.drawImage(fromImage, -x, -y);
return cut;
}
Note
That the pixel scale is unchanged and that there is not bounds checks. Part or all of the cut image may be empty (0 alpha) if the coordinated do not lay on the image source.
fromImage can be any valid image source, including a canvas.
width and height must be > 0 or the functions will throw an error.
Download
To download the cut to local store as downloaded "image/png" image file. Note filename can be changed by user on download. The image type is the default png. There is no way to know if download is successful.
function downloadCut(cut, name) {
const a = document.createElement("a");
a.download = name + ".png";
const download = blob => {
const url = a.href = URL.createObjectURL(blob);
a.dispatchEvent(new MouseEvent("click", {view: window, bubbles: true, cancelable: true}));
setTimeout(() => URL.revokeObjectURL(url), 1000); // clean up
}
if (cut instanceof OffscreenCanvas) { cut.convertToBlob().then(download) }
else { canvas.toBlob(download) }
}

jpg loaded with python keras is different from jpg loaded in javascript

I am loading jpg image in python on the server. Then I am loading the same jpg image with javascript on the client. Finally, I am trying to compare it with the python output. But loaded data are different so images do not match. Where do I have a mistake?
Python code
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
filename = './rcl.jpg'
original = load_img(filename)
numpy_image = img_to_array(original)
print(numpy_image)
JS code
import * as tf from '#tensorflow/tfjs';
photo() {
var can = document.createElement('canvas');
var ctx = can.getContext("2d");
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
};
img.crossOrigin = "anonymous";
img.src = './rcl.jpg';
var tensor = tf.fromPixels(can).toFloat();
tensor.print()
}
You are drawing the image on a canvas before rendering the canvas as a tensor. Drawing on a canvas can alter the shape of the initial image. For instance, unless specified otherwise - which is the case with your code - the canvas is created with a width of 300 px and a height of 150 px. Therefore the resulting shape of the tensor will be more or less something like the following [150, 300, 3].
1- Using Canvas
Canvas are suited to resize an image as one can draw on the canvas all or part of the initial image. In that case, one needs to resize the canvas.
const canvas = document.create('canvas')
// canvas has initial width: 300px and height: 150px
canvas.width = image.width
canvas.height = image.heigth
// canvas is set to redraw the initial image
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0) // to draw the entire image
One word of caution though: all the above piece should be executed after the image has finished loading using the event handler onload as the following
const im = new Image()
im.crossOrigin = 'anonymous'
im.src = 'url'
// document.body.appendChild(im) (optional if the image should be displayed)
im.onload = () => {
const canvas = document.create('canvas')
canvas.width = image.width
canvas.height = image.heigth
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0)
}
or using async/await
function load(url){
return new Promise((resolve, reject) => {
const im = new Image()
im.crossOrigin = 'anonymous'
im.src = 'url'
im.onload = () => {
resolve(im)
}
})
}
// use the load function inside an async function
(async() => {
const image = await load(url)
const canvas = document.create('canvas')
canvas.width = image.width
canvas.height = image.heigth
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0)
})()
2- Using fromPixel on the image directly
If the image is not to be resized, you can directly render the image as a tensor using fromPixel on the image itself

Categories

Resources