diff --git a/htroot/CrawlStartExpert.java b/htroot/CrawlStartExpert.java index 778df5f74..546afb335 100644 --- a/htroot/CrawlStartExpert.java +++ b/htroot/CrawlStartExpert.java @@ -513,9 +513,11 @@ public class CrawlStartExpert { // ---------- Snapshot generation + boolean wkhtmltopdfAvailable = Html2Image.wkhtmltopdfAvailable(); + boolean convertAvailable = Html2Image.convertAvailable(); if (sb.getConfigBool("isTransparentProxy", false) && sb.getConfigBool("proxyAlwaysFresh", false) && - Html2Image.wkhtmltopdfAvailable() && Html2Image.convertAvailable()) { + wkhtmltopdfAvailable && convertAvailable) { prop.put("snapshotSelect", 1); prop.put("snapshotSelect_snapshotsMaxDepth", post == null ? "-1" : post.get("snapshotsMaxDepth", "-1")); } else { diff --git a/source/net/yacy/cora/util/Html2Image.java b/source/net/yacy/cora/util/Html2Image.java index e9d06f361..bba7bced2 100644 --- a/source/net/yacy/cora/util/Html2Image.java +++ b/source/net/yacy/cora/util/Html2Image.java @@ -30,10 +30,15 @@ import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.ImageView; +import net.yacy.document.ImageParser; +import net.yacy.kelondro.util.FileUtils; import net.yacy.kelondro.util.OS; +import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.Image; +import java.awt.MediaTracker; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -46,8 +51,10 @@ public class Html2Image { // Mac // to install wkhtmltopdf, download wkhtmltox-0.12.1_osx-cocoa-x86-64.pkg from http://wkhtmltopdf.org/downloads.html // to install imagemagick, download from http://cactuslab.com/imagemagick/assets/ImageMagick-6.8.9-9.pkg.zip + // the convert command from imagemagick needs ghostscript, if not present on older macs, download a version of gs from http://pages.uoregon.edu/koch/ private final static File wkhtmltopdfMac = new File("/usr/local/bin/wkhtmltopdf"); - private final static File convertMac = new File("/opt/local/bin/convert"); + private final static File convertMac1 = new File("/opt/local/bin/convert"); + private final static File convertMac2 = new File("/opt/ImageMagick/bin/convert"); // debian // to install: apt-get install wkhtmltopdf imagemagick xvfb @@ -61,7 +68,7 @@ public class Html2Image { } public static boolean convertAvailable() { - return convertMac.exists() || convertDebian.exists(); + return convertMac1.exists() || convertMac2.exists() || convertDebian.exists(); } /** @@ -120,13 +127,50 @@ public class Html2Image { * @return */ public static boolean pdf2image(File pdf, File image, int width, int height, int density, int quality) { - final File convert = convertMac.exists() ? convertMac : convertDebian; + final File convert = convertMac1.exists() ? convertMac1 : convertMac2.exists() ? convertMac2 : convertDebian; try { // i.e. convert -density 300 -trim yacy.pdf[0] -trim -resize 1024x -crop x1024+0+0 -quality 75% yacy-convert-300.jpg // note: both -trim are necessary, otherwise it is trimmed only on one side. The [0] selects the first page of the pdf - OS.execSynchronous(convert.getAbsolutePath() + " -density " + density + " -trim " + pdf.getAbsolutePath() + "[0] -trim -resize " + width + "x -crop x" + height + "+0+0 -quality " + quality + "% " + image.getAbsolutePath()); - return image.exists(); + String command = convert.getAbsolutePath() + " -density " + density + " -trim " + pdf.getAbsolutePath() + "[0] -trim -resize " + width + "x -crop x" + height + "+0+0 -quality " + quality + "% " + image.getAbsolutePath(); + List message = OS.execSynchronous(command); + if (image.exists()) return true; + ConcurrentLog.warn("Html2Image", "failed to create image with command: " + command); + for (String m: message) ConcurrentLog.warn("Html2Image", ">> " + m); + + // another try for mac: use Image Events using AppleScript in osacript commands... + // the following command overwrites a pdf with an png, so we must make a copy first + if (!OS.isMacArchitecture) return false; + File pngFile = new File(pdf.getAbsolutePath() + ".tmp.pdf"); + org.apache.commons.io.FileUtils.copyFile(pdf, pngFile); + String[] commandx = {"osascript", + "-e", "set ImgFile to \"" + pngFile.getAbsolutePath() + "\"", + "-e", "tell application \"Image Events\"", + "-e", "set Img to open file ImgFile", + "-e", "save Img as PNG", + "-e", "end tell"}; + //ConcurrentLog.warn("Html2Image", "failed to create image with command: " + commandx); + message = OS.execSynchronous(commandx); + for (String m: message) ConcurrentLog.warn("Html2Image", ">> " + m); + // now we must read and convert this file to a jpg with the target size 1024x1024 + try { + File newPngFile = new File(pngFile.getAbsolutePath() + ".png"); + pngFile.renameTo(newPngFile); + Image img = ImageParser.parse(pngFile.getAbsolutePath(), FileUtils.read(newPngFile)); + final Image scaled = img.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING); + final MediaTracker mediaTracker = new MediaTracker(new Container()); + mediaTracker.addImage(scaled, 0); + try {mediaTracker.waitForID(0);} catch (final InterruptedException e) {} + // finally write the image + final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + bi.createGraphics().drawImage(scaled, 0, 0, width, height, null); + ImageIO.write(bi, "jpg", image); + newPngFile.delete(); + return image.exists(); + } catch (IOException e) { + ConcurrentLog.logException(e); + return false; + } } catch (IOException e) { e.printStackTrace(); return false; diff --git a/source/net/yacy/kelondro/util/OS.java b/source/net/yacy/kelondro/util/OS.java index 452a4b815..008b75562 100644 --- a/source/net/yacy/kelondro/util/OS.java +++ b/source/net/yacy/kelondro/util/OS.java @@ -196,19 +196,31 @@ public final class OS { FileUtils.deletedelete(starterFile); } - public static List execSynchronous(final String command) throws IOException { - // runs a unix/linux command and returns output as Vector of Strings - // this method blocks until the command is executed - final Process p = Runtime.getRuntime().exec(command); - final BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); - String text; - final List output = new ArrayList(); - while ((text = in.readLine()) != null) { - output.add(text); - } - in.close(); - return output; - } + public static List execSynchronous(final String command) throws IOException { + // runs a unix/linux command and returns output as Vector of Strings + // this method blocks until the command is executed + final Process p = Runtime.getRuntime().exec(command); + return execSynchronousProcess(p); + } + + public static List execSynchronous(final String[] command) throws IOException { + // runs a unix/linux command and returns output as Vector of Strings + // this method blocks until the command is executed + final Process p = Runtime.getRuntime().exec(command); + return execSynchronousProcess(p); + } + + private static List execSynchronousProcess(Process p) throws IOException { + String line; + BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); + final List output = new ArrayList(); + while ((line = in.readLine()) != null) output.add(line); + in.close(); + in = new BufferedReader(new InputStreamReader(p.getErrorStream())); + while ((line = in.readLine()) != null) output.add(line); + in.close(); + return output; + } public static void main(final String[] args) { try {