You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ms...@apache.org on 2020/12/06 16:13:01 UTC
svn commit: r1884154 -
/pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java
Author: msahyoun
Date: Sun Dec 6 16:13:01 2020
New Revision: 1884154
URL: http://svn.apache.org/viewvc?rev=1884154&view=rev
Log:
PDFBOX-2602: use picocli for command line parsing
Modified:
pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java
Modified: pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java?rev=1884154&r1=1884153&r2=1884154&view=diff
==============================================================================
--- pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java (original)
+++ pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/ExtractImages.java Sun Dec 6 16:13:01 2020
@@ -22,11 +22,14 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.PrintStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.Callable;
+import org.apache.commons.io.FilenameUtils;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.contentstream.PDFGraphicsStreamEngine;
import org.apache.pdfbox.cos.COSName;
@@ -53,137 +56,80 @@ import org.apache.pdfbox.tools.imageio.I
import org.apache.pdfbox.util.Matrix;
import org.apache.pdfbox.util.Vector;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.Parameters;
+
/**
* Extracts the images from a PDF file.
*
* @author Ben Litchfield
*/
-public final class ExtractImages
+@Command(name = "ExtractImages", description = "Extracts the images from a PDF file.")
+public final class ExtractImages implements Callable<Integer>
{
- @SuppressWarnings({"squid:S2068"})
- private static final String PASSWORD = "-password";
- private static final String PREFIX = "-prefix";
- private static final String DIRECTJPEG = "-directJPEG";
- private static final String NOCOLORCONVERT = "-noColorConvert";
+ @Option(names = {"-h", "--help"}, usageHelp = true, description = "display this help message")
+ boolean usageHelpRequested;
- private static final List<String> JPEG = Arrays.asList(
- COSName.DCT_DECODE.getName(),
- COSName.DCT_DECODE_ABBREVIATION.getName());
+ @Option(names = "-password", description = "the password for the PDF or certificate in keystore.")
+ private String password;
+ @Option(names = "-prefix", description = "the image prefix (default to pdf name).")
+ private String prefix;
+
+ @Option(names = "-useDirectJPEG", description = "Forces the direct extraction of JPEG/JPX images " +
+ "regardless of colorspace or masking.")
private boolean useDirectJPEG;
+
+ @Option(names = "-noColorConvert", description = "Images are extracted with their " +
+ "original colorspace if possible.")
private boolean noColorConvert;
- private String prefix;
+
+ @Parameters(paramLabel = "inputfile", index = "0", arity = "1", description = "the PDF file to decrypt.")
+ private File infile;
+
+ // Expected for CLI app to write to System.out/Sytem.err
+ @SuppressWarnings("squid:S106")
+ private PrintStream sysout = System.out;
+ @SuppressWarnings("squid:S106")
+ private PrintStream syserr = System.err;
+
+ private static final List<String> JPEG = Arrays.asList(
+ COSName.DCT_DECODE.getName(),
+ COSName.DCT_DECODE_ABBREVIATION.getName());
private final Set<COSStream> seen = new HashSet<>();
private int imageCounter = 1;
- private ExtractImages()
- {
- }
-
/**
* Entry point for the application.
*
* @param args The command-line arguments.
- * @throws IOException if there is an error reading the file or extracting the images.
*/
- public static void main(String[] args) throws IOException
+ public static void main(String[] args)
{
// suppress the Dock icon on OS X
System.setProperty("apple.awt.UIElement", "true");
- ExtractImages extractor = new ExtractImages();
- extractor.run(args);
+ int exitCode = new CommandLine(new ExtractImages()).execute(args);
+ System.exit(exitCode);
}
- private void run(String[] args) throws IOException
+ public Integer call()
{
- if (args.length < 1 || args.length > 4)
- {
- usage();
- }
- else
+ try (PDDocument document = Loader.loadPDF(infile, password))
{
- String pdfFile = null;
- @SuppressWarnings({"squid:S2068"})
- String password = "";
- for(int i = 0; i < args.length; i++)
- {
- switch (args[i])
- {
- case PASSWORD:
- i++;
- if (i >= args.length)
- {
- usage();
- }
- password = args[i];
- break;
- case PREFIX:
- i++;
- if (i >= args.length)
- {
- usage();
- }
- prefix = args[i];
- break;
- case DIRECTJPEG:
- useDirectJPEG = true;
- break;
- case NOCOLORCONVERT:
- noColorConvert = true;
- break;
- default:
- if (pdfFile == null)
- {
- pdfFile = args[i];
- }
- break;
- }
- }
- if (pdfFile == null)
- {
- usage();
- }
- else
+ AccessPermission ap = document.getCurrentAccessPermission();
+ if (!ap.canExtractContent())
{
- if (prefix == null && pdfFile.length() >4)
- {
- prefix = pdfFile.substring(0, pdfFile.length() -4);
- }
-
- extract(pdfFile, password);
+ syserr.println("You do not have permission to extract images");
+ return 1;
}
- }
- }
- /**
- * Print the usage requirements and exit.
- */
- private static void usage()
- {
- String message = "Usage: java " + ExtractImages.class.getName() + " [options] <inputfile>\n"
- + "\nOptions:\n"
- + " -password <password> : Password to decrypt document\n"
- + " -prefix <image-prefix> : Image prefix (default to pdf name)\n"
- + " -directJPEG : Forces the direct extraction of JPEG/JPX images \n"
- + " regardless of colorspace or masking\n"
- + " -noColorConvert : Images are extracted with their \n"
- + " original colorspace if possible.\n"
- + " <inputfile> : The PDF document to use\n";
-
- System.err.println(message);
- System.exit(1);
- }
-
- private void extract(String pdfFile, String password) throws IOException
- {
- try (PDDocument document = Loader.loadPDF(new File(pdfFile), password))
- {
- AccessPermission ap = document.getCurrentAccessPermission();
- if (!ap.canExtractContent())
+ if (prefix == null)
{
- throw new IOException("You do not have permission to extract images");
+ prefix = FilenameUtils.removeExtension(infile.getAbsolutePath());
}
for (PDPage page : document.getPages())
@@ -192,6 +138,12 @@ public final class ExtractImages
extractor.run();
}
}
+ catch (IOException ioe)
+ {
+ syserr.println("Error extracting images: " + ioe.getMessage());
+ return 4;
+ }
+ return 0;
}
private class ImageGraphicsEngine extends PDFGraphicsStreamEngine
@@ -255,7 +207,6 @@ public final class ExtractImages
String name = prefix + "-" + imageCounter;
imageCounter++;
- System.out.println("Writing image: " + name);
write2file(pdImage, name, useDirectJPEG, noColorConvert);
}
@@ -263,32 +214,32 @@ public final class ExtractImages
public void appendRectangle(Point2D p0, Point2D p1, Point2D p2, Point2D p3)
throws IOException
{
-
+ // Empty: add special handling if needed
}
@Override
public void clip(int windingRule) throws IOException
{
-
+ // Empty: add special handling if needed
}
@Override
public void moveTo(float x, float y) throws IOException
{
-
+ // Empty: add special handling if needed
}
@Override
public void lineTo(float x, float y) throws IOException
{
-
+ // Empty: add special handling if needed
}
@Override
public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3)
throws IOException
{
-
+ // Empty: add special handling if needed
}
@Override
@@ -300,13 +251,13 @@ public final class ExtractImages
@Override
public void closePath() throws IOException
{
-
+ // Empty: add special handling if needed
}
@Override
public void endPath() throws IOException
{
-
+ // Empty: add special handling if needed
}
@Override
@@ -347,7 +298,7 @@ public final class ExtractImages
@Override
public void shadingFill(COSName shadingName) throws IOException
{
-
+ // Empty: add special handling if needed
}
// find out if it is a tiling pattern, then process that one
@@ -411,16 +362,20 @@ public final class ExtractImages
// but a TIFF codec must be in the class path for this to work.
suffix = "tiff";
}
- try (FileOutputStream out = new FileOutputStream(prefix + "." + suffix))
+ try (FileOutputStream imageOutput = new FileOutputStream(prefix + "." + suffix))
{
- ImageIOUtil.writeImage(image, suffix, out);
- out.flush();
+ sysout.println("Writing image: " + prefix + "." + suffix);
+ ImageIOUtil.writeImage(image, suffix, imageOutput);
+ imageOutput.flush();
}
return;
}
}
- try (FileOutputStream out = new FileOutputStream(prefix + "." + suffix))
+
+ try (FileOutputStream imageOutput = new FileOutputStream(prefix + "." + suffix))
{
+ sysout.println("Writing image: " + prefix + "." + suffix);
+
if ("jpg".equals(suffix))
{
String colorSpaceName = pdImage.getColorSpace().getName();
@@ -430,7 +385,7 @@ public final class ExtractImages
{
// RGB or Gray colorspace: get and write the unmodified JPEG stream
InputStream data = pdImage.createInputStream(JPEG);
- IOUtils.copy(data, out);
+ IOUtils.copy(data, imageOutput);
IOUtils.closeQuietly(data);
}
else
@@ -439,7 +394,7 @@ public final class ExtractImages
BufferedImage image = pdImage.getImage();
if (image != null)
{
- ImageIOUtil.writeImage(image, suffix, out);
+ ImageIOUtil.writeImage(image, suffix, imageOutput);
}
}
}
@@ -453,7 +408,7 @@ public final class ExtractImages
// RGB or Gray colorspace: get and write the unmodified JPEG2000 stream
InputStream data = pdImage.createInputStream(
Arrays.asList(COSName.JPX_DECODE.getName()));
- IOUtils.copy(data, out);
+ IOUtils.copy(data, imageOutput);
IOUtils.closeQuietly(data);
}
else
@@ -462,7 +417,7 @@ public final class ExtractImages
BufferedImage image = pdImage.getImage();
if (image != null)
{
- ImageIOUtil.writeImage(image, "jpeg2000", out);
+ ImageIOUtil.writeImage(image, "jpeg2000", imageOutput);
}
}
}
@@ -487,17 +442,17 @@ public final class ExtractImages
bitonalImage.setRGB(x, y, image.getRGB(x, y));
}
}
- ImageIOUtil.writeImage(bitonalImage, suffix, out);
+ ImageIOUtil.writeImage(bitonalImage, suffix, imageOutput);
}
else
{
BufferedImage image = pdImage.getImage();
if (image != null)
{
- ImageIOUtil.writeImage(image, suffix, out);
+ ImageIOUtil.writeImage(image, suffix, imageOutput);
}
}
- out.flush();
+ imageOutput.flush();
}
}