Change JPEG file DPI header in Node.js - node.js

I have a file (for example JPEG size 1588 × 2244px). It's generated by puppeteer (but phantomjs also generate 72 DPI screenshot). When I save this image into a file with .jpeg extension and I use macOS General Info I see:
As you can see it has 72 DPI set in metadata, but I want to use file with 300 DPI. I know, that in digital it doesn't change anything - it's property for printing, but I don't want to explain to each customer that this file could be print in 300 DPI.
When I use Gimp and Image > Print Size
I can change the DPI, and export a picture again. And now it has 300 DPI in General Info window.
I try to do it in Node.JS server, but I found few options to change this property on .PNG pictures, but anyone is working for .JPEG files.
I think that the most accurate option is to use method changeDpiDataUrl from this library:
https://github.com/shutterstock/changeDPI/blob/master/src/index.js
But when I put my image as base64image, after a split operation I have the array with 1 element only - I think that this is body, so I don't have format property (at 63 line).
Anybody meet this problem before?

You can use the library piexifjs to change the EXIF data of an image. The library only changes the meta data (called EXIF), not the image itself.
Code Sample
The following code uses the API to read the EXIF data of an image, change it and create a new buffer from the changed data.
const piexif = require("piexifjs");
// get the image buffer from puppeteer or from disk
const imageBuffer = /* ... */
// convert buffer to string and load it
const imageString = imageBuffer.toString('binary');
const exif = piexif.load(imageString);
// change resolution
exif['0th'][piexif.ImageIFD.XResolution] = [300,1];
exif['0th'][piexif.ImageIFD.YResolution] = [300,1];
// generate new EXIF data
const newExifDump = piexif.dump(exif);
// generate new image
const newData = piexif.insert(newExifDump, imageString);
const jpgBuffer = new Buffer(newData, "binary");
// write to file or use buffer
// ...
Be aware, that I have not used the library myself, nor have I tested the code.

This solution is another alternative to the answer given by #thomasdondorf.
The resolution/density can be set easily using JavaScript standard image processing library sharp by withMetadata function.
Simple example:
// Set output metadata to 96 DPI
const data = await sharp(input)
.withMetadata({ density: 96 })
.toBuffer();
Npm module: sharp

Related

SVG in PPT( generated by Pptxgenjs) shown incorrectly when the PPT is opened in libreOffice

Pptxgenjs is able to add SVG images and generate PPT correctly. When this PPT is opened using Microsoft office, SVG images are shown properly. However, when this PPT is opened using libreOffice, SVG images are shown as invalid cross symbols as mentioned below.
ENV: Windows 10
LibreOffice Version 7
Am I missing something here?
You can try using Aspose.Slides Cloud SDK for Node.js to add SVG images and other content to your presentations. You can evaluate this REST-based API making 150 free API calls per month for API learning and presentation processing. The following code example shows you how to add an SVG image to a presentation using Aspose.Slides Cloud:
const cloud = require("asposeslidescloud")
const model = require("asposeslidescloud/model")
const fs = require("fs")
const slidesApi = new cloud.SlidesApi("client_id", "client_key")
const fileName = "example.pptx"
const imagePath = "image.svg"
const slideIndex = 1
// Create a picture frame for the SVG image with a specified size and position.
var pictureFrame = new model.PictureFrame()
pictureFrame.pictureFillFormat = new model.PictureFill()
pictureFrame.pictureFillFormat.svgData = fs.readFileSync(imagePath, "utf8")
pictureFrame.X = 20
pictureFrame.Y = 20
pictureFrame.Width = 300
pictureFrame.Height = 200
// Add the picture frame on the slide.
slidesApi.createShape(fileName, slideIndex, pictureFrame).then((response) => {
console.log(JSON.stringify(response))
})
I work as a Support Developer at Aspose.

Using rotate for images leads to blank pdf with pdfkit

I have asked the question on the repository directly, but in my experience SO is more reactive.
Hey there,
I am trying to create a pdf from photos using pdfkit.
Depending on whether an image is in landscape or portait mode, I want to turn the image around.
This basically means the following (in typescript) :
function toPostscriptPoint(mm: number) {
return mm * 2.8346456693;
}
const document = new PDFDocument({
size: [toPostscriptPoint(156), toPostscriptPoint(106)],
});
document.pipe(fs.createWriteStream('output.pdf'));
document.save();
document.rotate(90);
document.image(
'photos/sample.jpeg',
{ width: toPostscriptPoint(150), fit: [toPostscriptPoint(150), toPostscriptPoint(100)] });
document.restore();
document.end();
What happens though is that the pdf renders completely white. I do see however that something is happening, because the pdf has the size of the input image.
Is rotation for images not supported? What would be possible alternatives? I would like to avoid having to rewrite my files before putting them in the pdf.
Thanks
Alright, after investigation, I can answer my own question :).
I could see that the images were in the pdf somehow because of the size of the file so I dived deeper.
What happened was that the image was rendered out of the viewport. This was due to multiple things:
By default, the origin of a page after rotation in pdfkit is the center of the page! ( See the doc for more info)
The origin is rotated together with the transformation.
The x and y in the image method are actually inverted.
So after getting all this right, the following code shows the image as expected :
function toPostscriptPoint(mm: number) {
return mm * 2.8346456693;
}
const document = new PDFDocument({
size: [toPostscriptPoint(156), toPostscriptPoint(106)],
});
document.pipe(fs.createWriteStream('output.pdf'));
document.save();
document.rotate(90, {origin : [0, 0]});
document.image(
'photos/sample.jpeg',
toPostscriptPoint(0),
toPostscriptPoint(-150),
{ width: toPostscriptPoint(150), height: toPostscriptPoint(100) });
document.restore();
document.end();
Note the :
origin argument in the rotation
toPostscriptPoint(-150) actually takes into account the position of the origin, and corresponds to the X axis.
Hope that helps some later on :).
Its because taking picture from camera , if picture ISO is less than 100 it will be automatically rotated , take picture with iso more than or equal to 100 to avoid autorotation.

Poor quality jpeg resize on GD library use. Wrong steps?

So I have the following script to resize an incoming jpg and save it to the server in a new size. The created jpg file has terrible quality, even when I am making the quality 90 on the imagejpeg. I am wondering if I am messing it up earlier in my efforts.
// Get new sizes
list($width, $height) = getimagesize($filename);
$percentW=298/$width;
$newwidth = $width * $percentW;
$newheight = $height * $percentW;
// Creating a blank canvas to put the new file. Is this an extra step?
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($filename);
// Now I create the resized photo with the needed width and height on the blank canvas with the source file resized
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// Output to server, define 90% quality. My guess is the quality is destroyed before now.
imagejpeg($thumb,"../../uploads/buckets/" . $_POST["bucket"] . "/" .$fileNameBucket,90);
imagedestroy($thumb);
Am I messing up the quality before I even output the file to the server? Should I use resample instead of resize? I am stuck with using the GD library so ImageMagick is not an option. Thanks.

view RGBA image

Can someone tell me how can I view an RGBA image? I just want a tool that I can display an RGBA image with!
I have written a code, which outputs only RGBA format. I just want to verify if my code worked, and just want to find a simple tool to view this image.
I wasn't able to come across a software to be able to display a RGBA image.
Thanks in advance.
RGBA files only contain raw channel data. The binary data will not have enough information to display an image (ie. width,height,depth, &tc).
If you know the image dimensions of each .rgba file, you should be able to work with the data. Here's an example of viewing raw date in javascript.
var fr = new FileReader(),
myWidth = 200,
myHeight = 200;
fr.onload = function(frEvent) {
var canvasElement = document.getElementById("myCanvas"),
ctx = canvasElement.getContext("2d"),
blob = ctx.createImageData(myWidth,myHeight),
index = 0;
while(index < frEvent.target.result.length)
blob.data[index] = frEvent.target.result.charCodeAt(index++);
ctx.putImageData(blob,0,0);
}
Imagemagick will be able to display raw RGBA data. Assuming that each color sample is 8 bits.
display -size 200x200 -depth 8 mySimpleData.rgba

trying to extract formatted images from indesign into a separate folder

I'm looking for a way to extract images from an ID file in a 'formatted' / cropped form.
i.e: a. I have placed numerous, hi-res (tiff, psd) images into an InDesign CS5 file
b. The image boxes that they have been placed into, are smaller than the actual image (pretty intense cropping occurred) c. I am trying to collect these images in their new stage (cropped to the image box) and export them as jpg at 72dpi.
Are there any plug-ins out there that would automatically collect "formatted" images from ID for me? Or is there some other way?
If you're familiar with Indesign Scripting, this can very easily be done via a script. I use Javascript but this can be done with VBSript or AppleScript as well. Here is a basic example of a script that will open a document, and export a rectangle (your image box) as a JPG. Basically, you can just loop through the pictures in your document and export each one to a location/filename you choose (see the myFile variable below). There are several "jpegExportPreferences" you can pick from to determine how your output JPG will be (i.e. DPI).
test();
function test(){
var myDoc = app.open('c:/user/desktop/testDocument.indd');
var myGroups = myDoc.groups;
//for each group...
for (var i = 0;i < myGroups.length; i++){
// for each rectangle in the group...
for(var r = 0; r< myGroups[i].rectangles.length; r++){
var myRect = myGroups[i].rectangles[r];
app.jpegExportPreferences.exportResolution = 300;
app.jpegExportPreferences.jpegQuality = JPEGOptionsQuality.MAXIMUM;
//give it a unique name
var myFile = new File('c:/users/desktop/newJPG' + myRect.id + '.jpg');
myRect.exportFile(ExportFormat.JPG, myFile);
}
}
}
For a list of the other optional JPG Export preferences, see this link:
http://indesignscriptingreference.com/cs2/javascript-cs2/jpegexportpreference.htm
Hope this helps!

Resources