Copy link to clipboard
Copied
Hi, does anyone know how I can get a png to save with an embedded color profile using a .jsx script?
I've tried using pngSaveOptions but embedColorProfile = true; doesn't seem to be supported with that.
I then tried using SaveForWeb which did embed the profile but it also reduced the ppi to 72 when I need it to stay at 300ppi.
It seems strange that pngSaveOptions can't do it because when I manually save as, there is an option to embed the color profile and it exports exactly how I need it to.
Here are the png options that I ideally want for reference.
Thanks in advance.
Mikey
I've added a little bit extra to my script to reopen the SaveForWeb png and then it sets it to 300ppi.
Thanks very much for all your help guys! Much appreciated.
For anyone that wants to reference this in the future. Here is the script. It saves the png in a folder called PNG where the filepath of the original psd file is. It's a little frustrating that the ppi needs to be set to 300 but i'm just working to a spec.
var doc = app.activeDocument;
var doc_path = doc.path;
var fullName = doc.name;
var myF
Copy link to clipboard
Copied
What Ps version are you using? There was a long-standing bug with ICC in PNG in older versions.
Copy link to clipboard
Copied
I'm using Photoshop 2023, V24.6.0
Copy link to clipboard
Copied
It was fixed in v2022 I believe.
You can use AM code, as a generic example:
var docName = activeDocument.name.replace(/\.[^\.]+$/, '');
try {
var outputPath = activeDocument.path.fsName;
} catch (e) {
var outputPath = Folder.selectDialog("Unsaved base file, select the output folder:");
}
saveAsPNG(6, new File(outputPath + "/" + docName + ".png"), true);
function saveAsPNG(compression, savePath, copy) {
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
descriptor2.putEnumerated( s2t( "method" ), s2t( "PNGMethod" ), s2t( "quick" ));
descriptor2.putEnumerated( s2t( "PNGInterlaceType" ), s2t( "PNGInterlaceType" ), s2t( "PNGInterlaceNone" ));
descriptor2.putEnumerated( s2t( "PNGFilter" ), s2t( "PNGFilter" ), s2t( "PNGFilterAdaptive" ));
descriptor2.putInteger( s2t( "compression" ), compression );
descriptor2.putEnumerated( s2t( "embedIccProfileLastState" ), s2t( "embedOff" ), s2t( "embedOn" ));
descriptor.putObject( s2t( "as" ), s2t( "PNGFormat" ), descriptor2 );
descriptor.putPath( s2t( "in" ), savePath );
descriptor.putInteger( s2t( "documentID" ), 219 );
descriptor.putBoolean( s2t( "copy" ), copy );
descriptor.putBoolean( s2t( "lowerCase" ), true );
executeAction( s2t( "save" ), descriptor, DialogModes.NO );
}
Copy link to clipboard
Copied
Thanks very much for this! I've just tried it out but the new png file on my desktop still seems to be opening up with an untagged color profile.
Copy link to clipboard
Copied
It obviously works for me!
I have tested with Photoshop, Apple Preview and ExifTool. They all show the same profile embedded in the PNG.
Copy link to clipboard
Copied
Ah that's really odd. Apple preview is showing that it has the profile, but when I open it back in photoshop, it's untagged.
Copy link to clipboard
Copied
Profile embedding in Save As PNG has been buggy forever - it has taken different forms over the years, but there always seems to be something not working properly. I have no idea why it's so difficult to fix this.
Save For Web consistently works correctly, so that's what I always use when I need PNGs.
To be clear, SFW does not change ppi to 72. What it does is strip the ppi value from the file altogether. The 72 number just appears as a default value when the file is reopened into Photoshop.
It should be possible to retain the ppi number by setting metadata to All. In reality, of course, it doesn't really matter. Not one image pixel is affected by it. If yo're running a script, you might be able to insert a function that assigns 300 later.
Copy link to clipboard
Copied
To be clear, SFW does not change ppi to 72. What it does is strip the ppi value from the file altogether. The 72 number just appears as a default value when the file is reopened into Photoshop.
By @D Fosse
Agreed, in fact, the PNG specification is actually based on PIXELS PER METRE! Photoshop opens and rounds to the nearest PPI value when the units are inches, but the value written is in PPM.
Copy link to clipboard
Copied
I've added a little bit extra to my script to reopen the SaveForWeb png and then it sets it to 300ppi.
Thanks very much for all your help guys! Much appreciated.
For anyone that wants to reference this in the future. Here is the script. It saves the png in a folder called PNG where the filepath of the original psd file is. It's a little frustrating that the ppi needs to be set to 300 but i'm just working to a spec.
var doc = app.activeDocument;
var doc_path = doc.path;
var fullName = doc.name;
var myFileName = fullName.replace(/.[^.]+$/, '');
var defaultRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
var options = new ExportOptionsSaveForWeb();
options.format = SaveDocumentType.PNG;
options.transparency = true;
options.includeProfile = true;
options.PNG8 = false;
options.optimization = false;
options.interlaced = false;
// Check for folder
var pngf = new Folder(doc_path + "/PNG");
if (!pngf.exists) {
pngf.create();
}
var outputFile = new File(doc_path + "/PNG/" + myFileName + ".png");
// Check if a file with the same name already exists and delete it
if (outputFile.exists) {
outputFile.remove();
}
// Export the document using the ExportOptionsSaveForWeb
doc.exportDocument(outputFile, ExportType.SAVEFORWEB, options);
// Close the currently open document
doc.close(SaveOptions.DONOTSAVECHANGES);
// Reopen the exported PNG file
var reopenedDoc = app.open(outputFile);
// Set the DPI to 300 PPI
reopenedDoc.resizeImage(null, null, 300, ResampleMethod.NONE);
// Save and close the document
reopenedDoc.save();
reopenedDoc.close(SaveOptions.SAVECHANGES);
Copy link to clipboard
Copied
Yeah I think that might be a good solution if the save as option keeps on giving me grief.
Copy link to clipboard
Copied
I do most of my scripting in 2021.
But for this, I tested in 2022.
I haven't tested in 2023 yet.