Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get dpi and set quality by specific size #1

Open
akwatra opened this issue Jun 4, 2018 · 1 comment
Open

get dpi and set quality by specific size #1

akwatra opened this issue Jun 4, 2018 · 1 comment

Comments

@akwatra
Copy link

akwatra commented Jun 4, 2018

Hi Joseph,
its seems good, yet i have to try this.
can you implement or suggest to achive with html 5 canvas api

-- how to get the image dpi eg: 300 pixels or 96 so we can .
-- how can we resize image by specify image weight size., as uploaded image of x size and we want to reduce image at spefic jpeg quality 90 or 30 , but still image weight is higher than requirement,
so if we can get what quality param we can get specific image weight size

ex:
upload image : 5mb
set weight : 200kb
get quality param: 10 %

resize( jpeg_quality )
get resize image of what weight we wanted

@jhuckaby
Copy link
Owner

jhuckaby commented Jun 6, 2018

Hello there!

To get the image DPI, you can access the EXIF data via the getEXIF() method call, and examine the XResolution and YResolution properties. Example:

{
	"Make": "Apple",
	"Model": "iPhone 7",
	"Orientation": 1,
	"XResolution": 72,
	"YResolution": 72,
	"ResolutionUnit": 2,
	"Software": "10.3.1",
	"DateTime": "2017:04:29 16:36:23",
	...
}

This example image is 72x72 API. Note that only some images provide this EXIF data, so have a default fallback (72 DPI is typical). Please call this function immediately after loading the image, as most transforms wipe the EXIF data (because they clone and copy/paste the canvas).

For saving images based on a target file size, there is no provided way using the node-canvas library (on the server) or HTML5 Canvas API (on the client). They only allow you to specify the JPEG quality as a percentage number (1 - 100).

The only way I can think to accomplish this is to do a brute-force method. Meaning, save at 50%, measure size, increase or decrease by 25%, measure size, then 12.5%, etc. then either add half or subtract half, and repeat until you get close to your target size. To prevent an infinite loop, only allow 8 iterations or so. Quick example:

var fs = require('fs');
var async = require('async');
var CanvasPlus = require('canvas-plus');
var canvas = new CanvasPlus();

canvas.load('test.jpg', function(err) {
	if (err) throw err;
	
	var target_size = 50 * 1024; // 50KB target
	var idx = 0;
	var max_iterations = 8;
	var current_quality = 50;
	var current_size = 0;
	var current_buffer = null;
	var adjust_by = 25;
	
	async.doWhilst(
		function(callback) {
			// test a save, record size
			canvas.write({format: "jpeg", quality: Math.floor(current_quality)}, function(err, buf) {
				idx++;
				current_buffer = buf;
				console.log( current_quality + '% Quality: ' + buf.length + ' bytes' );
				
				if (buf.length < target_size) {
					current_quality += adjust_by;
					adjust_by /= 2;
				}
				else if (buf.length > target_size) {
					current_quality -= adjust_by;
					adjust_by /= 2;
				}
				else {
					idx = max_iterations;
				}
				
				if (current_quality < 1) current_quality = 1;
				callback();
			});
		},
		function() {
			return( idx < max_iterations );
		},
		function(err) {
			console.log("\nFinal image: " + current_buffer.length + " bytes (" + canvas.get('quality') + "% quality)");
			fs.writeFileSync( 'myimage.jpg', current_buffer );
		}
	); // doWhilst

});

This works on my test image (target: 50K):

50% Quality: 44309 bytes
75% Quality: 67193 bytes
62.5% Quality: 52631 bytes
56.25% Quality: 47946 bytes
59.375% Quality: 50268 bytes
60.9375% Quality: 50980 bytes
61.71875% Quality: 52006 bytes
61.328125% Quality: 52006 bytes

Final image: 52006 bytes (61% quality)

Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants