OSDN Git Service

Change directory structure.
[dvibrowser/dvi2epub.git] / src / main / java / jp / sourceforge / dvibrowser / dvicore / cli / tools / ConvertToImage.java
diff --git a/src/main/java/jp/sourceforge/dvibrowser/dvicore/cli/tools/ConvertToImage.java b/src/main/java/jp/sourceforge/dvibrowser/dvicore/cli/tools/ConvertToImage.java
new file mode 100644 (file)
index 0000000..89ff203
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2009, Takeyuki Nagao
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the
+ * following conditions are met:
+ * 
+ *  * Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer in the documentation and/or other
+ *    materials provided with the distribution.
+ *    
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+package jp.sourceforge.dvibrowser.dvicore.cli.tools;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FilterOutputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.imageio.ImageIO;
+
+import jp.sourceforge.dvibrowser.dvicore.DviException;
+import jp.sourceforge.dvibrowser.dvicore.DviObject;
+import jp.sourceforge.dvibrowser.dvicore.DviPaperSize;
+import jp.sourceforge.dvibrowser.dvicore.DviRect;
+import jp.sourceforge.dvibrowser.dvicore.DviResolution;
+import jp.sourceforge.dvibrowser.dvicore.api.DviContext;
+import jp.sourceforge.dvibrowser.dvicore.api.DviContextSupport;
+import jp.sourceforge.dvibrowser.dvicore.api.DviDocument;
+import jp.sourceforge.dvibrowser.dvicore.api.DviPage;
+import jp.sourceforge.dvibrowser.dvicore.ctx.DefaultDviContext;
+import jp.sourceforge.dvibrowser.dvicore.gui.swing.ViewSpec;
+import jp.sourceforge.dvibrowser.dvicore.image.split.ImageFileConfig;
+import jp.sourceforge.dvibrowser.dvicore.util.Benchmark;
+import jp.sourceforge.dvibrowser.dvicore.util.DviUtils;
+import jp.sourceforge.dvibrowser.dvicore.util.ZipBuilder;
+
+
+public class ConvertToImage
+extends DviObject
+{
+  private static final String OPT_SHRINK_FACTOR = "--shrink-factor=";
+  private static final String OPT_DPI = "--dpi=";
+  private static final String OPT_OUTPUT_FILE = "--output-file=";
+  private static final String OPT_RESOURCES_FILE = "--resources-file=";
+  private static final String OPT_PAPER_SIZE = "--paper-size=";
+  private static final String OPT_USE_BBOX = "--use-bbox=";
+  private static final String OPT_PADDING = "--padding=";
+  private static final Logger LOGGER = Logger.getLogger(ConvertToImage.class
+      .getName());
+  
+  public static class Config
+  extends DviObject
+  {
+    private final ViewSpec viewSpec;
+    private final ArrayList<File> inputs = new ArrayList<File>();
+    private boolean useBoundingBox;
+    private File outputFile;
+    private DviPaperSize paperSize;
+    private ImageFileConfig imageFileConfig;
+    private int padding;
+       private File resourcesFile;
+    
+    public Config(DviContextSupport dcs) {
+      super(dcs);
+      viewSpec = new ViewSpec(dcs);
+      try {
+        setPaperSize(getDviContext().getDefaultPaperSize());
+      } catch (DviException e) {
+        DviUtils.logStackTrace(LOGGER, Level.WARNING, e);
+        setPaperSize(DviPaperSize.FALLBACK);
+      }
+      // TODO: outsource the config.
+      imageFileConfig = ImageFileConfig.PNG;
+      padding = 0;
+    }
+    
+    public void setDpi(int dpi)
+    {
+      viewSpec.setResolution(new DviResolution(dpi, viewSpec.getResolution().shrinkFactor()));
+    }
+    
+    public void setShrinkFactor(int sf)
+    {
+      viewSpec.setResolution(new DviResolution(viewSpec.getResolution().dpi(), sf));
+    }
+    
+    public ViewSpec getViewSpec() {
+      return viewSpec;
+    }
+    
+    public void setUseBoundingBox(boolean crop) {
+      this.useBoundingBox = crop;
+    }
+    
+    public boolean useBoundingBox() { return useBoundingBox; }
+    
+    public void setOutputFile(File outputFile) {
+      if (outputFile != null) {
+        this.outputFile = outputFile;
+      } else {
+        this.outputFile = null;
+      }
+    }
+    
+    public void addInputFile(File file)
+    {
+      if (file != null) {
+        inputs.add(file);
+      } else {
+        LOGGER.warning("Input file is null. Ignored.");
+      }
+    }
+
+    public File getOutputFile() {
+      return outputFile;
+    }
+    
+    public DviPaperSize getPaperSize() {
+      return paperSize;
+    }
+    
+
+    public ArrayList<File> getInputs() {
+      return inputs;
+    }
+    
+    public void parseArguments(String [] args) throws DviException
+    {
+      final DviContext ctx = getDviContext();
+      for (int i=0; i<args.length; i++) {
+        String a = args[i];
+        if (a.startsWith(OPT_DPI)) {
+          int dpi = Integer.parseInt(a.substring(OPT_DPI.length()));
+          setShrinkFactor(dpi);
+        } else if (a.startsWith(OPT_SHRINK_FACTOR)) {
+          int sf = Integer.parseInt(a.substring(OPT_SHRINK_FACTOR.length()));
+          setShrinkFactor(sf);
+        } else if (a.startsWith(OPT_PADDING)) {
+          int padding = Integer.parseInt(a.substring(OPT_PADDING.length()));
+          setPaddingSize(padding);
+        } else if (a.startsWith(OPT_PAPER_SIZE)) {
+          String s = a.substring(OPT_PAPER_SIZE.length());
+          DviPaperSize paperSize = ctx.findPaperSizeByName(s);
+          if (paperSize == null) {
+            throw new DviException("Unrecognized papersize: " + s);
+          }
+        } else if (a.startsWith(OPT_RESOURCES_FILE)) {
+            String s = a.substring(OPT_RESOURCES_FILE.length()).trim();
+            if (!"".equals(s)) {
+              setResourcesFile(new File(s));
+            } else {
+              throw new DviException("Output filename is empty.");
+            }
+        } else if (a.startsWith(OPT_OUTPUT_FILE)) {
+          String s = a.substring(OPT_OUTPUT_FILE.length()).trim();
+          if (!"".equals(s)) {
+            setOutputFile(new File(s));
+          } else {
+            throw new DviException("Output filename is empty.");
+          }
+        } else if (a.startsWith(OPT_USE_BBOX)) {
+          String s = a.substring(OPT_USE_BBOX.length()).trim();
+          if ("yes".equalsIgnoreCase(s)) {
+            setUseBoundingBox(true);
+          } else if ("no".equalsIgnoreCase(s)) {
+              setUseBoundingBox(false);
+          } else {
+            throw new DviException("Invalid parameter value: " + a);
+          }
+        } else if (a.startsWith("-")) {
+          throw new DviException("Unrecognized commandline option: " + a);
+        } else {
+          for (; i<args.length; i++) {
+            a = args[i];
+            addInputFile(new File(a));
+          }
+        }
+      }
+    }
+
+    private void setResourcesFile(File file) {
+       this.resourcesFile = file;
+       }
+
+       public File getResourcesFile() {
+               return resourcesFile;
+       }
+
+       private void setPaddingSize(int padding) {
+      this.setPadding(padding);
+    }
+
+    public void setPaperSize(DviPaperSize paperSize) {
+      this.paperSize = paperSize;
+    }
+    
+    public ImageFileConfig getImageFileConfig()
+    {
+      return imageFileConfig;
+    }
+
+    public void setImageFileConfig(ImageFileConfig imageFileConfig) {
+      this.imageFileConfig = imageFileConfig;
+    }
+    
+    public static String getUsage()
+    {
+      StringWriter sw = new StringWriter();
+      PrintWriter pw = new PrintWriter(sw);
+      pw.println("usage: java " + ConvertToImage.class.getName() + " [options] <input-files>");
+      pw.println("  options: ");
+      pw.println("    --dpi=N            Set output DPI to N");
+      pw.println("    --shrink-factor=N  Set shrink factor to N (1--1024)");
+      pw.println("    --output-file=F    Set output zip file to F");
+      pw.println("    --resources-file=F Set resources file to F");
+      pw.println("    --padding=N        Set padding size to N");
+      return sw.toString();
+    }
+    
+    public void showUsage()
+    {
+      System.err.println(getUsage());
+    }
+
+    public boolean isValid() {
+      return getInputs().size() > 0;
+    }
+
+    public void setPadding(int padding) {
+      this.padding = padding;
+    }
+
+    public int getPadding() {
+      return padding;
+    }
+  }
+  
+  public ConvertToImage(DviContextSupport dcs) {
+    super(dcs);
+  }
+
+  public int convert(Config config) throws Exception {
+    DviContext ctx = getDviContext();
+    ViewSpec vs = config.getViewSpec();
+    DviResolution res = vs.getResolution();
+    File outputFile = config.getOutputFile();
+    OutputStream os = null;
+    if (outputFile != null) {
+      if (!outputFile.getName().toLowerCase().endsWith(".zip")) {
+        outputFile = new File(outputFile.getParentFile(), outputFile.getName() + ".zip");
+      }
+      os = new FileOutputStream(outputFile);
+      LOGGER.info("Writing outputs to " + outputFile);
+    } else {
+      os = new FilterOutputStream(System.out) {
+        @Override
+        public void close()
+        {
+          // We don't close the stdout.
+        }
+      };
+    }
+    ZipBuilder zb = new ZipBuilder(os);
+    
+    try {
+      for (File file : config.getInputs()) {
+        try {
+          DviDocument doc = ctx.openDviDocument(file);
+          LOGGER.info("Processing file: " + file);
+          for (int i=0; i<doc.getTotalPages(); i++) {
+            DviPage page = doc.getPage(i);
+            LOGGER.info("Processing page " + (i + 1) + "/" + doc.getTotalPages());
+            DviRect bbox;
+            if (config.useBoundingBox()) {
+              bbox = 
+                ctx.getDviToolkit().computeBoundingBox(page, res);
+            } else {
+              bbox = config.getPaperSize().toBoundingBox(res);
+            }
+            bbox = bbox.addPadding(config.getPadding());
+            
+            BufferedImage img = ctx.getDviToolkit().renderToBufferedImage(page, bbox, vs);
+            if (img == null) {
+              throw new DviException("Failed to render page " + (i + 1));
+            }
+            
+            OutputStream imageOut = zb.openOutputStream
+              (String.format("%04d%s", i+1, config.getImageFileConfig().getImageExtension()));
+            try {
+              ImageIO.write(img, config.getImageFileConfig().getImageType(), imageOut);
+            } finally {
+              DviUtils.silentClose(imageOut);
+            }
+          }
+        } catch (DviException e) {
+          DviUtils.logStackTrace(LOGGER, Level.SEVERE, e);
+          throw e;
+        }
+      }
+    } finally {
+      DviUtils.silentClose(zb);
+    }
+    return 0;
+  }
+
+  public static void main(String[] args)
+  {
+    try {
+      DefaultDviContext ctx = new DefaultDviContext();
+      
+      Config config = new Config(ctx);
+      config.parseArguments(args);
+      
+      if (!config.isValid()) {
+        config.showUsage();
+        throw new DviException
+          ("Unrecognized command line: " + DviUtils.join(" ", args));
+      }
+      
+      File resourcesFile = config.getResourcesFile();
+
+      if (resourcesFile != null) {
+         ctx.setRecordResources(true);
+      }
+      
+      Benchmark benchmark = new Benchmark();
+      benchmark.begin("dvi rendering");
+      benchmark.addSample();
+      ConvertToImage app = new ConvertToImage(ctx);
+      int retcode = app.convert(config);
+      benchmark.end();
+      
+      if (resourcesFile != null) {
+       Set<URL> resources = ctx.getRecordedResources();
+       FileOutputStream fos = new FileOutputStream(resourcesFile);
+       PrintWriter out = new PrintWriter(fos);
+       for (URL url : resources) {
+               out.println(url);
+       }
+       out.flush();
+       out.close();
+       fos.close();
+      }
+      
+      LOGGER.info("Finished: " + benchmark.format());
+      // INT_ARGB: Finished: Benchmark result: dvi rendering: 1 samples in 68.182 sec. 0.015 samples/sec.  68182 msec./sample.
+      // INT_RGB: Finished: Benchmark result: dvi rendering: 1 samples in 62.976 sec. 0.016 samples/sec.  62976 msec./sample.
+      System.exit(retcode);
+    } catch (Exception e) {
+      DviUtils.logStackTrace(LOGGER, Level.WARNING, e);
+      System.exit(1);
+    }
+  }
+
+}