Skip to content

Commit e025ddc

Browse files
author
Samuel Huylebroeck
committed
Fix nullpointer for transform functions in separation
Type 0 and Type 4 functions pass a PdfStream and not a PdfDictionnary Separation CS can contain a function, which can be a stream as well Add tests DEVSIX-1663
1 parent 2ba74d0 commit e025ddc

File tree

4 files changed

+123
-11
lines changed

4 files changed

+123
-11
lines changed

pdfa/src/main/java/com/itextpdf/pdfa/PdfAConformanceException.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,11 @@ public class PdfAConformanceException extends PdfException {
146146
public static final String TheSmaskKeyIsNotAllowedInXobjects = "The smask key is not allowed in xobjects";
147147
public static final String TheValueOfInterpolateKeyShallNotBeTrue = "The value of interpolate key shall not be true";
148148
public static final String TheValueOfTheMethEntryInColrBoxShallBe123 = "The value of the meth entry in colr box shall be 123";
149+
//TODO(DEVSIX-1672): remove in 7.1
150+
@Deprecated
149151
public static final String TintTransformAndAlternateSpaceOfSeparationArraysInTheColorantsOfDeviceNShallBeConsistentWithSameAttributesOfDeviceN = "TintTransform and alternateSpace of separation arrays in the colorants of deviceN shall be consistent with same attributes of deviceN";
152+
//TODO(DEVSIX-1672): move to LogConstants
153+
public static final String WarningTintTransformAndAlternateSpaceOfSeparationArraysInTheColorantsOfDeviceNShallBeConsistentWithSameAttributesOfDeviceN = "WARNING: TintTransform and alternateSpace of separation arrays in the colorants of deviceN is not consistent with same attributes of deviceN";
150154
public static final String TintTransformAndAlternateSpaceShallBeTheSameForTheAllSeparationCSWithTheSameName = "TintTransform and alternateSpace shall be the same for the all separation cs with the same name";
151155
public static final String TransparencyIsNotAllowedCAShallBeEqualTo1 = "Transparency is not allowed. CA shall be equal to 1";
152156
public static final String TransparencyIsNotAllowedCaShallBeEqualTo1 = "Transparency is not allowed. ca shall be equal to 1";

pdfa/src/main/java/com/itextpdf/pdfa/checker/PdfA2Checker.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ This file is part of the iText (R) project.
7070
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
7171
import com.itextpdf.pdfa.PdfAConformanceException;
7272
import com.itextpdf.kernel.pdf.PdfAConformanceLevel;
73+
import org.slf4j.Logger;
74+
import org.slf4j.LoggerFactory;
7375

7476
import java.util.ArrayList;
7577
import java.util.Arrays;
@@ -107,6 +109,8 @@ public class PdfA2Checker extends PdfA1Checker {
107109

108110
private Map<PdfName, PdfArray> separationColorSpaces = new HashMap<>();
109111

112+
private static final Logger LOGGER = LoggerFactory.getLogger(PdfA2Checker.class);
113+
110114

111115
/**
112116
* Creates a PdfA2Checker with the required conformance level
@@ -188,7 +192,7 @@ public void checkColorSpace(PdfColorSpace colorSpace, PdfDictionary currentColor
188192
if (colorants != null) {
189193
for (Map.Entry<PdfName, PdfObject> entry : colorants.entrySet()) {
190194
PdfArray separation = (PdfArray) entry.getValue();
191-
checkSeparationInsideDeviceN(separation, ((PdfArray) deviceN.getPdfObject()).get(2), ((PdfArray) deviceN.getPdfObject()).get(3).getIndirectReference());
195+
checkSeparationInsideDeviceN(separation, ((PdfArray) deviceN.getPdfObject()).get(2), ((PdfArray) deviceN.getPdfObject()).get(3));
192196
}
193197
}
194198
if (checkAlternate) {
@@ -817,29 +821,34 @@ private void checkBlendMode(PdfName blendMode) {
817821
}
818822
}
819823

820-
private void checkSeparationInsideDeviceN(PdfArray separation, PdfObject deviceNColorSpace, PdfIndirectReference deviceNTintTransform) {
824+
private void checkSeparationInsideDeviceN(PdfArray separation, PdfObject deviceNColorSpace, PdfObject deviceNTintTransform) {
821825
if (!isAltCSIsTheSame(separation.get(2), deviceNColorSpace) ||
822-
!deviceNTintTransform.equals(separation.getAsDictionary(3).getIndirectReference())) {
823-
throw new PdfAConformanceException(PdfAConformanceException.TintTransformAndAlternateSpaceOfSeparationArraysInTheColorantsOfDeviceNShallBeConsistentWithSameAttributesOfDeviceN);
826+
!deviceNTintTransform.equals(separation.get(3))) {
827+
LOGGER.warn(PdfAConformanceException.WarningTintTransformAndAlternateSpaceOfSeparationArraysInTheColorantsOfDeviceNShallBeConsistentWithSameAttributesOfDeviceN);
824828
}
825829

826830
checkSeparationCS(separation);
827831
}
828832

829833
private void checkSeparationCS(PdfArray separation) {
830834
if (separationColorSpaces.containsKey(separation.getAsName(0))) {
831-
boolean altCSIsTheSame = false;
832-
boolean tintTransformIsTheSame = false;
835+
boolean altCSIsTheSame;
836+
boolean tintTransformIsTheSame;
833837

834838
PdfArray sameNameSeparation = separationColorSpaces.get(separation.getAsName(0));
835839
PdfObject cs1 = separation.get(2);
836840
PdfObject cs2 = sameNameSeparation.get(2);
837841
altCSIsTheSame = isAltCSIsTheSame(cs1, cs2);
842+
// TODO(DEVSIX-1672) in fact need to check if objects content is equal. ISO 19005-2, 6.2.4.4 "Separation and DeviceN colour spaces":
843+
// In evaluating equivalence, the PDF objects shall be compared, rather than the computational
844+
// result of the use of those PDF objects. Compression and whether or not an object is direct or indirect shall be ignored.
845+
PdfObject f1Obj = separation.get(3);
846+
PdfObject f2Obj = sameNameSeparation.get(3);
847+
//Can be a stream or dict
848+
boolean bothAllowedType = (f1Obj.getType() == f2Obj.getType()) && (f1Obj.isDictionary() || f1Obj.isStream());
849+
//Check if the indirect references are equal
850+
tintTransformIsTheSame = bothAllowedType && f1Obj.equals(f2Obj);
838851

839-
PdfDictionary f1 = separation.getAsDictionary(3);
840-
PdfDictionary f2 = sameNameSeparation.getAsDictionary(3);
841-
//todo compare dictionaries or stream references
842-
tintTransformIsTheSame = f1.getIndirectReference().equals(f2.getIndirectReference());
843852

844853
if (!altCSIsTheSame || !tintTransformIsTheSame) {
845854
throw new PdfAConformanceException(PdfAConformanceException.TintTransformAndAlternateSpaceShallBeTheSameForTheAllSeparationCSWithTheSameName);
@@ -855,7 +864,9 @@ private boolean isAltCSIsTheSame(PdfObject cs1, PdfObject cs2) {
855864
if (cs1 instanceof PdfName) {
856865
altCSIsTheSame = cs1.equals(cs2);
857866
} else if (cs1 instanceof PdfArray && cs2 instanceof PdfArray) {
858-
//todo compare cs dictionaries or stream reference
867+
// TODO(DEVSIX-1672) in fact need to check if objects content is equal. ISO 19005-2, 6.2.4.4 "Separation and DeviceN colour spaces":
868+
// In evaluating equivalence, the PDF objects shall be compared, rather than the computational
869+
// result of the use of those PDF objects. Compression and whether or not an object is direct or indirect shall be ignored.
859870
altCSIsTheSame = ((PdfArray) cs1).get(0).equals(((PdfArray) cs1).get(0));
860871
}
861872
return altCSIsTheSame;

pdfa/src/test/java/com/itextpdf/pdfa/PdfA2GraphicsCheckTest.java

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,26 @@ This file is part of the iText (R) project.
4747
import com.itextpdf.kernel.color.ColorConstants;
4848
import com.itextpdf.kernel.color.DeviceCmyk;
4949
import com.itextpdf.kernel.color.DeviceGray;
50+
import com.itextpdf.kernel.color.DeviceN;
51+
import com.itextpdf.kernel.color.Separation;
5052
import com.itextpdf.kernel.font.PdfFont;
5153
import com.itextpdf.kernel.font.PdfFontFactory;
5254
import com.itextpdf.kernel.pdf.PdfAConformanceLevel;
55+
import com.itextpdf.kernel.pdf.PdfArray;
5356
import com.itextpdf.kernel.pdf.PdfDictionary;
5457
import com.itextpdf.kernel.pdf.PdfName;
5558
import com.itextpdf.kernel.pdf.PdfNumber;
5659
import com.itextpdf.kernel.pdf.PdfOutputIntent;
60+
import com.itextpdf.kernel.pdf.PdfPage;
5761
import com.itextpdf.kernel.pdf.PdfWriter;
5862
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
5963
import com.itextpdf.kernel.pdf.canvas.PdfCanvasConstants;
6064
import com.itextpdf.kernel.pdf.colorspace.PdfCieBasedCs;
65+
import com.itextpdf.kernel.pdf.colorspace.PdfColorSpace;
66+
import com.itextpdf.kernel.pdf.colorspace.PdfDeviceCs;
67+
import com.itextpdf.kernel.pdf.colorspace.PdfSpecialCs;
6168
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
69+
import com.itextpdf.kernel.pdf.function.PdfFunction;
6270
import com.itextpdf.kernel.utils.CompareTool;
6371
import com.itextpdf.kernel.xmp.XMPException;
6472
import com.itextpdf.test.ExtendedITextTest;
@@ -75,6 +83,7 @@ This file is part of the iText (R) project.
7583
import java.io.IOException;
7684
import java.io.InputStream;
7785
import java.net.MalformedURLException;
86+
import java.util.Collections;
7887

7988
import static org.junit.Assert.fail;
8089

@@ -500,6 +509,82 @@ public void transparencyCheckTest3() throws FileNotFoundException, XMPException
500509
doc.close();
501510
}
502511

512+
@Test
513+
public void colourSpaceTest01() throws FileNotFoundException {
514+
PdfWriter writer = new PdfWriter(new com.itextpdf.io.source.ByteArrayOutputStream());
515+
InputStream is = new FileInputStream(sourceFolder + "sRGB Color Space Profile.icm");
516+
PdfADocument doc = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_2B, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", is));
517+
PdfPage page = doc.addNewPage();
518+
519+
PdfColorSpace alternateSpace= new PdfDeviceCs.Rgb();
520+
//Tint transformation function is a stream
521+
byte[] samples = {0x00,0x00,0x00,0x01,0x01,0x01};
522+
PdfArray domain = new PdfArray(new float[]{0,1});
523+
PdfArray range =new PdfArray(new float[]{0,1,0,1,0,1});
524+
PdfArray size = new PdfArray(new float[]{2});
525+
PdfNumber bitsPerSample = new PdfNumber(8);
526+
527+
PdfFunction.Type0 type0 = new PdfFunction.Type0(domain,range,size,bitsPerSample,samples);
528+
PdfColorSpace separationColourSpace = new PdfSpecialCs.Separation("separationTestFunction0",alternateSpace,type0);
529+
//Add to document
530+
page.getResources().addColorSpace(separationColourSpace);
531+
532+
doc.close();
533+
}
534+
535+
@Test
536+
public void colourSpaceTest02() throws FileNotFoundException {
537+
PdfWriter writer = new PdfWriter(new com.itextpdf.io.source.ByteArrayOutputStream());
538+
InputStream is = new FileInputStream(sourceFolder + "sRGB Color Space Profile.icm");
539+
PdfADocument doc = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_2B, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", is));
540+
PdfPage page = doc.addNewPage();
541+
542+
PdfColorSpace alternateSpace= new PdfDeviceCs.Rgb();
543+
//Tint transformation function is a dictionary
544+
PdfArray domain = new PdfArray(new float[]{0,1});
545+
PdfArray range =new PdfArray(new float[]{0,1,0,1,0,1});
546+
PdfArray C0 = new PdfArray(new float[]{0,0,0});
547+
PdfArray C1 = new PdfArray(new float[]{1,1,1});
548+
PdfNumber n = new PdfNumber(1);
549+
550+
PdfFunction.Type2 type2 = new PdfFunction.Type2(domain,range,C0,C1,n);
551+
PdfColorSpace separationColourSpace = new PdfSpecialCs.Separation("separationTestFunction2",alternateSpace,type2);
552+
//Add to document
553+
page.getResources().addColorSpace(separationColourSpace);
554+
doc.close();
555+
}
556+
557+
@Test
558+
public void colourSpaceTest03() throws FileNotFoundException {
559+
PdfWriter writer = new PdfWriter(new com.itextpdf.io.source.ByteArrayOutputStream());
560+
InputStream is = new FileInputStream(sourceFolder + "sRGB Color Space Profile.icm");
561+
PdfADocument doc = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_2B, new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", is));
562+
PdfPage page = doc.addNewPage();
563+
564+
PdfColorSpace alternateSpace= new PdfDeviceCs.Rgb();
565+
//Tint transformation function is a dictionary
566+
PdfArray domain = new PdfArray(new float[]{0,1});
567+
PdfArray range =new PdfArray(new float[]{0,1,0,1,0,1});
568+
PdfArray C0 = new PdfArray(new float[]{0,0,0});
569+
PdfArray C1 = new PdfArray(new float[]{1,1,1});
570+
PdfNumber n = new PdfNumber(1);
571+
572+
PdfFunction.Type2 type2 = new PdfFunction.Type2(domain,range,C0,C1,n);
573+
574+
PdfCanvas canvas = new PdfCanvas(page);
575+
String separationName = "separationTest";
576+
canvas.setColor(new Separation(separationName, alternateSpace, type2, 0.5f), true);
577+
578+
PdfDictionary attributes = new PdfDictionary();
579+
PdfDictionary colorantsDict = new PdfDictionary();
580+
colorantsDict.put(new PdfName(separationName), new PdfSpecialCs.Separation(separationName, alternateSpace,type2).getPdfObject());
581+
attributes.put(PdfName.Colorants, colorantsDict);
582+
DeviceN deviceN = new DeviceN(new PdfSpecialCs.NChannel(Collections.<String>singletonList(separationName), alternateSpace, type2, attributes), new float[]{0.5f});
583+
canvas.setColor(deviceN, true);
584+
585+
doc.close();
586+
}
587+
503588
private void compareResult(String outPdf, String cmpPdf) throws IOException, InterruptedException {
504589
String result = new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff_");
505590
if (result != null) {

pdfa/src/test/java/com/itextpdf/pdfa/PdfA2PageCheckTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,30 @@ This file is part of the iText (R) project.
4343
package com.itextpdf.pdfa;
4444

4545
import com.itextpdf.io.source.ByteArrayOutputStream;
46+
import com.itextpdf.kernel.color.Color;
47+
import com.itextpdf.kernel.color.DeviceN;
48+
import com.itextpdf.kernel.color.Separation;
4649
import com.itextpdf.kernel.pdf.PdfAConformanceLevel;
50+
import com.itextpdf.kernel.pdf.PdfArray;
4751
import com.itextpdf.kernel.pdf.PdfDictionary;
4852
import com.itextpdf.kernel.pdf.PdfName;
53+
import com.itextpdf.kernel.pdf.PdfNumber;
4954
import com.itextpdf.kernel.pdf.PdfOutputIntent;
5055
import com.itextpdf.kernel.pdf.PdfPage;
5156
import com.itextpdf.kernel.pdf.PdfWriter;
57+
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
58+
import com.itextpdf.kernel.pdf.colorspace.PdfColorSpace;
59+
import com.itextpdf.kernel.pdf.colorspace.PdfDeviceCs;
60+
import com.itextpdf.kernel.pdf.colorspace.PdfSpecialCs;
61+
import com.itextpdf.kernel.pdf.function.PdfFunction;
5262
import com.itextpdf.test.ExtendedITextTest;
5363
import com.itextpdf.test.annotations.type.IntegrationTest;
5464
import com.itextpdf.kernel.xmp.XMPException;
5565

5666
import java.io.FileInputStream;
5767
import java.io.FileNotFoundException;
5868
import java.io.InputStream;
69+
import java.util.Collections;
5970

6071
import org.junit.Rule;
6172
import org.junit.Test;
@@ -82,4 +93,5 @@ public void catalogCheck01() throws FileNotFoundException, XMPException {
8293

8394
doc.close();
8495
}
96+
8597
}

0 commit comments

Comments
 (0)