Merge branch 'develop' into spike/JAL-4047/JAL-4048_columns_in_sequenceID
[jalview.git] / src / jalview / util / ImageMaker.java
index 0cd017f..3306b0d 100755 (executable)
@@ -20,8 +20,6 @@
  */
 package jalview.util;
 
-import jalview.io.JalviewFileChooser;
-
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.RenderingHints;
@@ -36,6 +34,10 @@ import org.jfree.graphics2d.svg.SVGGraphics2D;
 import org.jfree.graphics2d.svg.SVGHints;
 import org.jibble.epsgraphics.EpsGraphics2D;
 
+import jalview.bin.Console;
+import jalview.io.JalviewFileChooser;
+import jalview.util.imagemaker.BitmapImageSizing;
+
 public class ImageMaker
 {
   public static final String SVG_DESCRIPTION = "Scalable Vector Graphics";
@@ -110,10 +112,12 @@ public class ImageMaker
    * @param file
    * @param fileTitle
    * @param useLineart
+   * @param bitmapscale
    * @throws IOException
    */
   public ImageMaker(TYPE imageType, int width, int height, File file,
-          String fileTitle, boolean useLineart) throws IOException
+          String fileTitle, boolean useLineart, BitmapImageSizing userBis)
+          throws IOException
   {
     this.type = imageType;
 
@@ -127,7 +131,7 @@ public class ImageMaker
       setupEPS(width, height, fileTitle, useLineart);
       break;
     case PNG:
-      setupPNG(width, height);
+      setupPNG(width, height, userBis);
       break;
     default:
     }
@@ -176,14 +180,28 @@ public class ImageMaker
    * 
    * @param width
    * @param height
+   * @param scale
    */
-  protected void setupPNG(int width, int height)
+  protected void setupPNG(int width, int height, BitmapImageSizing userBis)
   {
-    bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+    if (width == 0 || height == 0)
+      return;
+
+    BitmapImageSizing bis = ImageMaker.getScaleWidthHeight(width, height,
+            userBis);
+    float usescale = bis.scale;
+    int usewidth = bis.width;
+    int useheight = bis.height;
+
+    bi = new BufferedImage(usewidth, useheight, BufferedImage.TYPE_INT_RGB);
     graphics = bi.getGraphics();
     Graphics2D ig2 = (Graphics2D) graphics;
     ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
             RenderingHints.VALUE_ANTIALIAS_ON);
+    if (usescale > 0.0f)
+    {
+      ig2.scale(usescale, usescale);
+    }
   }
 
   /**
@@ -227,4 +245,120 @@ public class ImageMaker
     pg.setAccurateTextMode(useLineart);
     graphics = pg;
   }
+
+  /**
+   * Takes suggested float scale, int width, int height and create a bounding
+   * box returned as a BitmapImageSizing object with consistent scale, width,
+   * height fields.
+   * 
+   * @param scale
+   * @param bitmapwidth
+   * @param bitmapheight
+   * @return BitmapImageSizing
+   */
+  public static BitmapImageSizing getScaleWidthHeight(int width, int height,
+          float scale, int bitmapwidth, int bitmapheight)
+  {
+    float usescale = 0.0f;
+    int usewidth = width;
+    int useheight = height;
+
+    // use the smallest positive scale (i.e. fit in the box)
+    if (scale > 0.0f)
+    {
+      usescale = scale;
+      usewidth = Math.round(scale * width);
+      useheight = Math.round(scale * height);
+    }
+    if (bitmapwidth > 0)
+    {
+      float wscale = (float) bitmapwidth / width;
+      if (wscale > 0.0f && (usescale == 0.0f || wscale < usescale))
+      {
+        usescale = wscale;
+        usewidth = bitmapwidth;
+        useheight = Math.round(usescale * height);
+      }
+    }
+    if (bitmapheight > 0)
+    {
+      float hscale = (float) bitmapheight / height;
+      if (hscale > 0.0f && (usescale == 0.0f || hscale < usescale))
+      {
+        usescale = hscale;
+        usewidth = Math.round(usescale * width);
+        useheight = bitmapheight;
+      }
+    }
+    return new BitmapImageSizing(usescale, usewidth, useheight);
+  }
+
+  /**
+   * Takes suggested scale, width, height as a BitmapImageSizing object and
+   * create a bounding box returned as a BitmapImageSizing object with
+   * consistent scale, width, height fields.
+   * 
+   * @param bis
+   * @return BitmapImageSizing
+   */
+  public static BitmapImageSizing getScaleWidthHeight(int width, int height,
+          BitmapImageSizing bis)
+  {
+    return ImageMaker.getScaleWidthHeight(width, height, bis.scale,
+            bis.width, bis.height);
+  }
+
+  /**
+   * Takes String versions of suggested float scale, int width, int height and
+   * create a bounding box returned as a BitmapImageSizing object with
+   * consistent scale, width, height fields.
+   * 
+   * @param scaleS
+   * @param widthS
+   * @param heightS
+   * @return BitmapImageSizing
+   */
+  public static BitmapImageSizing parseScaleWidthHeightStrings(
+          String scaleS, String widthS, String heightS)
+  {
+    float scale = 0.0f;
+    int width = 0;
+    int height = 0;
+
+    if (scaleS != null)
+    {
+      try
+      {
+        scale = Float.parseFloat(scaleS);
+      } catch (NumberFormatException e)
+      {
+        Console.warn("Did not understand scale '" + scaleS
+                + "', won't be used.");
+      }
+    }
+    if (widthS != null)
+    {
+      try
+      {
+        width = Integer.parseInt(widthS);
+      } catch (NumberFormatException e)
+      {
+        Console.warn("Did not understand width '" + widthS
+                + "', won't be used.");
+      }
+    }
+    if (heightS != null)
+    {
+      try
+      {
+        height = Integer.parseInt(heightS);
+      } catch (NumberFormatException e)
+      {
+        Console.warn("Did not understand height '" + heightS
+                + "', won't be used.");
+      }
+    }
+
+    return new BitmapImageSizing(scale, width, height);
+  }
 }