I've been working on embedding an ICC profile (AdobeRGB1998.icc) into a PDF file. Despite multiple attempts using various tools, I'm unable to get the ICC profile to show up in the metadata. What I want to achieve is to show ICC Profile Tags in metadata as shown in following screenshot:
I've spent countless hours and tried the following approaches: PDFBox Java Code
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class EmbedICCWithPDFBox {
public static void main(String[] args) {
if (args.length != 3) {
System.err.println("Usage: java EmbedICCWithPDFBox <pdfPath> <outputPdfPath> <iccPath>");
return;
}
String pdfPath = args[0];
String outputPdfPath = args[1];
String iccPath = args[2];
try {
embedICCProfile(pdfPath, outputPdfPath, iccPath);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void embedICCProfile(String pdfPath, String outputPdfPath, String iccPath) throws IOException {
PDDocument document = PDDocument.load(new File(pdfPath));
try (FileInputStream iccStream = new FileInputStream(iccPath)) {
PDStream iccPDStream = new PDStream(document, iccStream);
iccPDStream.addCompression();
PDOutputIntent outputIntent = new PDOutputIntent(document, iccPDStream);
outputIntent.setInfo("sRGB IEC61966-2.1");
outputIntent.setOutputCondition("sRGB IEC61966-2.1");
outputIntent.setOutputConditionIdentifier("sRGB IEC61966-2.1");
outputIntent.setRegistryName("http://www.color.org");
document.getDocumentCatalog().addOutputIntent(outputIntent);
System.out.println("ICC profile embedded successfully.");
}
document.save(outputPdfPath);
document.close();
}
}
iText Java Code
import com.itextpdf.kernel.pdf.*;
import java.io.FileInputStream;
import java.io.IOException;
public class EmbedICCWithIText {
public static void embedICCProfile(String pdfPath, String outputPdfPath, String iccPath) throws IOException {
PdfDocument pdfDoc = new PdfDocument(new PdfReader(pdfPath), new PdfWriter(outputPdfPath));
try (FileInputStream iccStream = new FileInputStream(iccPath)) {
byte[] iccProfileBytes = iccStream.readAllBytes();
PdfStream iccPdfStream = new PdfStream(iccProfileBytes);
iccPdfStream.put(PdfName.N, new PdfNumber(3));
iccPdfStream.put(PdfName.Length, new PdfNumber(iccProfileBytes.length));
iccPdfStream.put(PdfName.Filter, PdfName.FlateDecode);
PdfDictionary outputIntentDict = new PdfDictionary();
outputIntentDict.put(PdfName.Type, PdfName.OutputIntent);
outputIntentDict.put(PdfName.S, PdfName.GTS_PDFA1);
outputIntentDict.put(PdfName.OutputConditionIdentifier, new PdfString("AdobeRGB (1998)"));
outputIntentDict.put(PdfName.OutputCondition, new PdfString("Adobe RGB (1998)"));
outputIntentDict.put(PdfName.Info, new PdfString("Adobe RGB (1998)"));
outputIntentDict.put(PdfName.DestOutputProfile, iccPdfStream);
PdfArray outputIntents = new PdfArray();
outputIntents.add(outputIntentDict);
pdfDoc.getCatalog().put(PdfName.OutputIntents, outputIntents);
System.out.println("ICC profile embedded successfully.");
}
pdfDoc.close();
}
public static void main(String[] args) {
if (args.length != 3) {
System.err.println("Usage: java EmbedICCWithIText <pdfPath> <outputPdfPath> <iccPath>");
return;
}
String pdfPath = args[0];
String outputPdfPath = args[1];
String iccPath = args[2];
try {
embedICCProfile(pdfPath, outputPdfPath, iccPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
GhostScript Command
gswin64c.exe -o C:/ghost/output_done_Ghostscript.pdf -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sProcessColorModel=DeviceRGB -sOutputICCProfile=C:/ghost/AdobeRGB1998.icc -dEmbedAllFonts=true -dSubsetFonts=true -dMaxSubsetPct=100 -dPDFX=true -dCompatibilityLevel=1.4 C:/ghost/test1_no_xref.pdf
Issue: Despite the reported successful embedding, the ICC profile is not being detected by ExifTool:
exiftool.exe -G1 "C:/PDFWorkFlow/output_done_PDFBox.pdf"
What might be causing the ICC profile not to embed correctly in the PDF? Are there any additional steps or alternative methods that I can try to ensure the ICC profile is embedded and detectable? Any insights or suggestions would be greatly appreciated. Thank you!
I found an ICC profile in your file here: Root/Pages/Kids/[0]/Resources/ColorSpace/DefaultRGB/[1]
. That's one of many places where icc profiles can appear. In this file the author redefined the default RGB colorspace.
This code for PDFBox 2.0 / jdk11 adds that icc profile as default RGB to every page:
public static void addDefaultRGB(String pdfPath, String outputPdfPath, String iccPath) throws IOException
{
byte[] iccProfileData;
try (InputStream is = new FileInputStream(iccPath))
{
iccProfileData = is.readAllBytes();
}
try (PDDocument document = PDDocument.load(new File(pdfPath)))
{
PDICCBased iccColorSpace = new PDICCBased(document);
PDStream pdStream = iccColorSpace.getPDStream();
try (OutputStream outputStream = pdStream.createOutputStream(COSName.FLATE_DECODE))
{
outputStream.write(iccProfileData);
}
pdStream.getCOSObject().setInt(COSName.N, 3);
pdStream.getCOSObject().setItem(COSName.ALTERNATE, COSName.DEVICERGB);
for (PDPage page : document.getPages())
{
PDResources resources = page.getResources();
if (resources == null)
{
resources = new PDResources();
page.setResources(resources);
}
resources.put(COSName.DEFAULT_RGB, iccColorSpace);
}
document.save(outputPdfPath);
}
}