I'm implementing a graphic related web app and I want to detect the image resolution and validate if the user is uploading an image with too low DPI
How can I achieve this?
Is there a library for this?
Is there a solution in HTML 5 canvas for this, or in Konvajs (HTML canvas library)
Is there any image up-loader that supports determining uploaded image resolution?
Most modern file uploaders will give you access to image dimensions, or you can use a filereader to load the image into a hidden dom image object and get the sizes that way. Example in this SO question.
But they will not tell you if the image is suitable for your intended use. You have to do some math yourself to decide that.
To decide if an image is going to be acceptable, we need to start with the target. We need to know the final output DPI and the measured dimensions. I will look at the width only but the same calculations work for the height too. Example DPI's, for a PC screen the DPI is 96, for a decent inkjet printer it might be up to 4800 by 1200. Commercial printing ranges from 300 to 2400.
Next we need to know the target region size - in other words a measurement. I will use inches here to keep things simple.
The calculation we need to do is:
Image size dots / (target size inches * DPI)
This produces the image scaling that is needed to fit the image in the target space. If the image dot size is twice the size of the target then the scale is 0.5, if the image dot size is 3 times the target then the scale is 3.
Next we need to know the acceptable range of scaling for the image. This is arbitrary and depends on the circumstances in hand.
Let's take an example - making a business card 3.5 ins x 2 ins where we want to put an uploaded picture on the back. We are printing at 300 DPI. The user uploads an image that is 800px wide. I will ignore aspect ratio to keep it simple.
The calculation we need to complete is -
Perfect image dot size would be: 3.5 ins x 300 DPI = 1050 dots.
Scaling of image to target = 800 / 1050 = 0.76
Assume acceptable scale range of 0.8x - 4x.
Conclusion: The image is not suitable because the scale from step 2 is outside the range defined in step 3.
Related
This question already has answers here:
Display pixel-perfect canvas on all devices
(3 answers)
Closed last month.
Is it possible to set the size of the bitmap in an HTML5 canvas so that it exactly matches the display size in device pixels, ie the number of physical pixels used to display the canvas, even when window.devicePixelRatio is not an integer?
There is a good description of how to resize the canvas on webglfundamentals but it does not properly handle non-integer devicePixelRatios. My understanding so far:
The display size of the canvas is set in CSS with, eg, canvas {width: 200px;}.
The underlying bitmap size is set with, eg, <canvas width="100"/> in HTML or canvas.width = 100 in JS.
The bitmap will be stretched to fit the CSS size (how is affected by object-fit and object-position).
We can set bitmap size to be equal to some expression involving canvas.clientWidth.
canvas.clientWidth is an integer and its unit are CSS pixels and is the calculated width of the content (plus padding). I don't know if the browsers actually draw the content into a whole number of CSS pixels or a whole number of device pixels.
So webglfundamentals suggests something like
canvas.width = Math.floor(canvas.clientWidth * window.devicePixelRatio);
but if window.devicePixelRatio is a fraction, this sometimes doesn't work (2 pixel wide lines drawn on integer coordinates are fuzzy). My 1920x1080 screen has devicePixelRatio of 1.5 by default, and page zoom can affects this, so lots of reasons why devicePixelRatio is not an integer as a rule. What can we do?
1px is a logical length unit in CSS/DOM realm. Dot.
So I don't think that you will find reliable method for getting physical pixels. Check this.
That's why in Sciter I've made px units to represent always physical pixels of the device. And introduced dip units that are logical pixels - 1/96 of inch measured by the ruler on device surface (so 1dip ~ 1px of W3C CSS).
I simply do not understand how to do serious UI development without the ability to define objects in device pixels.
I know this is an old thread, but I hope I can help a bit any other wanderer coming to this.
There is a way to make a "canvas pixel" match "device pixel" as close to a 1:1 ratio as possible, at least from my experience while making a Canvas WebGL based game engine, even with non-integer devicePixelRatio values.
First, there are 3 things we need to understand:
CSS Size: Refers to the actual Canvas DOM element size in CSS pixel (px) units.
Canvas Size: Logical size of the canvas, as set using the element properties (i.e. canvasElem.width = 100;), this affects your render space.
Device Pixel Ratio: Value obtained from window which effectively describes the ratio between a physical pixel and a CSS pixel.
Brief Example
Let's say you have a devicePixelRatio of 2.625, and your mobile device reports a screen/window size of 411 x 487 -a weird size- you might say, but that is in CSS pixel units, if we multiply those by the devicePixelRatio we get a size of 1078 x 1278 which tells us that most likely the device screen is actually a 1080 x 1280 screen, as originally advertised by your favorite phone manufacturer.
Now, to size stuff...
Say we want a canvas filling the whole screen. Set your CSS Size match the screen size (or any box size you want).
canvas.style.width = '411px';
canvas.style.height = '487px';
Now set the Canvas Size to the same but scaled-up by devicePixelRatio:
canvas.width = 411 * window.devicePixelRatio;
canvas.height = 487 * window.devicePixelRatio;
Now you can render your images.
When the browser calculates the layouts, it will have to scale-down your canvas to make it fit in its DOM rectangle area, the down-scale factor is cssSize / canvasSize yielding a down-scale factor of 1 / devicePixelRatio.
And then when the browser needs to render the layout to physical screen, it will scale it up by devicePixelRatio, thus leaving a total scaling of 1.0.
TL;DR
Supersampling. Scale up your canvas logical size by devicePixelRatio while keeping your CSS size at whatever size you need, and let the browser do the rest.
NOTE: If your rendering expects the canvas to be of certain size, and this "scaling up" messes up your layout and/or calculations, use the canvas setTransform method to scale down your "logical units" by 1.0 / devicePixelRatio, no quality is loss at all.
I am under the impression that JPEGs cannot store resolution/DPI/density information. How is it possible that iOS Image Preview is able to provide resolution per image attached?
The reason I ask is that I need to alter the resolution to a specific number so that when I send the image to a 3rd party API, they know how many pixels per inch to print. I only allow image uploads in JPEG/PNG format.
Any solutions in javascript would be greatly appreciated
Thanks!
You have to change the values from pixels to inches and then set the dimensions. The resolution for full hd images is 1024 or 720 pixels per inch
I'm creating a HTML5 upload plugin (I'll link to it when it is completed) that reads an image from the file system, and then displays the image onto a canvas. I then read the canvas data and send it up to a server for processing.
Displaying the image on a canvas smaller than the original image dimension shrinks the file size down. What I noticed was that for a canvas of dimension 1024 x 768, the file size was the same for an input file of 5MB and an input file of 100+MB (around 1.1MB), which leads me to the question I ask today!
In uncompressed form, yes - in compressed form no, not necessarily.
In compressed form content is the dominating factor as well as type of compression. The more high-frequency signal the image has (noise, details) the harder the image is to compress, so two images of the same dimension can be compressed to two different sized depending on the content.
One small image with high frequencies can become larger than a large dimension image with low frequency (blurred, noise-free etc.).
If you get an image with large size after compression you can use low-pass filtering on it (ie. here: blur it a bit).
The image dimension is directly proportional to the image size. If you are processing the image before sending it to the server and resizing it then your no doubts your image size is going to be affected.
I found that images are resized in all kind of actions, e.g. by opening a jpg file and writing it back again, by using your PC's encoder which may give a different result than the original encoder did. I am still looking for a way to prevent that! So it seems logical that using a canvas and reading the image from there also changes the file size. I assume these links may help you further:
HTML5 canvas: image resizing
Html5 Canvas resize
Dick
I'm looking to create a system where users create an image in canvas on their browser (with the help of paper.js or processing.js etc) and be able to print a large (up to A3, 300dpi ideally) size representation of what they have created in canvas.
Obviously exporting images straight from the canvas element in the users browser I'm limited to screen size and resolution etc.
So I've looked into the solution of momentarily scaling up the canvas element when the users saves and capturing the image data at the larger size. This could be a solution but I'm pretty sure file size would get out of hand pretty quickly at larger sizes.
I haven't used Node.js very much but was wondering if anyone with experience would know if Node could achieve this and if it would be a better solution and briefly how I'd go about it?
I see two ways to achieve what you want :
use an oversized canvas, that you scale with css.
For instance, you can have a 1000X1000 canvas, that you show within a 200pxX200px smaller view.
<canvas width=1000 height=1000
style = 'width:200px; height:200px;' id='cv'>
</canvas>
use a small canvas for display on screen, and really draw on a backing canvas, that you reproduce on the view canvas at each change.
Both solution cannot solve the issue that mouse coordinates are integer, so to implement a 'pixel perfect' location of object you'll have to implement some kind of zooming. Second solution might be simpler for this.
To retrieve the mouse coordinates, with css scaling do not forget to multiply them by the scale, and in case 2, by the scale you decided.
// formula to get the css scale :
var cssScaleX = canvas.width / canvas.offsetWidth;
var cssScaleY = canvas.height / canvas.offsetHeight;
// then mouse coords are to be multiplied by the scale :
// mouse.x *= cssScaleX;
I tried quickly both solutions, and i was quite surprised to see that css solution is very slow (in both Ch and FF), and it seems faster to copy a back canvas than to have css doing it.
Maybe it depends on some quality settings, but it seems solution 2 is both more flexible and faster.
first css version is here (move mouse to draw 10X10 rect) :
http://jsbin.com/kegohufu/1/
second back canvas + copy version is here (move mouse to draw 10X10 rect) :
http://jsbin.com/qomiqoqi/1/
I am trying to load a HTML file that does one thing: display an image on a canvas element that is auto-resized and auto-rescaled to the maximum dimensions for the device in question.
For example:
User presses button on device.
Device opens WebKit/WebView to http://some.url/page.html.
That page shows image.png in the maximum height/width proportion possible on said device.
Requirements:
Actual HTML file should only contain a canvas element within the body.
Image path should be dynamic and the width/height interpreted after the file has been loaded.
No third party dependencies.
I took a stab at this here, but am running into problems: http://jsfiddle.net/zfG2B/
if (scaledHeight < scaledWidth) {
_config.newImgHeight = _cache.canvas.height;
_config.newImgWidth = Math.round(_config.newImgHeight * _config.imgWidthRatio);
} else if (scaledWidth < scaledHeight) {
_config.newImgWidth = _cache.canvas.width;
_config.newImgHeight = Math.round(_config.newImgWidth * _config.imgHeightRatio);
}
The code I've cobbled together (above, and see jsfiddle) kind of works, but I can only get it to rescale based on the height. Any ideas on what I've done wrong or the best path forward?
For reference, I've attempted to join together the best of:
HTML5 Canvas Resize (Downscale) Image High Quality?
Scaling HTML5 canvas width preserving w/h aspect ratio
Resizing an image in an HTML5 canvas
HTML5 Canvas drawImage ratio bug iOS
scaling a canvas element and keeping the aspect ratio
So here's the question: what's the best way to place an Image on a Canvas in HTML5 and make it auto-rescale based on the current screen size? Bonus points for being able to specify a clipping range!