update pdfbox 2.0.28, bytebuddy, Ghostscript loading reworked, added dispose()
This commit is contained in:
parent
9cbc3f3d10
commit
a0d193eb7f
13 changed files with 213 additions and 241 deletions
|
@ -1,5 +1,5 @@
|
|||
group = org.xbib.graphics
|
||||
name = graphics
|
||||
version = 4.3.3
|
||||
version = 4.3.4
|
||||
|
||||
org.gradle.warning.mode = ALL
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,7 +256,9 @@ public class Ghostscript {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws IOException {
|
||||
if (closed.compareAndSet(false, true)) {
|
||||
if (stdIn != null) {
|
||||
stdIn.close();
|
||||
stdIn = null;
|
||||
|
@ -270,20 +271,14 @@ public class Ghostscript {
|
|||
stdErr.close();
|
||||
stdErr = null;
|
||||
}
|
||||
libraryInstance = null;
|
||||
INSTANCE = null;
|
||||
if (libraryInstance != null) {
|
||||
libraryInstance.dispose();
|
||||
System.gc();
|
||||
logger.log(Level.INFO, "ghostscript instance closed and gc'ed()");
|
||||
logger.log(Level.INFO, "ghostscript library instance disposed and gc'ed()");
|
||||
} else {
|
||||
logger.log(Level.WARNING, "ghostscript library instance is null");
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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()]));
|
||||
gs.run(gsArgs.toArray(new String[0]));
|
||||
Files.copy(output.toAbsolutePath(), outputStream);
|
||||
} finally {
|
||||
delete(tmpPath);
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,19 +290,17 @@ 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 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");
|
||||
|
@ -338,15 +332,10 @@ public class PDFRasterizer {
|
|||
gsArgs.add("-sOutputFile=" + target.toString());
|
||||
gsArgs.add(pdfapsPath.toAbsolutePath().toString());
|
||||
gsArgs.add(source.toString());
|
||||
Ghostscript gs = Ghostscript.getInstance();
|
||||
try {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
for (String libname : LIBNAMES) {
|
||||
return null;
|
||||
});
|
||||
String[] libnames = LINUX_LIBNAMES;
|
||||
if (Platform.getOSType() == MAC) {
|
||||
libnames = MAC_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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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,21 +21,10 @@ 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();
|
||||
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());
|
||||
|
@ -47,20 +34,22 @@ public class GhostscriptTest {
|
|||
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in a new issue