JAL-4274 Use Cache BITMAP_* if no other image restrictions given
authorBen Soares <b.soares@dundee.ac.uk>
Wed, 13 Sep 2023 16:28:11 +0000 (17:28 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Wed, 13 Sep 2023 16:28:11 +0000 (17:28 +0100)
src/jalview/bin/Cache.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AppJmol.java
src/jalview/gui/ImageExporter.java
src/jalview/util/ImageMaker.java
src/jalview/util/imagemaker/BitmapImageSizing.java
test/jalview/util/imagemaker/BitmapImageSizeTest.java

index 038a5a0..9266d2a 100755 (executable)
@@ -141,7 +141,8 @@ import jalview.ws.sifts.SiftsSettings;
  * <li>WRAP_ALIGNMENT</li>
  * <li>EPS_RENDERING (Prompt each time|Lineart|Text) default for EPS rendering
  * style check</li>
- * <li>BITMAP_SCALE - scale factor for PNG export - default 0 - native resolution</li>
+ * <li>BITMAP_SCALE - scale factor for PNG export - default 0.0 - native
+ * resolution</li>
  * <li>BITMAP_HEIGHT - height bound for PNG export or 0 for unbound</li>
  * <li>BITMAP_WIDTH - width bound for PNG export or 0 for unbound</li>
  * <li>SORT_ALIGNMENT (No sort|Id|Pairwise Identity)</li>
@@ -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<String> 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(
index ce87c01..7ed5227 100644 (file)
@@ -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());
   }
 
   /**
index 950f129..cfbac04 100644 (file)
@@ -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());
     }
   }
 
index 8d28b1b..457ea1f 100644 (file)
@@ -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,
index 3306b0d..fa473f3 100755 (executable)
@@ -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);
   }
 }
index 8bd8ec3..e170f0e 100644 (file)
@@ -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;
   }
 }
index 49e1084..016c91f 100644 (file)
@@ -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);
   }
 }