Skip to content

Commits on Source 8

libsambox-java (1.1.41-1) unstable; urgency=medium
* New upstream version 1.1.41.
* Switch to compat level 11.
* Declare compliance with Debian Policy 4.2.1.
-- Markus Koschany <apo@debian.org> Fri, 12 Oct 2018 12:55:01 +0200
libsambox-java (1.1.19-1) unstable; urgency=medium
* New upstream version 1.1.19.
......
......@@ -5,7 +5,7 @@ Maintainer: Debian Java Maintainers <pkg-java-maintainers@lists.alioth.debian.or
Uploaders:
Markus Koschany <apo@debian.org>
Build-Depends:
debhelper (>= 10),
debhelper (>= 11),
default-jdk,
junit4,
libbcmail-java,
......@@ -15,7 +15,7 @@ Build-Depends:
libsejda-io-java (>= 1.1.3-2),
libslf4j-java (>= 1.7.25),
maven-debian-helper (>= 2.1)
Standards-Version: 4.1.1
Standards-Version: 4.2.1
Vcs-Git: https://anonscm.debian.org/git/pkg-java/libsambox-java.git
Vcs-Browser: https://anonscm.debian.org/git/pkg-java/libsambox-java.git
Homepage: https://github.com/torakiki/sambox
......
......@@ -5,7 +5,7 @@ Files-Excluded:
src/test/*
Files: *
Copyright: 2016-2017, Andrea Vacondio
Copyright: 2016-2018, Andrea Vacondio
2010-2017, The Apache Software Foundation
License: Apache-2.0
......@@ -40,7 +40,7 @@ Copyright: 2007-2010, basICColor GmbH
License: zlib
Files: debian/*
Copyright: 2017, Markus Koschany <apo@debian.org>
Copyright: 2017-2018, Markus Koschany <apo@debian.org>
License: Apache-2.0
License: Apache-2.0
......
......@@ -7,3 +7,5 @@ org.apache.maven.plugins maven-source-plugin * * * *
org.apache.maven.plugins maven-surefire-plugin * * * *
org.hamcrest hamcrest-core * * * *
org.mockito mockito-core * * * *
com.googlecode.maven-download-plugin download-maven-plugin * * * *
org.apache.pdfbox jbig2-imageio * * * *
......@@ -5,7 +5,7 @@
<artifactId>sambox</artifactId>
<packaging>jar</packaging>
<name>sambox</name>
<version>1.1.19</version>
<version>1.1.41</version>
<description>An Apache PDFBox fork intended to be used as PDF processor for Sejda and PDFsam related projects</description>
<url>http://www.sejda.org</url>
......@@ -33,7 +33,7 @@
<connection>scm:git:git@github.com:torakiki/sambox.git</connection>
<developerConnection>scm:git:git@github.com:torakiki/sambox.git</developerConnection>
<url>scm:git:git@github.com:torakiki/sambox.git</url>
<tag>v1.1.19</tag>
<tag>v1.1.41</tag>
</scm>
<developers>
......@@ -138,6 +138,47 @@
</plugins>
</build>
</profile>
<profile>
<id>private-release</id>
<distributionManagement>
<snapshotRepository>
<id>sejda-pro-snapshot</id>
<url>http://mvn.sejda.com/artifactory/libs-snapshot</url>
</snapshotRepository>
<repository>
<id>sejda-pro</id>
<url>http://mvn.sejda.com/artifactory/libs-release</url>
</repository>
</distributionManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.2</version>
<configuration>
<tagNameFormat>v@{project.version}</tagNameFormat>
<preparationGoals>clean install</preparationGoals>
<localCheckout>true</localCheckout>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
......@@ -192,7 +233,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>-Xmx768m</argLine>
<argLine>-Xmx768m -Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider</argLine>
<excludes>
<exclude>org/sejda/sambox/rendering/TestPDFToImage.java</exclude>
</excludes>
......@@ -200,6 +241,187 @@
<reuseForks>false</reuseForks>
</configuration>
</plugin>
<!-- PDFBOX-3974: download test files from JIRA and keep them in repository cache -->
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>1.3.0</version>
<executions>
<execution>
<id>PDFBOX-3703</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://issues.apache.org/jira/secure/attachment/12854913/966635-p12.pdf</url>
<outputDirectory>${project.build.directory}/pdfs</outputDirectory>
<outputFileName>PDFBOX-3703-966635-p12.pdf</outputFileName>
<sha512>28fcb3be0bd3aa983a05107912b7c75ec8203b1ab14e7e76fa2b542d9d2dec9c96921d4220610dff96a299d935d9fffb3be2b552421b516a93344b14aed0ce0d</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-3747</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://github.com/jondot/dotfiles/blob/master/.fonts/calibri.ttf?raw=true</url>
<outputDirectory>${project.build.directory}/fonts</outputDirectory>
<outputFileName>PDFBOX-3747-calibri.ttf</outputFileName>
<sha512>b7eb8e6f2a4549eb68280d0d8834b2a14f711f2d15ffe1420fde654f05dd939181c617bf51e11c44aededaa729966b49288b0a07a35b79aa73a08b8c48b72de0</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-3948</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://issues.apache.org/jira/secure/attachment/12890034/EUWO6SQS5TM4VGOMRD3FLXZHU35V2CP2.pdf</url>
<outputDirectory>${project.build.directory}/pdfs</outputDirectory>
<outputFileName>PDFBOX-3948-EUWO6SQS5TM4VGOMRD3FLXZHU35V2CP2.pdf</outputFileName>
<sha512>f8a9b0b9ea6132f24e54136a40ad99d67df2402f3849a5cb0b7d80cd72298737fe4701e0e77ddd602a06e3ea0a7e107ca40d8d29389eea5834ff37245829c2d2</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-3949</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://issues.apache.org/jira/secure/attachment/12890037/MKFYUGZWS3OPXLLVU2Z4LWCTVA5WNOGF.pdf</url>
<outputDirectory>${project.build.directory}/pdfs</outputDirectory>
<outputFileName>PDFBOX-3949-MKFYUGZWS3OPXLLVU2Z4LWCTVA5WNOGF.pdf</outputFileName>
<sha512>f450fb40ed5589ce0f390eb110d78bc721b766c34b753770b0cb00b2e40ffe15878f54df2423ab99d7df80dd91512858bf56a7cdc392d5c179b4440176fdd2fb</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-3950</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://issues.apache.org/jira/secure/attachment/12890042/23EGDHXSBBYQLKYOKGZUOVYVNE675PRD.pdf</url>
<outputDirectory>${project.build.directory}/pdfs</outputDirectory>
<outputFileName>PDFBOX-3950-23EGDHXSBBYQLKYOKGZUOVYVNE675PRD.pdf</outputFileName>
<sha512>ee1d464c3ed2ad91a4cafbc474b38e5c961282f53ef599d6d10e02058da5a67064550ddc54774dfa843a8b45f34b7e6e8ab4f9a445ba459fdcd858e8dce65b25</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-3951</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://issues.apache.org/jira/secure/attachment/12890047/FIHUZWDDL2VGPOE34N6YHWSIGSH5LVGZ.pdf</url>
<outputDirectory>${project.build.directory}/pdfs</outputDirectory>
<outputFileName>PDFBOX-3951-FIHUZWDDL2VGPOE34N6YHWSIGSH5LVGZ.pdf</outputFileName>
<sha512>2c0b91beb4a2b098738512fefdd40135bf66286cd350ac4e155a5a0150d649acb1da819c817ee9822e8686f526af6b7862fc63a0dae6dc7f1407c7f8b271c65e</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-3964</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://issues.apache.org/jira/secure/attachment/12892097/c687766d68ac766be3f02aaec5e0d713_2.pdf</url>
<outputDirectory>${project.build.directory}/pdfs</outputDirectory>
<outputFileName>PDFBOX-3964-c687766d68ac766be3f02aaec5e0d713_2.pdf</outputFileName>
<sha512>0457fd291a7f83f531fef205128929c8fa8147dd781ea7b7cd49d4d1287941989e72739329a7b172c6f53df0b54d991b514b9baa6145effa8ec7705ef273877b</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-4022</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://issues.apache.org/jira/secure/attachment/12899008/selection.pdf</url>
<outputDirectory>${project.build.directory}/pdfs</outputDirectory>
<outputFileName>PDFBOX-4022-selection.pdf</outputFileName>
<sha512>d08af71bc8e3911ee3ed7c9ce9d4acc0562488981bc83a9c612de9d5f0640fd2d9805f600810f1cad5293fa4acda12444a0dcefa2543125c95d06059feb2c4f0</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-4106</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://ipafont.ipa.go.jp/old/ipafont/ipag00303.php</url>
<outputDirectory>${project.build.directory}/fonts</outputDirectory>
<outputFileName>ipag00303.zip</outputFileName>
<unpack>true</unpack>
<sha512>59535137c649a2f8bdbb463cd716426811a6003a65883ca6e45bb0af1d526b3889af0fba3a353e90bc8d373cd32b90a27ff9ff6916ecbccb42e922c09e9b046a</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-4106b</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://ipafont.ipa.go.jp/old/ipafont/ipagp00303.php</url>
<outputDirectory>${project.build.directory}/fonts</outputDirectory>
<outputFileName>ipagp00303.zip</outputFileName>
<unpack>true</unpack>
<sha512>26d0a9bfba7f5457a98b0bf45a4a6b081bca4140047a0886625691231459f8c81a6cdbe523e9abcbd45fd7caed21d78f1baf3a2cf9167320f6b79be3d697cb5b</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-4115</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://issues.apache.org/jira/secure/attachment/12911053/n019003l.pfb</url>
<outputDirectory>${project.build.directory}/fonts</outputDirectory>
<outputFileName>n019003l.pfb</outputFileName>
<sha512>8eafe21ffa6f3d7d0a50e9f4e5bcdeb727e804b552d74e65b709e778c9ed4605e5aa63743be285f0bc17ad162768583fec4196e1d1146d98f8703359247f22d0</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-4197</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://issues.apache.org/jira/secure/attachment/12919726/sample.pdf</url>
<outputDirectory>${project.build.directory}/pdfs</outputDirectory>
<outputFileName>PDFBOX-4197.pdf</outputFileName>
<sha512>6fefc869dff9db8cd539db177d35beeacc62304173245742eaee8882dab330860a31cbbd4c4ec6cc724603cc453afc07ec61361fbc1e80a47f44b04ccfbaf40d</sha512>
</configuration>
</execution>
<execution>
<id>PDFBOX-4184</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>http://www.crh.noaa.gov/Image/gjt/images/ImageGallery/Uncompahgre_small.jpg</url>
<!-- file is also 032163.jpg
from http://downloads.digitalcorpora.org/corpora/files/govdocs1/zipfiles/032.zip -->
<outputDirectory>${project.build.directory}/imgs</outputDirectory>
<outputFileName>PDFBOX-4184-032163.jpg</outputFileName>
<sha512>35241c979d3808ca9d2641b5ec5e40637132b313f75070faca8b8f6d00ddce394070414236db3993f1092fe3bc16995750d528b6d803a7851423c14c308ccdde</sha512>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
......@@ -222,12 +444,12 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
<version>2.0.8</version>
<version>2.0.11</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
......@@ -239,13 +461,19 @@
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
<optional>true</optional>
<version>1.56</version>
<version>1.60</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<optional>true</optional>
<version>1.56</version>
<version>1.60</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>jbig2-imageio</artifactId>
<version>3.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
......
......@@ -16,6 +16,7 @@
*/
package org.sejda.sambox.contentstream;
import static java.util.Objects.isNull;
import static java.util.Optional.ofNullable;
import java.awt.geom.GeneralPath;
......@@ -104,6 +105,22 @@ public abstract class PDFStreamEngine
operators.put(op.getName(), op);
}
/**
* Adds an operator processor to the engine if there isn't an operator already associated with the PDF operator.
*
* @param op operator processor
* @return true if the operator is added, false if not (there's already an operator associated)
*/
public final boolean addOperatorIfAbsent(OperatorProcessor op)
{
if (isNull(operators.putIfAbsent(op.getName(), op)))
{
op.setContext(this);
return true;
}
return false;
}
/**
* Initialises the stream engine for the given page.
*/
......@@ -163,8 +180,11 @@ public abstract class PDFStreamEngine
throw new IllegalStateException("No current page, call "
+ "#processChildStream(PDContentStream, PDPage) instead");
}
if (!form.getCOSObject().isEmpty())
{
processStream(form);
}
}
/**
* Processes a soft mask transparency group stream.
......@@ -431,7 +451,7 @@ public abstract class PDFStreamEngine
* @param contentStream the content stream
* @throws IOException if there is an exception while processing the stream
*/
protected void processStream(PDContentStream contentStream) throws IOException
public void processStream(PDContentStream contentStream) throws IOException
{
PDResources parent = pushResources(contentStream);
Stack<PDGraphicsState> savedStack = saveGraphicsStack();
......@@ -879,7 +899,7 @@ public abstract class PDFStreamEngine
protected final Stack<PDGraphicsState> saveGraphicsStack()
{
Stack<PDGraphicsState> savedStack = graphicsStack;
graphicsStack = new Stack<PDGraphicsState>();
graphicsStack = new Stack<>();
graphicsStack.add(savedStack.peek().clone());
return savedStack;
}
......@@ -956,7 +976,7 @@ public abstract class PDFStreamEngine
}
/**
* Returns the stream' resources.
* @return the stream' resources. This is mainly to be used by the {@link OperatorProcessor} classes
*/
public PDResources getResources()
{
......
......@@ -22,7 +22,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
......@@ -480,7 +479,7 @@ public class COSArray extends COSBase implements List<COSBase>
public List<? extends COSBase> toList()
{
ArrayList<COSBase> retList = new ArrayList<>(size());
Collections.copy(retList, objects);
retList.addAll(objects);
return retList;
}
......
......@@ -592,7 +592,6 @@ public class COSDictionary extends COSBase
/**
* Convenience method that will get the dictionary object that is expected to be a name and convert it to a string.
* Null is returned if the entry does not exist in the dictionary.
*
* @param key The key to the item in the dictionary.
* @param defaultValue The value to return if the dictionary item is null.
......@@ -605,7 +604,6 @@ public class COSDictionary extends COSBase
/**
* Convenience method that will get the dictionary object that is expected to be a name and convert it to a string.
* Null is returned if the entry does not exist in the dictionary.
*
* @param key The key to the item in the dictionary.
* @param defaultValue The value to return if the dictionary item is null.
......@@ -643,7 +641,6 @@ public class COSDictionary extends COSBase
/**
* Convenience method that will get the dictionary object that is expected to be a name and convert it to a string.
* Null is returned if the entry does not exist in the dictionary.
*
* @param key The key to the item in the dictionary.
* @param defaultValue The default value to return.
......@@ -656,7 +653,6 @@ public class COSDictionary extends COSBase
/**
* Convenience method that will get the dictionary object that is expected to be a name and convert it to a string.
* Null is returned if the entry does not exist in the dictionary.
*
* @param key The key to the item in the dictionary.
* @param defaultValue The default value to return.
......@@ -709,7 +705,6 @@ public class COSDictionary extends COSBase
/**
* Convenience method that will get the dictionary object that is expected to be a name and convert it to a string.
* Null is returned if the entry does not exist in the dictionary.
*
* @param embedded The embedded dictionary.
* @param key The key to the item in the dictionary.
......@@ -1167,6 +1162,26 @@ public class COSDictionary extends COSBase
return getItem(COSName.getPDFName(key));
}
/**
* This is a special case of getItem that takes multiple keys, it will handle the situation
* where multiple keys could get the same value, ie if either CS or ColorSpace is used to get
* the colorspace. This will get an object from this dictionary.
*
* @param firstKey The first key to try.
* @param secondKey The second key to try.
*
* @return The object that matches the key.
*/
public COSBase getItem(COSName firstKey, COSName secondKey)
{
COSBase retval = getItem(firstKey);
if (retval == null && secondKey != null)
{
retval = getItem(secondKey);
}
return retval;
}
/**
* @return names of the entries in this dictionary. The returned set is in the order the entries were added to the
* dictionary.
......
......@@ -16,6 +16,7 @@
*/
package org.sejda.sambox.cos;
import static java.util.Objects.nonNull;
import static java.util.Optional.ofNullable;
import static org.sejda.util.RequireUtils.requireNotBlank;
import static org.sejda.util.RequireUtils.requireNotNullArg;
......@@ -83,7 +84,8 @@ public class COSDocument extends COSBase
*/
public boolean isEncrypted()
{
return trailer.getCOSObject().getDictionaryObject(COSName.ENCRYPT) != null;
return nonNull(
trailer.getCOSObject().getDictionaryObject(COSName.ENCRYPT, COSDictionary.class));
}
/**
......
......@@ -34,6 +34,7 @@ public final class COSName extends COSBase implements Comparable<COSName>
// A
public static final COSName A = newCommonInstance("A");
public static final COSName AA = newCommonInstance("AA");
public static final COSName AC = newCommonInstance("AC");
public static final COSName ACRO_FORM = newCommonInstance("AcroForm");
public static final COSName ACTUAL_TEXT = newCommonInstance("ActualText");
public static final COSName ADBE_PKCS7_DETACHED = newCommonInstance("adbe.pkcs7.detached");
......@@ -124,6 +125,7 @@ public final class COSName extends COSBase implements Comparable<COSName>
public static final COSName CMAPNAME = newCommonInstance("CMapName");
public static final COSName CMYK = newCommonInstance("CMYK");
public static final COSName CO = newCommonInstance("CO");
public static final COSName COLOR = new COSName("Color");
public static final COSName COLOR_BURN = newCommonInstance("ColorBurn");
public static final COSName COLOR_DODGE = newCommonInstance("ColorDodge");
public static final COSName COLORANTS = newCommonInstance("Colorants");
......@@ -184,6 +186,7 @@ public final class COSName extends COSBase implements Comparable<COSName>
public static final COSName DOC_OPEN = newCommonInstance("DocOpen");
public static final COSName DOC_TIME_STAMP = newCommonInstance("DocTimeStamp");
public static final COSName DOCMDP = newCommonInstance("DocMDP");
public static final COSName DOCUMENT = new COSName("Document");
public static final COSName DOMAIN = newCommonInstance("Domain");
public static final COSName DOS = newCommonInstance("DOS");
public static final COSName DP = newCommonInstance("DP");
......@@ -264,6 +267,7 @@ public final class COSName extends COSBase implements Comparable<COSName>
public static final COSName HIDE_MENUBAR = newCommonInstance("HideMenubar");
public static final COSName HIDE_TOOLBAR = newCommonInstance("HideToolbar");
public static final COSName HIDE_WINDOWUI = newCommonInstance("HideWindowUI");
public static final COSName HUE = new COSName("Hue");
// I
public static final COSName I = newCommonInstance("I");
public static final COSName IC = newCommonInstance("IC");
......@@ -284,6 +288,9 @@ public final class COSName extends COSBase implements Comparable<COSName>
public static final COSName INTERPOLATE = newCommonInstance("Interpolate");
public static final COSName IT = newCommonInstance("IT");
public static final COSName ITALIC_ANGLE = newCommonInstance("ItalicAngle");
public static final COSName ISSUER = newCommonInstance("Issuer");
public static final COSName IX = newCommonInstance("IX");
// J
public static final COSName JAVA_SCRIPT = newCommonInstance("JavaScript");
public static final COSName JBIG2_DECODE = newCommonInstance("JBIG2Decode");
......@@ -334,6 +341,7 @@ public final class COSName extends COSBase implements Comparable<COSName>
public static final COSName MCID = newCommonInstance("MCID");
public static final COSName MDP = newCommonInstance("MDP");
public static final COSName MEDIA_BOX = newCommonInstance("MediaBox");
public static final COSName MEASURE = new COSName("Measure");
public static final COSName METADATA = newCommonInstance("Metadata");
public static final COSName MISSING_WIDTH = newCommonInstance("MissingWidth");
public static final COSName MK = newCommonInstance("MK");
......@@ -346,6 +354,7 @@ public final class COSName extends COSBase implements Comparable<COSName>
public static final COSName NAME = newCommonInstance("Name");
public static final COSName NAMES = newCommonInstance("Names");
public static final COSName NEED_APPEARANCES = newCommonInstance("NeedAppearances");
public static final COSName NEW_WINDOW = new COSName("NewWindow");
public static final COSName NEXT = newCommonInstance("Next");
public static final COSName NM = newCommonInstance("NM");
public static final COSName NON_EFONT_NO_WARN = newCommonInstance("NonEFontNoWarn");
......@@ -444,6 +453,7 @@ public final class COSName extends COSBase implements Comparable<COSName>
// S
public static final COSName S = newCommonInstance("S");
public static final COSName SA = newCommonInstance("SA");
public static final COSName SATURATION = new COSName("Saturation");
public static final COSName SCREEN = newCommonInstance("Screen");
public static final COSName SE = newCommonInstance("SE");
public static final COSName SEPARATION = newCommonInstance("Separation");
......@@ -527,6 +537,8 @@ public final class COSName extends COSBase implements Comparable<COSName>
public static final COSName VIEW_AREA = newCommonInstance("ViewArea");
public static final COSName VIEW_CLIP = newCommonInstance("ViewClip");
public static final COSName VIEWER_PREFERENCES = newCommonInstance("ViewerPreferences");
public static final COSName VOLUME = new COSName("Volume");
public static final COSName VP = new COSName("VP");
// W
public static final COSName W = newCommonInstance("W");
public static final COSName W2 = newCommonInstance("W2");
......
......@@ -401,7 +401,7 @@ public class COSStream extends COSDictionary implements Closeable, Encryptable
/**
* Sets the function to be used to encrypt this stream.
*
* @param encrypted
* @param encryptor
*/
public void setEncryptor(Function<InputStream, InputStream> encryptor)
{
......@@ -471,10 +471,14 @@ public class COSStream extends COSDictionary implements Closeable, Encryptable
/**
* Adds Flate decode filter to the current filters list if possible
*
* @true if the FlateDecode filter has been added
*/
public void addCompression() throws IOException
public boolean addCompression()
{
if (canCompress())
{
try
{
COSArray newFilters = new COSArray(COSName.FLATE_DECODE);
COSBase filters = getFilters();
......@@ -492,8 +496,15 @@ public class COSStream extends COSDictionary implements Closeable, Encryptable
{
setFilters(COSName.FLATE_DECODE);
}
return true;
}
catch (IOException e)
{
LOG.warn("Unable to add FlateDecode filter to the stream", e);
}
}
return false;
}
/**
* @return true if we can add compression to the current filters
......
......@@ -49,10 +49,14 @@ final class ASCIIHexFilter extends Filter
};
@Override
public DecodeResult decode(InputStream encoded, OutputStream decoded,
COSDictionary parameters, int index) throws IOException
public DecodeResult decode(InputStream encoded, OutputStream decoded, COSDictionary parameters,
int index) throws IOException
{
// TODO iText and pdfjs both have similar impl which is different from what we have. Maybe we can replace this
// with the algorithm in pdfjs
int value, firstByte, secondByte;
try
{
while ((firstByte = encoded.read()) != -1)
{
// always after first char
......@@ -82,7 +86,8 @@ final class ASCIIHexFilter extends Filter
{
if (REVERSE_HEX[secondByte] == -1)
{
LOG.error("Invalid hex, int: " + secondByte + " char: " + (char)secondByte);
LOG.error(
"Invalid hex, int: " + secondByte + " char: " + (char) secondByte);
}
value += REVERSE_HEX[secondByte];
}
......@@ -91,6 +96,11 @@ final class ASCIIHexFilter extends Filter
decoded.flush();
return new DecodeResult(parameters);
}
catch (ArrayIndexOutOfBoundsException e)
{
throw new IOException("Illegal character in ASCIIHexFilter", e);
}
}
// whitespace
// 0 0x00 Null (NUL)
......
......@@ -279,7 +279,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream
{
if (optionByteAligned)
{
bufferPos = -1; // Skip remaining bits and fetch the next byte at row start
resetBuffer();
}
eof: while (true)
{
......@@ -316,7 +316,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream
{
if (optionByteAligned)
{
bufferPos = -1; // Skip remaining bits and fetch the next byte at row start
resetBuffer();
}
decode2D();
}
......@@ -421,30 +421,14 @@ final class CCITTFaxDecoderStream extends FilterInputStream
{
return total;
}
else
{
n = tree.root;
}
}
}
}
private void resetBuffer() throws IOException
private void resetBuffer()
{
for (int i = 0; i < decodedRow.length; i++)
{
decodedRow[i] = 0;
}
while (true)
{
if (bufferPos == -1)
{
return;
}
readBit();
}
bufferPos = -1;
}
int buffer = -1;
......@@ -688,8 +672,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream
}
}
static final short[][] BLACK_CODES = {
{ // 2 bits
static final short[][] BLACK_CODES = { { // 2 bits
0x2, 0x3, },
{ // 3 bits
0x2, 0x3, },
......@@ -718,8 +701,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream
{ // 13 bits
0x4a, 0x4b, 0x4c, 0x4d, 0x52, 0x53, 0x54, 0x55, 0x5a, 0x5b, 0x64, 0x65, 0x6c,
0x6d, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, } };
static final short[][] BLACK_RUN_LENGTHS = {
{ // 2 bits
static final short[][] BLACK_RUN_LENGTHS = { { // 2 bits
3, 2, },
{ // 3 bits
1, 4, },
......@@ -748,8 +730,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream
640, 704, 768, 832, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 512, 576,
896, 960, 1024, 1088, 1152, 1216, } };
public static final short[][] WHITE_CODES = {
{ // 4 bits
public static final short[][] WHITE_CODES = { { // 4 bits
0x7, 0x8, 0xb, 0xc, 0xe, 0xf, },
{ // 5 bits
0x12, 0x13, 0x14, 0x1b, 0x7, 0x8, },
......@@ -771,8 +752,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream
{ // 12 bits
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x1c, 0x1d, 0x1e, 0x1f, } };
public static final short[][] WHITE_RUN_LENGTHS = {
{ // 4 bits
public static final short[][] WHITE_RUN_LENGTHS = { { // 4 bits
2, 3, 4, 5, 6, 7, },
{ // 5 bits
128, 8, 9, 64, 10, 11, },
......
......@@ -38,9 +38,6 @@ final class CCITTFaxFilter extends Filter
public DecodeResult decode(InputStream encoded, OutputStream decoded, COSDictionary parameters,
int index) throws IOException
{
DecodeResult result = new DecodeResult(new COSDictionary());
result.getParameters().addAll(parameters);
// get decode parameters
COSDictionary decodeParms = getDecodeParams(parameters, index);
......@@ -103,12 +100,6 @@ final class CCITTFaxFilter extends Filter
invertBitmap(decompressed);
}
// repair missing color space
if (!parameters.containsKey(COSName.COLORSPACE))
{
result.getParameters().setItem(COSName.COLORSPACE, COSName.DEVICEGRAY);
}
decoded.write(decompressed);
return new DecodeResult(parameters);
}
......
......@@ -134,8 +134,7 @@ final class DCTFilter extends Filter
// already CMYK
break;
case 1:
// TODO YCbCr
LOG.warn("YCbCr JPEGs not implemented");
raster = fromYCbCrtoCMYK(raster);
break;
case 2:
raster = fromYCCKtoCMYK(raster);
......@@ -268,6 +267,44 @@ final class DCTFilter extends Filter
return writableRaster;
}
private WritableRaster fromYCbCrtoCMYK(Raster raster)
{
WritableRaster writableRaster = raster.createCompatibleWritableRaster();
int[] value = new int[4];
for (int y = 0, height = raster.getHeight(); y < height; y++)
{
for (int x = 0, width = raster.getWidth(); x < width; x++)
{
raster.getPixel(x, y, value);
// 4-channels 0..255
float Y = value[0];
float Cb = value[1];
float Cr = value[2];
float K = value[3];
// YCbCr to RGB, see http://www.equasys.de/colorconversion.html
int r = clamp( (1.164f * (Y-16)) + (1.596f * (Cr - 128)) );
int g = clamp( (1.164f * (Y-16)) + (-0.392f * (Cb-128)) + (-0.813f * (Cr-128)));
int b = clamp( (1.164f * (Y-16)) + (2.017f * (Cb-128)));
// naive RGB to CMYK
int cyan = 255 - r;
int magenta = 255 - g;
int yellow = 255 - b;
// update new raster
value[0] = cyan;
value[1] = magenta;
value[2] = yellow;
value[3] = (int)K;
writableRaster.setPixel(x, y, value);
}
}
return writableRaster;
}
// converts from BGR to RGB
private WritableRaster fromBGRtoRGB(Raster raster)
{
......
......@@ -112,7 +112,7 @@ public abstract class Filter
return new COSDictionary();
}
}
if (!(dp instanceof COSArray || dp instanceof COSArray))
if (!(filter instanceof COSArray || dp instanceof COSArray))
{
LOG.error("Ignoring invalid DecodeParams. Expected array or dictionary but found {}",
dp.getClass().getName());
......
......@@ -16,7 +16,6 @@
*/
package org.sejda.sambox.filter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
......@@ -25,9 +24,7 @@ import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import org.sejda.io.FastByteArrayOutputStream;
import org.sejda.sambox.cos.COSDictionary;
import org.sejda.sambox.cos.COSName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -40,39 +37,17 @@ import org.slf4j.LoggerFactory;
final class FlateFilter extends Filter
{
private static final Logger LOG = LoggerFactory.getLogger(FlateFilter.class);
private static final int BUFFER_SIZE = 16348;
private static final int BUFFER_SIZE = 0x4000;
@Override
public DecodeResult decode(InputStream encoded, OutputStream decoded, COSDictionary parameters,
int index) throws IOException
{
int predictor = -1;
final COSDictionary decodeParams = getDecodeParams(parameters, index);
if (decodeParams != null)
{
predictor = decodeParams.getInt(COSName.PREDICTOR);
}
try
{
if (predictor > 1)
{
int colors = Math.min(decodeParams.getInt(COSName.COLORS, 1), 32);
int bitsPerPixel = decodeParams.getInt(COSName.BITS_PER_COMPONENT, 8);
int columns = decodeParams.getInt(COSName.COLUMNS, 1);
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
decompress(encoded, baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
Predictor.decodePredictor(predictor, colors, bitsPerPixel, columns, bais, decoded);
decoded.flush();
baos.reset();
bais.reset();
}
else
{
decompress(encoded, decoded);
}
decompress(encoded, Predictor.wrapPredictor(decoded, decodeParams));
}
catch (DataFormatException e)
{
......@@ -154,7 +129,8 @@ final class FlateFilter extends Filter
}
compressionLevel = Math.max(-1, Math.min(Deflater.BEST_COMPRESSION, compressionLevel));
Deflater deflater = new Deflater(compressionLevel);
DeflaterOutputStream out = new DeflaterOutputStream(encoded, deflater);
try (DeflaterOutputStream out = new DeflaterOutputStream(encoded, deflater))
{
int amountRead;
int mayRead = input.available();
if (mayRead > 0)
......@@ -165,7 +141,7 @@ final class FlateFilter extends Filter
out.write(buffer, 0, amountRead);
}
}
out.close();
}
encoded.flush();
}
}
......@@ -20,6 +20,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.io.IOUtils;
import org.sejda.sambox.cos.COSDictionary;
/**
......@@ -30,19 +31,12 @@ import org.sejda.sambox.cos.COSDictionary;
*/
final class IdentityFilter extends Filter
{
private static final int BUFFER_SIZE = 1024;
@Override
public DecodeResult decode(InputStream encoded, OutputStream decoded,
COSDictionary parameters, int index)
throws IOException
{
byte[] buffer = new byte[BUFFER_SIZE];
int amountRead;
while((amountRead = encoded.read(buffer, 0, BUFFER_SIZE)) != -1)
{
decoded.write(buffer, 0, amountRead);
}
IOUtils.copy(encoded, decoded);
decoded.flush();
return new DecodeResult(parameters);
}
......@@ -51,12 +45,7 @@ final class IdentityFilter extends Filter
public void encode(InputStream input, OutputStream encoded, COSDictionary parameters)
throws IOException
{
byte[] buffer = new byte[BUFFER_SIZE];
int amountRead;
while((amountRead = input.read(buffer, 0, BUFFER_SIZE)) != -1)
{
encoded.write(buffer, 0, amountRead);
}
IOUtils.copy(input, encoded);
encoded.flush();
}
}
......@@ -40,8 +40,7 @@ import org.slf4j.LoggerFactory;
* monochrome (1 bit per pixel) image data (or an approximation of that data).
*
* Requires a JBIG2 plugin for Java Image I/O to be installed. A known working
* plug-in is <a href="http://code.google.com/p/jbig2-imageio/">jbig2-imageio</a>
* which is available under the GPL v3 license.
* plug-in is the Apache PDFBox JBIG2 plugin.
*
* @author Timo Boehme
*/
......@@ -49,11 +48,29 @@ final class JBIG2Filter extends Filter
{
private static final Logger LOG = LoggerFactory.getLogger(JBIG2Filter.class);
private static boolean levigoLogged = false;
private static synchronized void logLevigoDonated()
{
if (!levigoLogged)
{
LOG.info("The Levigo JBIG2 plugin has been donated to the Apache Foundation");
LOG.info("and an improved version is available for download at "
+ "https://pdfbox.apache.org/download.cgi");
levigoLogged = true;
}
}
@Override
public DecodeResult decode(InputStream encoded, OutputStream decoded,
COSDictionary parameters, int index) throws IOException
public DecodeResult decode(InputStream encoded, OutputStream decoded, COSDictionary
parameters, int index) throws IOException
{
ImageReader reader = findImageReader("JBIG2", "jbig2-imageio is not installed");
if (reader.getClass().getName().contains("levigo"))
{
logLevigoDonated();
}
DecodeResult result = new DecodeResult(new COSDictionary());
result.getParameters().addAll(parameters);
......@@ -127,12 +144,6 @@ final class JBIG2Filter extends Filter
reader.dispose();
}
// repair missing color space
if (!parameters.containsKey(COSName.COLORSPACE))
{
result.getParameters().setName(COSName.COLORSPACE, COSName.DEVICEGRAY.getName());
}
return new DecodeResult(parameters);
}
......