add close() method to Ghostscript

This commit is contained in:
Jörg Prante 2023-01-17 19:17:43 +01:00
parent 466cad318a
commit 3a79e6a87f
8 changed files with 166 additions and 114 deletions

View file

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

View file

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

View file

@ -31,32 +31,24 @@ public class Ghostscript {
private static Ghostscript INSTANCE; private static Ghostscript INSTANCE;
private static InputStream stdIn; private InputStream stdIn;
private static OutputStream stdOut; private OutputStream stdOut;
private static OutputStream stdErr; private OutputStream stdErr;
static { private GhostscriptLibrary libraryInstance;
try {
prepareTmp(); private Ghostscript(GhostscriptLibrary libraryInstance) {
INSTANCE = new Ghostscript(); this.libraryInstance = libraryInstance;
stdOut = new LoggingOutputStream(logger); this.stdOut = new LoggingOutputStream(logger);
stdErr = new LoggingOutputStream(logger); this.stdErr = new LoggingOutputStream(logger);
INSTANCE.setStdOut(stdOut); }
INSTANCE.setStdErr(stdErr);
} catch (Exception e) { public synchronized static Ghostscript getInstance() {
logger.log(Level.SEVERE, e.getMessage(), e); if (INSTANCE == null) {
INSTANCE = createInstance();
} }
}
private final GhostscriptLibrary libraryInstance;
private Ghostscript() {
libraryInstance = GhostscriptLibraryLoader.loadLibrary();
}
public static Ghostscript getInstance() {
return INSTANCE; return INSTANCE;
} }
@ -65,7 +57,7 @@ public class Ghostscript {
* *
* @return the Ghostscript revision data. * @return the Ghostscript revision data.
*/ */
public static GhostscriptRevision getRevision() { public synchronized static GhostscriptRevision getRevision() {
GhostscriptLibrary.gsapi_revision_s revision = new GhostscriptLibrary.gsapi_revision_s(); GhostscriptLibrary.gsapi_revision_s revision = new GhostscriptLibrary.gsapi_revision_s();
INSTANCE.libraryInstance.gsapi_revision(revision, revision.size()); INSTANCE.libraryInstance.gsapi_revision(revision, revision.size());
GhostscriptRevision result = new GhostscriptRevision(); GhostscriptRevision result = new GhostscriptRevision();
@ -83,7 +75,7 @@ public class Ghostscript {
* *
* @return The OutputStream or null * @return The OutputStream or null
*/ */
public synchronized OutputStream getStdErr() { public OutputStream getStdErr() {
return stdErr; return stdErr;
} }
@ -92,7 +84,7 @@ public class Ghostscript {
* *
* @param outputStream OutputStream object * @param outputStream OutputStream object
*/ */
public synchronized void setStdErr(OutputStream outputStream) { public void setStdErr(OutputStream outputStream) {
stdErr = outputStream; stdErr = outputStream;
} }
@ -101,7 +93,7 @@ public class Ghostscript {
* *
* @return The OutputStream or null * @return The OutputStream or null
*/ */
public synchronized OutputStream getStdOut() { public OutputStream getStdOut() {
return stdOut; return stdOut;
} }
@ -110,7 +102,7 @@ public class Ghostscript {
* *
* @param outputStream OutputStream object * @param outputStream OutputStream object
*/ */
public synchronized void setStdOut(OutputStream outputStream) { public void setStdOut(OutputStream outputStream) {
stdOut = outputStream; stdOut = outputStream;
} }
@ -119,7 +111,7 @@ public class Ghostscript {
* *
* @return The InputStream or null * @return The InputStream or null
*/ */
public synchronized InputStream getStdIn() { public InputStream getStdIn() {
return stdIn; return stdIn;
} }
@ -128,7 +120,7 @@ public class Ghostscript {
* *
* @param inputStream InputStream object * @param inputStream InputStream object
*/ */
public synchronized void setStdIn(InputStream inputStream) { public void setStdIn(InputStream inputStream) {
stdIn = inputStream; stdIn = inputStream;
} }
@ -265,6 +257,35 @@ public class Ghostscript {
} }
} }
public synchronized void close() throws IOException {
if (stdIn != null) {
stdIn.close();
stdIn = 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 { private static void prepareTmp() throws IOException {
String tmp = System.getenv("TMPDIR"); // the variable that ghostscript uses String tmp = System.getenv("TMPDIR"); // the variable that ghostscript uses
if (tmp == null) { if (tmp == null) {

View file

@ -106,73 +106,77 @@ public class PDFConverter {
if (outputStream == null) { if (outputStream == null) {
return; return;
} }
prepare(tmpPath);
Path output = Files.createTempFile(tmpPath, "pdf", "pdf");
Ghostscript gs = Ghostscript.getInstance(); Ghostscript gs = Ghostscript.getInstance();
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;
}
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;
}
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;
}
gsArgs.add("-dCompatibilityLevel=" + compatibilityLevel);
gsArgs.add("-dPDFX=" + pdfx);
gsArgs.add("-dDEVICEWIDTHPOINTS=" + paperSize.getWidth());
gsArgs.add("-dDEVICEHEIGHTPOINTS=" + paperSize.getHeight());
gsArgs.add("-sDEVICE=pdfwrite");
gsArgs.add("-sOutputFile=" + output.toAbsolutePath().toString());
//gsArgs.add("-q");
gsArgs.add("-f");
gsArgs.add("-");
try { try {
gs.setStdIn(inputStream); prepare(tmpPath);
gs.setStdOut(new LoggingOutputStream(logger)); Path output = Files.createTempFile(tmpPath, "pdf", "pdf");
gs.setStdErr(new LoggingOutputStream(logger)); List<String> gsArgs = new LinkedList<>();
gs.run(gsArgs.toArray(new String[gsArgs.size()])); gsArgs.add("-ps2pdf");
Files.copy(output.toAbsolutePath(), outputStream); 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;
}
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;
}
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;
}
gsArgs.add("-dCompatibilityLevel=" + compatibilityLevel);
gsArgs.add("-dPDFX=" + pdfx);
gsArgs.add("-dDEVICEWIDTHPOINTS=" + paperSize.getWidth());
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);
}
} finally { } finally {
delete(tmpPath); gs.close();
} }
} }

View file

@ -143,11 +143,15 @@ public class PDFRasterizer {
logger.info("pdfToImage args=" + gsArgs); logger.info("pdfToImage args=" + gsArgs);
// reset stdin // reset stdin
Ghostscript gs = Ghostscript.getInstance(); Ghostscript gs = Ghostscript.getInstance();
gs.setStdIn(null); try {
gs.setStdOut(new LoggingOutputStream(logger)); gs.setStdIn(null);
gs.setStdErr(new LoggingOutputStream(logger)); gs.setStdOut(new LoggingOutputStream(logger));
gs.run(gsArgs.toArray(new String[gsArgs.size()])); gs.setStdErr(new LoggingOutputStream(logger));
logger.info("pdfToImage done"); gs.run(gsArgs.toArray(new String[gsArgs.size()]));
logger.info("pdfToImage done");
} finally {
gs.close();
}
} }
public synchronized void pdfToImage(Path sourceFile, public synchronized void pdfToImage(Path sourceFile,
@ -179,12 +183,16 @@ public class PDFRasterizer {
gsArgs.add(sourceFile.toString()); gsArgs.add(sourceFile.toString());
logger.info("pdfToImage args=" + gsArgs); logger.info("pdfToImage args=" + gsArgs);
Ghostscript gs = Ghostscript.getInstance(); Ghostscript gs = Ghostscript.getInstance();
// reset stdin try {
gs.setStdIn(null); // reset stdin
gs.setStdOut(new LoggingOutputStream(logger)); gs.setStdIn(null);
gs.setStdErr(new LoggingOutputStream(logger)); gs.setStdOut(new LoggingOutputStream(logger));
gs.run(gsArgs.toArray(new String[gsArgs.size()])); gs.setStdErr(new LoggingOutputStream(logger));
logger.info("pdfToImage done"); gs.run(gsArgs.toArray(new String[gsArgs.size()]));
logger.info("pdfToImage done");
} finally {
gs.close();
}
} }
public int mergeImagesToPDF(Path sourceDir, Path targetFile) throws IOException { public int mergeImagesToPDF(Path sourceDir, Path targetFile) throws IOException {
@ -287,10 +295,14 @@ public class PDFRasterizer {
gsArgs.add("-sOutputFile=" + targetFile.toString()); gsArgs.add("-sOutputFile=" + targetFile.toString());
gsArgs.add(sourceFile.toString()); gsArgs.add(sourceFile.toString());
Ghostscript gs = Ghostscript.getInstance(); Ghostscript gs = Ghostscript.getInstance();
gs.setStdIn(null); try {
logger.info(gsArgs.toString()); gs.setStdIn(null);
gs.run(gsArgs.toArray(new String[gsArgs.size()])); logger.info(gsArgs.toString());
logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " done"); gs.run(gsArgs.toArray(new String[gsArgs.size()]));
logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " done");
} finally {
gs.close();
}
} }
public void toPDFA(Path source, Path target) throws IOException { public void toPDFA(Path source, Path target) throws IOException {
@ -326,14 +338,15 @@ public class PDFRasterizer {
gsArgs.add("-sOutputFile=" + target.toString()); gsArgs.add("-sOutputFile=" + target.toString());
gsArgs.add(pdfapsPath.toAbsolutePath().toString()); gsArgs.add(pdfapsPath.toAbsolutePath().toString());
gsArgs.add(source.toString()); gsArgs.add(source.toString());
Ghostscript gs = Ghostscript.getInstance();
try { try {
Ghostscript gs = Ghostscript.getInstance();
gs.setStdIn(null); gs.setStdIn(null);
gs.run(gsArgs.toArray(new String[gsArgs.size()])); gs.run(gsArgs.toArray(new String[gsArgs.size()]));
} finally { } finally {
delete(pdfapsPathTmp); delete(pdfapsPathTmp);
delete(pdfapsPath); delete(pdfapsPath);
delete(iccPath); delete(iccPath);
gs.close();
} }
} }

View file

@ -1,4 +1,4 @@
package org.xbib.graphics.ghostscript; package org.xbib.graphics.ghostscript.test;
import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.IntByReference;
import org.xbib.graphics.ghostscript.internal.GhostscriptLibrary; import org.xbib.graphics.ghostscript.internal.GhostscriptLibrary;

View file

@ -3,7 +3,6 @@ package org.xbib.graphics.ghostscript.test;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.xbib.graphics.ghostscript.GhostScriptLibraryTester;
import java.io.File; import java.io.File;
import java.util.logging.Logger; import java.util.logging.Logger;

View file

@ -1,5 +1,8 @@
package org.xbib.graphics.ghostscript.test; 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.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.xbib.graphics.ghostscript.Ghostscript; import org.xbib.graphics.ghostscript.Ghostscript;
@ -20,7 +23,17 @@ public class GhostscriptTest {
private static final String dir = "src/test/resources/org/xbib/graphics/ghostscript/test/"; private static final String dir = "src/test/resources/org/xbib/graphics/ghostscript/test/";
private static final Ghostscript gs = Ghostscript.getInstance(); static Ghostscript gs;
@BeforeAll
public static void init() {
gs = Ghostscript.getInstance();
}
@AfterAll
public static void shutdown() throws IOException {
gs.close();
}
@Test @Test
public void testGetRevision() { public void testGetRevision() {