From d0aee5b0b2cbd0805c3dec027c6f2d2ac0148e66 Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Wed, 13 Sep 2023 17:28:11 +0100 Subject: [PATCH] JAL-4274 Use Cache BITMAP_* if no other image restrictions given --- src/jalview/bin/Cache.java | 46 +++++++++---- src/jalview/gui/AlignmentPanel.java | 5 +- src/jalview/gui/AppJmol.java | 71 ++++++++++---------- src/jalview/gui/ImageExporter.java | 2 +- src/jalview/util/ImageMaker.java | 44 +++++++++--- src/jalview/util/imagemaker/BitmapImageSizing.java | 51 +++++++++++--- .../util/imagemaker/BitmapImageSizeTest.java | 51 +++++++------- 7 files changed, 178 insertions(+), 92 deletions(-) diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java index 038a5a0..9266d2a 100755 --- a/src/jalview/bin/Cache.java +++ b/src/jalview/bin/Cache.java @@ -141,7 +141,8 @@ import jalview.ws.sifts.SiftsSettings; *
  • WRAP_ALIGNMENT
  • *
  • EPS_RENDERING (Prompt each time|Lineart|Text) default for EPS rendering * style check
  • - *
  • BITMAP_SCALE - scale factor for PNG export - default 0 - native resolution
  • + *
  • BITMAP_SCALE - scale factor for PNG export - default 0.0 - native + * resolution
  • *
  • BITMAP_HEIGHT - height bound for PNG export or 0 for unbound
  • *
  • BITMAP_WIDTH - width bound for PNG export or 0 for unbound
  • *
  • SORT_ALIGNMENT (No sort|Id|Pairwise Identity)
  • @@ -641,8 +642,8 @@ public class Cache url = Cache.class.getResource(resourcePath).toString(); } catch (Exception ex) { - jalview.bin.Console.errPrintln("Failed to resolve resource " + resourcePath - + ": " + ex.getMessage()); + jalview.bin.Console.errPrintln("Failed to resolve resource " + + resourcePath + ": " + ex.getMessage()); } } else @@ -799,6 +800,25 @@ public class Cache return def; } + public static float getDefault(String property, float def) + { + String string = getProperty(property); + if (string != null) + { + try + { + def = Float.parseFloat(string); + } catch (NumberFormatException e) + { + if (!Jalview.quiet()) + jalview.bin.Console.outPrintln("Error parsing float property '" + + property + "' with value '" + string + "'"); + } + } + + return def; + } + /** * Answers the value of the given property, or the supplied default value if * the property is not set @@ -1064,8 +1084,9 @@ public class Cache return date_format.parse(val); } catch (Exception ex) { - jalview.bin.Console.errPrintln("Invalid or corrupt date in property '" - + propertyName + "' : value was '" + val + "'"); + jalview.bin.Console + .errPrintln("Invalid or corrupt date in property '" + + propertyName + "' : value was '" + val + "'"); } } return null; @@ -1088,8 +1109,8 @@ public class Cache return Integer.valueOf(val); } catch (NumberFormatException x) { - jalview.bin.Console.errPrintln("Invalid integer in property '" + property - + "' (value was '" + val + "')"); + jalview.bin.Console.errPrintln("Invalid integer in property '" + + property + "' (value was '" + val + "')"); } } return null; @@ -1632,7 +1653,6 @@ public class Cache private static final Collection bootstrapProperties = new ArrayList<>( Arrays.asList(JALVIEWLOGLEVEL, BOOTSTRAP_TEST)); - public static Properties bootstrapProperties(String filename) { Properties bootstrapProps = new Properties(); @@ -1661,8 +1681,9 @@ public class Cache return null; if (!file.exists()) { - jalview.bin.Console.errPrintln("Could not load bootstrap preferences file '" - + filename + "'"); + jalview.bin.Console + .errPrintln("Could not load bootstrap preferences file '" + + filename + "'"); return null; } @@ -1678,8 +1699,9 @@ public class Cache } } catch (FileNotFoundException e) { - jalview.bin.Console.errPrintln("Could not find bootstrap preferences file '" - + file.getAbsolutePath() + "'"); + jalview.bin.Console + .errPrintln("Could not find bootstrap preferences file '" + + file.getAbsolutePath() + "'"); } catch (IOException e) { jalview.bin.Console.errPrintln( diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index ce87c01..7ed5227 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -341,7 +341,8 @@ public class AlignmentPanel extends GAlignmentPanel implements if (Jalview.isHeadlessMode()) { AnnotationLabels aal = getAlabels(); - int stringWidth = aal.drawLabels(null, false, idWidth, false, false, fm); + int stringWidth = aal.drawLabels(null, false, idWidth, false, false, + fm); idWidth = Math.max(idWidth, stringWidth); } else @@ -1229,7 +1230,7 @@ public class AlignmentPanel extends GAlignmentPanel implements throws ImageOutputException { makeAlignmentImage(type, file, renderer, - BitmapImageSizing.nullBitmapImageSizing()); + BitmapImageSizing.defaultBitmapImageSizing()); } /** diff --git a/src/jalview/gui/AppJmol.java b/src/jalview/gui/AppJmol.java index 950f129..cfbac04 100644 --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@ -28,16 +28,10 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.io.File; -import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; import javax.swing.JPanel; import javax.swing.JSplitPane; @@ -371,8 +365,9 @@ public class AppJmol extends StructureViewerBase } if (waitTotal > waitMax) { - jalview.bin.Console.errPrintln("Timed out waiting for Jmol to load files after " - + waitTotal + "ms"); + jalview.bin.Console.errPrintln( + "Timed out waiting for Jmol to load files after " + + waitTotal + "ms"); // jalview.bin.Console.errPrintln("finished: " + jmb.isFinishedInit() // + "; loaded: " + Arrays.toString(jmb.getPdbFile()) // + "; files: " + files.toString()); @@ -434,11 +429,14 @@ public class AppJmol extends StructureViewerBase @Override public void makePDBImage(ImageMaker.TYPE type) { - try { - makePDBImage(null, type, null, - BitmapImageSizing.nullBitmapImageSizing()); - } catch (ImageOutputException ioex) { - Console.error("Unexpected error whilst writing "+type.toString(),ioex); + try + { + makePDBImage(null, type, null, + BitmapImageSizing.defaultBitmapImageSizing()); + } catch (ImageOutputException ioex) + { + Console.error("Unexpected error whilst writing " + type.toString(), + ioex); } } @@ -450,9 +448,9 @@ public class AppJmol extends StructureViewerBase BitmapImageSizing bis = ImageMaker.getScaleWidthHeight(width, height, userBis); - float usescale = bis.scale; - int usewidth = bis.width; - int useheight = bis.height; + float usescale = bis.scale(); + int usewidth = bis.width(); + int useheight = bis.height(); ImageWriterI writer = new ImageWriterI() { @@ -481,29 +479,33 @@ public class AppJmol extends StructureViewerBase .toLowerCase(Locale.ROOT); final ImageExporter exporter = new ImageExporter(writer, getProgressIndicator(), type, getTitle()); - + final Throwable[] exceptions = new Throwable[1]; exceptions[0] = null; final AppJmol us = this; try { - Thread runner = Executors.defaultThreadFactory().newThread(new Runnable() - { - @Override - public void run() - { - try - { - exporter.doExport(file, us, width, height, view, renderer, - userBis); - } catch (Throwable t) - { - exceptions[0] = t; - } - } - }); + Thread runner = Executors.defaultThreadFactory() + .newThread(new Runnable() + { + @Override + public void run() + { + try + { + exporter.doExport(file, us, width, height, view, + renderer, userBis); + } catch (Throwable t) + { + exceptions[0] = t; + } + } + }); runner.start(); - do { Thread.sleep(25); } while (runner.isAlive()); + do + { + Thread.sleep(25); + } while (runner.isAlive()); } catch (Throwable e) { throw new ImageOutputException( @@ -532,7 +534,8 @@ public class AppJmol extends StructureViewerBase .openURL("http://wiki.jmol.org");// http://jmol.sourceforge.net/docs/JmolUserGuide/"); } catch (Exception ex) { - jalview.bin.Console.errPrintln("Show Jmol help failed with: " + ex.getMessage()); + jalview.bin.Console + .errPrintln("Show Jmol help failed with: " + ex.getMessage()); } } diff --git a/src/jalview/gui/ImageExporter.java b/src/jalview/gui/ImageExporter.java index 8d28b1b..457ea1f 100644 --- a/src/jalview/gui/ImageExporter.java +++ b/src/jalview/gui/ImageExporter.java @@ -108,7 +108,7 @@ public class ImageExporter String imageSource) throws ImageOutputException { doExport(file, parent, width, height, imageSource, null, - BitmapImageSizing.nullBitmapImageSizing()); + BitmapImageSizing.defaultBitmapImageSizing()); } public void doExport(File file, Component parent, int width, int height, diff --git a/src/jalview/util/ImageMaker.java b/src/jalview/util/ImageMaker.java index 3306b0d..fa473f3 100755 --- a/src/jalview/util/ImageMaker.java +++ b/src/jalview/util/ImageMaker.java @@ -189,9 +189,9 @@ public class ImageMaker BitmapImageSizing bis = ImageMaker.getScaleWidthHeight(width, height, userBis); - float usescale = bis.scale; - int usewidth = bis.width; - int useheight = bis.height; + float usescale = bis.scale(); + int usewidth = bis.width(); + int useheight = bis.height(); bi = new BufferedImage(usewidth, useheight, BufferedImage.TYPE_INT_RGB); graphics = bi.getGraphics(); @@ -247,14 +247,22 @@ public class ImageMaker } /** - * Takes suggested float scale, int width, int height and create a bounding - * box returned as a BitmapImageSizing object with consistent scale, width, - * height fields. + * Takes initial width and height, and suggested float scale, int width, int + * height and create a bounding box returned as a BitmapImageSizing object + * with consistent scale, width, height fields. * + * @param width + * The unscaled image width + * @param height + * The unscaled image height * @param scale + * The suggested scaling * @param bitmapwidth + * The suggested width * @param bitmapheight - * @return BitmapImageSizing + * The suggested height + * @return BitmapImageSizing A consistent scale,width and height for the final + * image */ public static BitmapImageSizing getScaleWidthHeight(int width, int height, float scale, int bitmapwidth, int bitmapheight) @@ -263,6 +271,13 @@ public class ImageMaker int usewidth = width; int useheight = height; + if ((width == 0 && bitmapwidth > 0) + || (height == 0 && bitmapheight > 0)) + { + // original image is zero sized! Avoid dividing by zero! + return BitmapImageSizing.nullBitmapImageSizing(); + } + // use the smallest positive scale (i.e. fit in the box) if (scale > 0.0f) { @@ -290,7 +305,7 @@ public class ImageMaker useheight = bitmapheight; } } - return new BitmapImageSizing(usescale, usewidth, useheight); + return new BitmapImageSizing(usescale, usewidth, useheight, false); } /** @@ -304,8 +319,8 @@ public class ImageMaker public static BitmapImageSizing getScaleWidthHeight(int width, int height, BitmapImageSizing bis) { - return ImageMaker.getScaleWidthHeight(width, height, bis.scale, - bis.width, bis.height); + return ImageMaker.getScaleWidthHeight(width, height, bis.scale(), + bis.width(), bis.height()); } /** @@ -321,6 +336,13 @@ public class ImageMaker public static BitmapImageSizing parseScaleWidthHeightStrings( String scaleS, String widthS, String heightS) { + if (scaleS == null && widthS == null && heightS == null) + { + // if all items are null (i.e. not provided) we use the dynamic + // preferences set BIS + return BitmapImageSizing.defaultBitmapImageSizing(); + } + float scale = 0.0f; int width = 0; int height = 0; @@ -359,6 +381,6 @@ public class ImageMaker } } - return new BitmapImageSizing(scale, width, height); + return new BitmapImageSizing(scale, width, height, false); } } diff --git a/src/jalview/util/imagemaker/BitmapImageSizing.java b/src/jalview/util/imagemaker/BitmapImageSizing.java index 8bd8ec3..e170f0e 100644 --- a/src/jalview/util/imagemaker/BitmapImageSizing.java +++ b/src/jalview/util/imagemaker/BitmapImageSizing.java @@ -4,17 +4,21 @@ import jalview.bin.Cache; public class BitmapImageSizing { - public final float scale; + private final float scale; - public final int width; + private final int width; - public final int height; + private final int height; - public BitmapImageSizing(float scale, int width, int height) + private boolean isDefault = false; + + public BitmapImageSizing(float scale, int width, int height, + boolean isDefault) { this.scale = scale; this.width = width; this.height = height; + this.isDefault = isDefault; } public boolean isNull() @@ -24,7 +28,7 @@ public class BitmapImageSizing public static BitmapImageSizing nullBitmapImageSizing() { - return new BitmapImageSizing(0.0f, 0, 0); + return new BitmapImageSizing(0.0f, 0, 0, false); } public static final String BITMAP_SCALE = "BITMAP_SCALE"; @@ -39,10 +43,41 @@ public class BitmapImageSizing */ public static BitmapImageSizing defaultBitmapImageSizing() { + return new BitmapImageSizing(0f, 0, 0, true); + } + + private float defaultScale() + { + return Cache.getDefault(BITMAP_SCALE, 0f); + } + + private int defaultWidth() + { + return Cache.getDefault(BITMAP_WIDTH, 0); + } + + private int defaultHeight() + { + return Cache.getDefault(BITMAP_HEIGHT, 0); + } + + public float scale() + { + return isDefault() ? defaultScale() : scale; + } + + public int width() + { + return isDefault() ? defaultWidth() : width; + } - return new BitmapImageSizing(Cache.getDefault(BITMAP_SCALE, 0) / 10f, - Cache.getDefault(BITMAP_WIDTH, 0), - Cache.getDefault(BITMAP_HEIGHT, 0)); + public int height() + { + return isDefault() ? defaultHeight() : height; + } + public boolean isDefault() + { + return isDefault; } } diff --git a/test/jalview/util/imagemaker/BitmapImageSizeTest.java b/test/jalview/util/imagemaker/BitmapImageSizeTest.java index 49e1084..016c91f 100644 --- a/test/jalview/util/imagemaker/BitmapImageSizeTest.java +++ b/test/jalview/util/imagemaker/BitmapImageSizeTest.java @@ -6,38 +6,41 @@ import org.testng.annotations.Test; import jalview.bin.Cache; -public class BitmapImageSizeTest { - @Test(groups = {"Functional"}) - public void testCacheSettingsRecovery() { +public class BitmapImageSizeTest +{ + @Test(groups = { "Functional" }) + public void testCacheSettingsRecovery() + { Cache.setPropsAreReadOnly(true); Cache.loadProperties("test/jalview/bin/testProps.jvprops"); - + Cache.removeProperty(BitmapImageSizing.BITMAP_HEIGHT); Cache.removeProperty(BitmapImageSizing.BITMAP_SCALE); Cache.removeProperty(BitmapImageSizing.BITMAP_WIDTH); - + BitmapImageSizing def = BitmapImageSizing.defaultBitmapImageSizing(); BitmapImageSizing zero = BitmapImageSizing.nullBitmapImageSizing(); - assertEquals(def.height, zero.height); - assertEquals(def.width, zero.width); - assertEquals(def.scale, zero.scale); - - Cache.setProperty(BitmapImageSizing.BITMAP_HEIGHT,"120"); - Cache.setProperty(BitmapImageSizing.BITMAP_SCALE,"240"); - Cache.setProperty(BitmapImageSizing.BITMAP_WIDTH,"360"); - - def = BitmapImageSizing.defaultBitmapImageSizing(); - - assertEquals(def.height, 120); - assertEquals(def.width, 360); - assertEquals(def.scale, 24f); - + assertEquals(def.height(), zero.height()); + assertEquals(def.width(), zero.width()); + assertEquals(def.scale(), zero.scale()); + + Cache.setProperty(BitmapImageSizing.BITMAP_HEIGHT, "120"); + Cache.setProperty(BitmapImageSizing.BITMAP_SCALE, "24"); + Cache.setProperty(BitmapImageSizing.BITMAP_WIDTH, "360"); + + // default now updates dynamically + // def = BitmapImageSizing.defaultBitmapImageSizing(); + + assertEquals(def.height(), 120); + assertEquals(def.width(), 360); + assertEquals(def.scale(), 24f); + Cache.removeProperty(BitmapImageSizing.BITMAP_WIDTH); - - def = BitmapImageSizing.defaultBitmapImageSizing(); - assertEquals(def.height, 120); - assertEquals(def.width, zero.width); - assertEquals(def.scale, 24f); + + // def = BitmapImageSizing.defaultBitmapImageSizing(); + assertEquals(def.height(), 120); + assertEquals(def.width(), zero.width()); + assertEquals(def.scale(), 24f); } } -- 1.7.10.2