update pdfbox 2.0.28, bytebuddy, Ghostscript loading reworked, added dispose()

This commit is contained in:
Jörg Prante 2023-04-17 09:35:04 +02:00
parent 9cbc3f3d10
commit a0d193eb7f
13 changed files with 213 additions and 241 deletions

View file

@ -1,5 +1,5 @@
group = org.xbib.graphics
name = graphics
version = 4.3.3
version = 4.3.4
org.gradle.warning.mode = ALL

View file

@ -7,13 +7,13 @@ dependencies {
test {
useJUnitPlatform()
failFast = false
failFast = true
environment 'TMPDIR', '/var/tmp/gs'
file('/var/tmp/gs').mkdirs()
systemProperty 'java.awt.headless', 'true'
systemProperty 'java.io.tmpdir', '/var/tmp/'
systemProperty 'jna.tmpdir', '/var/tmp/'
systemProperty 'jna.debug', 'false'
systemProperty 'jna.debug', 'true'
systemProperty 'java.util.logging.config.file', 'src/test/resources/logging.properties'
testLogging {
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'

View file

@ -23,8 +23,8 @@ public class FontAnalyzer {
"-sFile=" + path.toAbsolutePath(),
"-sOutputFile=%stdout",
"-f", "-"};
Ghostscript gs = Ghostscript.getInstance();
try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("script/AnalyzePDFFonts.ps");
try (Ghostscript gs = new Ghostscript();
InputStream is = this.getClass().getClassLoader().getResourceAsStream("script/AnalyzePDFFonts.ps");
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
gs.setStdIn(is);
gs.setStdOut(baos);
@ -56,8 +56,6 @@ public class FontAnalyzer {
}
}
return result;
} finally {
gs.close();
}
}
}

View file

@ -2,6 +2,8 @@ package org.xbib.graphics.ghostscript;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import org.xbib.graphics.ghostscript.internal.ErrorCodes;
import org.xbib.graphics.ghostscript.internal.GhostscriptLibrary;
import org.xbib.graphics.ghostscript.internal.GhostscriptLibraryLoader;
@ -23,13 +25,13 @@ import java.util.logging.Logger;
/**
* The Ghostscript native library API.
*/
public class Ghostscript {
public class Ghostscript implements AutoCloseable {
private static final Logger logger = Logger.getLogger(Ghostscript.class.getName());
public static final String ENCODING_PARAMETER = "org.xbib.graphics.ghostscript.encoding";
private static Ghostscript INSTANCE;
private final GhostscriptLibrary libraryInstance;
private InputStream stdIn;
@ -37,19 +39,16 @@ public class Ghostscript {
private OutputStream stdErr;
private GhostscriptLibrary libraryInstance;
private final AtomicBoolean closed;
private Ghostscript(GhostscriptLibrary libraryInstance) {
this.libraryInstance = libraryInstance;
public Ghostscript() throws IOException {
prepareTmp();
GhostscriptLibraryLoader libraryLoader = new GhostscriptLibraryLoader();
this.libraryInstance = libraryLoader.getGhostscriptLibrary();
Objects.requireNonNull(this.libraryInstance);
this.stdOut = new LoggingOutputStream(logger);
this.stdErr = new LoggingOutputStream(logger);
}
public synchronized static Ghostscript getInstance() {
if (INSTANCE == null) {
INSTANCE = createInstance();
}
return INSTANCE;
this.closed = new AtomicBoolean(false);
}
/**
@ -57,9 +56,9 @@ public class Ghostscript {
*
* @return the Ghostscript revision data.
*/
public synchronized static GhostscriptRevision getRevision() {
public synchronized GhostscriptRevision getRevision() {
GhostscriptLibrary.gsapi_revision_s revision = new GhostscriptLibrary.gsapi_revision_s();
INSTANCE.libraryInstance.gsapi_revision(revision, revision.size());
libraryInstance.gsapi_revision(revision, revision.size());
GhostscriptRevision result = new GhostscriptRevision();
result.setProduct(revision.product);
result.setCopyright(revision.copyright);
@ -257,33 +256,29 @@ public class Ghostscript {
}
}
@Override
public synchronized void close() throws IOException {
if (stdIn != null) {
stdIn.close();
stdIn = null;
if (closed.compareAndSet(false, true)) {
if (stdIn != null) {
stdIn.close();
stdIn = null;
}
if (stdOut != null) {
stdOut.close();
stdOut = null;
}
if (stdErr != null) {
stdErr.close();
stdErr = null;
}
if (libraryInstance != null) {
libraryInstance.dispose();
System.gc();
logger.log(Level.INFO, "ghostscript library instance disposed and gc'ed()");
} else {
logger.log(Level.WARNING, "ghostscript library instance is null");
}
}
if (stdOut != null) {
stdOut.close();
stdOut = null;
}
if (stdErr != null) {
stdErr.close();
stdErr = null;
}
libraryInstance = null;
INSTANCE = null;
System.gc();
logger.log(Level.INFO, "ghostscript instance closed and gc'ed()");
}
private static Ghostscript createInstance() {
try {
prepareTmp();
return new Ghostscript(GhostscriptLibraryLoader.loadLibrary());
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
return null;
}
private static void prepareTmp() throws IOException {

View file

@ -1,5 +1,6 @@
package org.xbib.graphics.ghostscript;
import java.security.SecureRandom;
import org.xbib.graphics.ghostscript.internal.LoggingOutputStream;
import java.io.IOException;
@ -20,6 +21,8 @@ public class PDFConverter {
private static final Logger logger = Logger.getLogger(PDFConverter.class.getName());
private static final SecureRandom random = new SecureRandom();
public static final int OPTION_AUTOROTATEPAGES_NONE = 0;
public static final int OPTION_AUTOROTATEPAGES_ALL = 1;
public static final int OPTION_AUTOROTATEPAGES_PAGEBYPAGE = 2;
@ -72,8 +75,6 @@ public class PDFConverter {
*/
private final PaperSize paperSize;
private final Path tmpPath;
public PDFConverter() {
this(OPTION_AUTOROTATEPAGES_OFF, OPTION_PROCESSCOLORMODEL_RGB,
OPTION_PDFSETTINGS_PRINTER, "1.4", false, PaperSize.A4);
@ -91,7 +92,6 @@ public class PDFConverter {
this.compatibilityLevel = compatibilityLevel;
this.pdfx = pdfx;
this.paperSize = paperSize;
this.tmpPath = Paths.get(System.getProperty("java.io.tmpdir", "/var/tmp")).resolve(toString());
}
/**
@ -106,56 +106,32 @@ public class PDFConverter {
if (outputStream == null) {
return;
}
Ghostscript gs = Ghostscript.getInstance();
try {
prepare(tmpPath);
Path tmpPath = createTmpPath();
try (Ghostscript gs = new Ghostscript()) {
Path output = Files.createTempFile(tmpPath, "pdf", "pdf");
List<String> gsArgs = new LinkedList<>();
gsArgs.add("-ps2pdf");
gsArgs.add("-dNOPAUSE");
//gsArgs.add("-dQUIET");
gsArgs.add("-dBATCH");
gsArgs.add("-dSAFER");
switch (autoRotatePages) {
case OPTION_AUTOROTATEPAGES_NONE:
gsArgs.add("-dAutoRotatePages=/None");
break;
case OPTION_AUTOROTATEPAGES_ALL:
gsArgs.add("-dAutoRotatePages=/All");
break;
case OPTION_AUTOROTATEPAGES_PAGEBYPAGE:
gsArgs.add("-dAutoRotatePages=/PageByPage");
break;
default:
break;
case OPTION_AUTOROTATEPAGES_NONE -> gsArgs.add("-dAutoRotatePages=/None");
case OPTION_AUTOROTATEPAGES_ALL -> gsArgs.add("-dAutoRotatePages=/All");
case OPTION_AUTOROTATEPAGES_PAGEBYPAGE -> gsArgs.add("-dAutoRotatePages=/PageByPage");
default -> {
}
}
switch (processColorModel) {
case OPTION_PROCESSCOLORMODEL_CMYK:
gsArgs.add("-dProcessColorModel=/DeviceCMYK");
break;
case OPTION_PROCESSCOLORMODEL_GRAY:
gsArgs.add("-dProcessColorModel=/DeviceGray");
break;
default:
gsArgs.add("-dProcessColorModel=/DeviceRGB");
break;
case OPTION_PROCESSCOLORMODEL_CMYK -> gsArgs.add("-dProcessColorModel=/DeviceCMYK");
case OPTION_PROCESSCOLORMODEL_GRAY -> gsArgs.add("-dProcessColorModel=/DeviceGray");
default -> gsArgs.add("-dProcessColorModel=/DeviceRGB");
}
switch (pdfsettings) {
case OPTION_PDFSETTINGS_EBOOK:
gsArgs.add("-dPDFSETTINGS=/ebook");
break;
case OPTION_PDFSETTINGS_SCREEN:
gsArgs.add("-dPDFSETTINGS=/screen");
break;
case OPTION_PDFSETTINGS_PRINTER:
gsArgs.add("-dPDFSETTINGS=/printer");
break;
case OPTION_PDFSETTINGS_PREPRESS:
gsArgs.add("-dPDFSETTINGS=/prepress");
break;
default:
gsArgs.add("-dPDFSETTINGS=/default");
break;
case OPTION_PDFSETTINGS_EBOOK -> gsArgs.add("-dPDFSETTINGS=/ebook");
case OPTION_PDFSETTINGS_SCREEN -> gsArgs.add("-dPDFSETTINGS=/screen");
case OPTION_PDFSETTINGS_PRINTER -> gsArgs.add("-dPDFSETTINGS=/printer");
case OPTION_PDFSETTINGS_PREPRESS -> gsArgs.add("-dPDFSETTINGS=/prepress");
default -> gsArgs.add("-dPDFSETTINGS=/default");
}
gsArgs.add("-dCompatibilityLevel=" + compatibilityLevel);
gsArgs.add("-dPDFX=" + pdfx);
@ -163,28 +139,19 @@ public class PDFConverter {
gsArgs.add("-dDEVICEHEIGHTPOINTS=" + paperSize.getHeight());
gsArgs.add("-sDEVICE=pdfwrite");
gsArgs.add("-sOutputFile=" + output.toAbsolutePath().toString());
//gsArgs.add("-q");
gsArgs.add("-f");
gsArgs.add("-");
try {
gs.setStdIn(inputStream);
gs.setStdOut(new LoggingOutputStream(logger));
gs.setStdErr(new LoggingOutputStream(logger));
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
Files.copy(output.toAbsolutePath(), outputStream);
} finally {
delete(tmpPath);
}
gs.setStdIn(inputStream);
gs.setStdOut(new LoggingOutputStream(logger));
gs.setStdErr(new LoggingOutputStream(logger));
gs.run(gsArgs.toArray(new String[0]));
Files.copy(output.toAbsolutePath(), outputStream);
} finally {
gs.close();
deleteTmpPath(tmpPath);
}
}
private static void prepare(Path path) throws IOException {
Files.createDirectories(path);
}
private static void delete(Path path) throws IOException {
private static void deleteTmpPath(Path path) throws IOException {
if (path == null) {
return;
}
@ -211,4 +178,12 @@ public class PDFConverter {
Files.deleteIfExists(path);
}
}
private static Path createTmpPath() throws IOException {
int integer = random.nextInt();
Path tmpPath = Paths.get(System.getProperty("java.io.tmpdir", "/var/tmp"))
.resolve("gs" + Math.abs(integer));
Files.createDirectories(tmpPath);
return tmpPath;
}
}

View file

@ -1,5 +1,6 @@
package org.xbib.graphics.ghostscript;
import java.security.SecureRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import javax.imageio.ImageIO;
@ -45,6 +46,8 @@ public class PDFRasterizer {
private static final Logger logger = Logger.getLogger(PDFRasterizer.class.getName());
private static final SecureRandom random = new SecureRandom();
private static final int MAX_IMAGE_SIZE_BYTES = 128 * 1024 * 1024;
private String creator;
@ -53,10 +56,7 @@ public class PDFRasterizer {
private String subject;
private final Path tmpPath;
public PDFRasterizer() {
this.tmpPath = Paths.get(System.getProperty("java.io.tmpdir", "/var/tmp")).resolve(toString());
}
public void setCreator(String creator) {
@ -82,51 +82,54 @@ public class PDFRasterizer {
if (Files.size(source) == 0) {
throw new IOException("empty file at " + source);
}
prepare(tmpPath);
Path tmp = Files.createTempDirectory(tmpPath, "pdf-rasterize");
if (!Files.isWritable(tmp)) {
throw new IOException("unable to write to " + tmp);
}
Path tmpPath = createTmpPath();
try {
pdfToImage(source, tmp, "pdf", null);
Path tmpTarget = tmp.resolve(target.getFileName());
mergeImagesToPDF(tmp, tmpTarget);
Path path = Files.createTempDirectory(tmpPath, "pdf-rasterize");
pdfToImage(source, path, "pdf", null);
Path tmpTarget = path.resolve(target.getFileName());
mergeImagesToPDF(path, tmpTarget);
scalePDF(tmpTarget, target);
logger.info("convert source=" + source + " done");
} finally {
delete(tmpPath);
deleteTmpPath(tmpPath);
}
}
public synchronized void screenConvert(Path source, Path target) throws IOException {
logger.info("convert source=" + source.toAbsolutePath() + " target=" + target);
logger.info("screen convert source=" + source.toAbsolutePath() + " target=" + target);
if (!Files.exists(source.toAbsolutePath())) {
throw new FileNotFoundException(source.toString());
}
if (!Files.isReadable(source.toAbsolutePath())) {
throw new IOException("unable to read " + source.toString());
}
prepare(tmpPath);
Path tmp = Files.createTempDirectory(tmpPath, "pdf-rasterize");
if (Files.size(source) == 0) {
throw new IOException("empty file at " + source);
}
Path tmpPath = createTmpPath();
try {
pdfToGrayScreenImage(source.toAbsolutePath(), tmp);
Path tmpTarget = tmp.resolve(target.getFileName());
mergeImagesToPDF(tmp, tmpTarget);
Path path = Files.createTempDirectory(tmpPath, "pdf-rasterize");
pdfToGrayScreenImage(source.toAbsolutePath(), path);
Path tmpTarget = path.resolve(target.getFileName());
mergeImagesToPDF(path, tmpTarget);
//toPDFA(tmpTarget, target);
scalePDF(tmpTarget, target);
logger.info("convert source=" + source.toAbsolutePath() + " done");
logger.info("screen convert source=" + source.toAbsolutePath() + " done");
} finally {
delete(tmpPath);
deleteTmpPath(tmpPath);
}
}
public synchronized void pdfToGrayScreenImage(Path source, Path target) throws IOException {
logger.info("pdfToGrayScreenImage source=" + source + " target=" + target);
if (!Files.exists(source.toAbsolutePath())) {
throw new FileNotFoundException(source.toString());
throw new FileNotFoundException("not found: " + source);
}
if (!Files.isReadable(source.toAbsolutePath())) {
throw new IOException("unable to read " + source.toString());
throw new IOException("unable to read " + source);
}
if (Files.size(source) == 0) {
throw new IOException("empty file at " + source);
}
List<String> gsArgs = new LinkedList<>();
gsArgs.add("-dNOPAUSE");
@ -141,16 +144,12 @@ public class PDFRasterizer {
gsArgs.add("-f");
gsArgs.add(source.toString());
logger.info("pdfToImage args=" + gsArgs);
// reset stdin
Ghostscript gs = Ghostscript.getInstance();
try {
try (Ghostscript gs = new Ghostscript()) {
gs.setStdIn(null);
gs.setStdOut(new LoggingOutputStream(logger));
gs.setStdErr(new LoggingOutputStream(logger));
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
gs.run(gsArgs.toArray(new String[0]));
logger.info("pdfToImage done");
} finally {
gs.close();
}
}
@ -182,16 +181,13 @@ public class PDFRasterizer {
gsArgs.add("-f");
gsArgs.add(sourceFile.toString());
logger.info("pdfToImage args=" + gsArgs);
Ghostscript gs = Ghostscript.getInstance();
try {
try (Ghostscript gs = new Ghostscript()) {
// reset stdin
gs.setStdIn(null);
gs.setStdOut(new LoggingOutputStream(logger));
gs.setStdErr(new LoggingOutputStream(logger));
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
gs.run(gsArgs.toArray(new String[0]));
logger.info("pdfToImage done");
} finally {
gs.close();
}
}
@ -294,59 +290,52 @@ public class PDFRasterizer {
gsArgs.add("-sPAPERSIZE=a4");
gsArgs.add("-sOutputFile=" + targetFile.toString());
gsArgs.add(sourceFile.toString());
Ghostscript gs = Ghostscript.getInstance();
try {
try (Ghostscript gs = new Ghostscript()) {
gs.setStdIn(null);
logger.info(gsArgs.toString());
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
gs.run(gsArgs.toArray(new String[0]));
logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " done");
} finally {
gs.close();
}
}
public void toPDFA(Path source, Path target) throws IOException {
prepare(tmpPath);
Path iccPath = Files.createTempFile(tmpPath, "srgb", ".icc");
Path pdfapsPathTmp = Files.createTempFile(tmpPath, "PDFA_def", ".tmp");
Path pdfapsPath = Files.createTempFile(tmpPath, "PDFA_def", ".ps");
try (InputStream srgbIcc = getClass().getResourceAsStream("/iccprofiles/srgb.icc")) {
if (srgbIcc != null) {
Files.copy(srgbIcc, iccPath, StandardCopyOption.REPLACE_EXISTING);
Path tmpPath = createTmpPath();
try (Ghostscript gs = new Ghostscript()) {
Path iccPath = Files.createTempFile(tmpPath, "srgb", ".icc");
Path pdfapsPathTmp = Files.createTempFile(tmpPath, "PDFA_def", ".tmp");
Path pdfapsPath = Files.createTempFile(tmpPath, "PDFA_def", ".ps");
try (InputStream srgbIcc = getClass().getResourceAsStream("/iccprofiles/srgb.icc")) {
if (srgbIcc != null) {
Files.copy(srgbIcc, iccPath, StandardCopyOption.REPLACE_EXISTING);
}
}
}
try (InputStream pdfaPs = getClass().getResourceAsStream("/lib/PDFA_def.ps")) {
if (pdfaPs != null) {
Files.copy(pdfaPs, pdfapsPathTmp, StandardCopyOption.REPLACE_EXISTING);
try (InputStream pdfaPs = getClass().getResourceAsStream("/lib/PDFA_def.ps")) {
if (pdfaPs != null) {
Files.copy(pdfaPs, pdfapsPathTmp, StandardCopyOption.REPLACE_EXISTING);
}
}
}
copyAndReplace(pdfapsPathTmp, pdfapsPath, "srgb.icc", iccPath.toAbsolutePath().toString());
List<String> gsArgs = new LinkedList<>();
gsArgs.add("-E");
gsArgs.add("-dNOPAUSE");
gsArgs.add("-dBATCH");
gsArgs.add("-dQUIET"); // do not print to stdout
gsArgs.add("-dNOSAFER"); // do not use SAFER because we need access to PDFA_def.ps and srgb.icc
gsArgs.add("-dPDFA=2"); // PDF/A-2b
gsArgs.add("-sColorConversionStrategy=/sRGB");
gsArgs.add("-sOutputICCProfile=" + iccPath.toAbsolutePath().toString());
gsArgs.add("-sDEVICE=pdfwrite");
gsArgs.add("-dPDFSETTINGS=/printer");
gsArgs.add("-sPAPERSIZE=a4");
gsArgs.add("-dPDFFitPage");
gsArgs.add("-dAutoRotatePages=/PageByPage");
gsArgs.add("-sOutputFile=" + target.toString());
gsArgs.add(pdfapsPath.toAbsolutePath().toString());
gsArgs.add(source.toString());
Ghostscript gs = Ghostscript.getInstance();
try {
copyAndReplace(pdfapsPathTmp, pdfapsPath, "srgb.icc", iccPath.toAbsolutePath().toString());
List<String> gsArgs = new LinkedList<>();
gsArgs.add("-E");
gsArgs.add("-dNOPAUSE");
gsArgs.add("-dBATCH");
gsArgs.add("-dQUIET"); // do not print to stdout
gsArgs.add("-dNOSAFER"); // do not use SAFER because we need access to PDFA_def.ps and srgb.icc
gsArgs.add("-dPDFA=2"); // PDF/A-2b
gsArgs.add("-sColorConversionStrategy=/sRGB");
gsArgs.add("-sOutputICCProfile=" + iccPath.toAbsolutePath().toString());
gsArgs.add("-sDEVICE=pdfwrite");
gsArgs.add("-dPDFSETTINGS=/printer");
gsArgs.add("-sPAPERSIZE=a4");
gsArgs.add("-dPDFFitPage");
gsArgs.add("-dAutoRotatePages=/PageByPage");
gsArgs.add("-sOutputFile=" + target.toString());
gsArgs.add(pdfapsPath.toAbsolutePath().toString());
gsArgs.add(source.toString());
gs.setStdIn(null);
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
gs.run(gsArgs.toArray(new String[0]));
} finally {
delete(pdfapsPathTmp);
delete(pdfapsPath);
delete(iccPath);
gs.close();
deleteTmpPath(tmpPath);
}
}
@ -420,11 +409,7 @@ public class PDFRasterizer {
return pos >= 0 ? filename.substring(pos + 1).toLowerCase(Locale.ROOT) : null;
}
private static void prepare(Path path) throws IOException {
Files.createDirectories(path);
}
private static void delete(Path path) throws IOException {
private static void deleteTmpPath(Path path) throws IOException {
if (path == null) {
return;
}
@ -451,4 +436,15 @@ public class PDFRasterizer {
Files.deleteIfExists(path);
}
}
private static Path createTmpPath() throws IOException {
int integer = random.nextInt();
Path tmpPath = Paths.get(System.getProperty("java.io.tmpdir", "/var/tmp"))
.resolve("gs" + Math.abs(integer));
Files.createDirectories(tmpPath);
if (!Files.isWritable(tmpPath)) {
throw new IOException("unable to write to " + tmpPath);
}
return tmpPath;
}
}

View file

@ -21,6 +21,11 @@ import java.util.List;
*/
public interface GhostscriptLibrary extends Library {
/**
* A default method to call JNA's dispose().
*/
void dispose();
/**
* This function returns the revision numbers and strings of the Ghostscript
* interpreter library. You should call it before any other interpreter

View file

@ -1,13 +1,13 @@
package org.xbib.graphics.ghostscript.internal;
import static com.sun.jna.Platform.LINUX;
import static com.sun.jna.Platform.MAC;
import com.sun.jna.Function;
import com.sun.jna.InvocationMapper;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -28,29 +28,39 @@ public class GhostscriptLibraryLoader {
"libgs.9.25",
"gs.9.25",
"libgs.dylib",
"libgs",
"gs",
};
public static GhostscriptLibrary loadLibrary() {
Map<String, Object> options = new HashMap<>();
options.put(Library.OPTION_CALLING_CONVENTION, Function.C_CONVENTION);
String[] LIBNAMES = {};
switch (Platform.getOSType()) {
case LINUX:
LIBNAMES = LINUX_LIBNAMES;
break;
case MAC:
LIBNAMES = MAC_LIBNAMES;
break;
private GhostscriptLibrary ghostscriptLibrary;
public GhostscriptLibraryLoader() {
Map<String, Object> options = Map.of(Library.OPTION_CALLING_CONVENTION, Function.C_CONVENTION,
Library.OPTION_INVOCATION_MAPPER, (InvocationMapper) (lib, m) -> {
if (m.getName().equals("dispose")) {
return (proxy, method, args) -> {
lib.dispose();
return null;
};
}
return null;
});
String[] libnames = LINUX_LIBNAMES;
if (Platform.getOSType() == MAC) {
libnames = MAC_LIBNAMES;
}
for (String libname : LIBNAMES) {
for (String libname : libnames) {
try {
return Native.load(libname, GhostscriptLibrary.class, options);
this.ghostscriptLibrary = Native.load(libname, GhostscriptLibrary.class, options);
} catch (Error e) {
logger.log(Level.WARNING, "library " + libname + " not found", e);
}
}
return null;
if (this.ghostscriptLibrary == null) {
throw new IllegalStateException("library not found in libs: " + Arrays.asList(libnames));
}
}
public GhostscriptLibrary getGhostscriptLibrary() {
return ghostscriptLibrary;
}
}

View file

@ -9,7 +9,8 @@ public class GhostScriptLibraryTester {
private final GhostscriptLibrary ghostscriptLibrary;
public GhostScriptLibraryTester() {
ghostscriptLibrary = GhostscriptLibraryLoader.loadLibrary();
GhostscriptLibraryLoader loader = new GhostscriptLibraryLoader();
this.ghostscriptLibrary = loader.getGhostscriptLibrary();
}
public String getRevisionProduct() {

View file

@ -1,8 +1,6 @@
package org.xbib.graphics.ghostscript.test;
import java.io.IOException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.xbib.graphics.ghostscript.Ghostscript;
@ -23,44 +21,35 @@ public class GhostscriptTest {
private static final String dir = "src/test/resources/org/xbib/graphics/ghostscript/test/";
static Ghostscript gs;
@BeforeAll
public static void init() {
gs = Ghostscript.getInstance();
}
@AfterAll
public static void shutdown() throws IOException {
gs.close();
}
@Test
public void testGetRevision() {
GhostscriptRevision revision = Ghostscript.getRevision();
logger.log(Level.INFO, "product = " + revision.getProduct());
assertNotNull(revision.getProduct());
logger.log(Level.INFO, "copyright = " + revision.getCopyright());
assertNotNull(revision.getCopyright());
logger.log(Level.INFO, "revision date = " + revision.getRevisionDate());
assertNotNull(revision.getRevisionDate());
logger.log(Level.INFO, "number = " + revision.getNumber());
assertNotNull(revision.getNumber());
public void testGetRevision() throws IOException {
try (Ghostscript gs = new Ghostscript()) {
GhostscriptRevision revision = gs.getRevision();
logger.log(Level.INFO, "product = " + revision.getProduct());
assertNotNull(revision.getProduct());
logger.log(Level.INFO, "copyright = " + revision.getCopyright());
assertNotNull(revision.getCopyright());
logger.log(Level.INFO, "revision date = " + revision.getRevisionDate());
assertNotNull(revision.getRevisionDate());
logger.log(Level.INFO, "number = " + revision.getNumber());
assertNotNull(revision.getNumber());
}
}
@Test
public void testExit() {
try {
try (Ghostscript gs = new Ghostscript()) {
String[] args = {"-dNODISPLAY", "-dQUIET"};
gs.run(args);
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
fail(e.getMessage());
}
}
@Test
public void testRunString() {
try {
try (Ghostscript gs = new Ghostscript()) {
String[] args = {"-dNODISPLAY", "-dQUIET"};
gs.run(args, "devicenames ==", null);
} catch (Exception e) {
@ -73,7 +62,7 @@ public class GhostscriptTest {
@Test
public void testRunFile() {
try {
try (Ghostscript gs = new Ghostscript()) {
String[] args = {"-dNODISPLAY", "-dQUIET", "-dNOPAUSE", "-dBATCH", "-dSAFER"};
gs.run(args, null, dir + "input.ps");
} catch (Exception e) {
@ -90,7 +79,8 @@ public class GhostscriptTest {
@Disabled("core dump")
@Test
public void testStdIn() {
try (InputStream is = new FileInputStream(dir + "input.ps")) {
try (Ghostscript gs = new Ghostscript();
InputStream is = new FileInputStream(dir + "input.ps")) {
gs.setStdIn(is);
String[] args = {"-dNODISPLAY", "-dQUIET", "-dNOPAUSE", "-dBATCH", "-sOutputFile=%stdout", "-f", "-"};
gs.run(args);
@ -101,7 +91,8 @@ public class GhostscriptTest {
@Test
public void testStdOut() {
try (InputStream is = new ByteArrayInputStream("devicenames ==\n".getBytes())) {
try (Ghostscript gs = new Ghostscript();
InputStream is = new ByteArrayInputStream("devicenames ==\n".getBytes())) {
gs.setStdIn(is);
String[] args = { "-dNODISPLAY", "-sOutputFile=%stdout", "-f", "-" };
gs.run(args);
@ -112,7 +103,8 @@ public class GhostscriptTest {
@Test
public void testStdErr() {
try (InputStream is = new ByteArrayInputStream("stupid\n".getBytes())) {
try (Ghostscript gs = new Ghostscript();
InputStream is = new ByteArrayInputStream("stupid\n".getBytes())) {
gs.setStdIn(is);
String[] args = { "-dNODISPLAY", "-sOutputFile=%stdout", "-f", "-" };
gs.run(args);

View file

@ -45,17 +45,17 @@ public class PDFRasterizerTest {
public void testPDFUnpackRasterAndScale() throws IOException {
Path source = Paths.get("src/test/resources/org/xbib/graphics/ghostscript/test/20200024360.pdf");
Path target = Paths.get("build/20200024360-new.pdf");
Path tmp = Files.createTempDirectory("graphics-test");
Path path = Files.createTempDirectory("graphics-test");
int pagecount = 0;
try {
PDFRasterizer pdfRasterizer = new PDFRasterizer();
pdfRasterizer.pdfToImage(source, tmp, null, null);
Path tmpTarget = tmp.resolve(target.getFileName());
pagecount = pdfRasterizer.mergeImagesToPDF(tmp, tmpTarget);
pdfRasterizer.pdfToImage(source, path, null, null);
Path tmpTarget = path.resolve(target.getFileName());
pagecount = pdfRasterizer.mergeImagesToPDF(path, tmpTarget);
logger.info("pagecount = " + pagecount);
pdfRasterizer.scalePDF(tmpTarget, target);
} finally {
delete(tmp);
delete(path);
}
assertEquals(28, pagecount);
}

View file

@ -14,6 +14,6 @@ dependencies {
testImplementation libs.groovy.templates
testImplementation libs.groovy.test
testImplementation libs.spock
testImplementation libs.cglib
testImplementation libs.bytebuddy
testImplementation libs.objenesis
}

View file

@ -36,10 +36,10 @@ dependencyResolutionManagement {
library('groovy-templates', 'org.apache.groovy', 'groovy-templates').versionRef('groovy')
library('groovy-test', 'org.apache.groovy', 'groovy-test').versionRef('groovy')
library('spock', 'org.spockframework', 'spock-core').versionRef('spock')
library('cglib', 'cglib', 'cglib-nodep').version('3.3.0')
library('bytebuddy', 'net.bytebuddy', 'byte-buddy').version('1.14.4')
library('objenesis', 'org.objenesis', 'objenesis').version('2.6')
library('jna', 'net.java.dev.jna', 'jna').version('5.12.1')
library('pdfbox', 'org.apache.pdfbox', 'pdfbox').version('2.0.27')
library('jna', 'net.java.dev.jna', 'jna').version('5.13.0')
library('pdfbox', 'org.apache.pdfbox', 'pdfbox').version('2.0.28')
library('zxing', 'com.google.zxing', 'javase').version('3.4.1')
library('reflections', 'org.reflections', 'reflections').version('0.9.11')
library('jfreechart', 'org.jfree', 'jfreechart').version('1.5.2')