From eb778a7237e020b2dd26938ff72300c94fdb48a6 Mon Sep 17 00:00:00 2001 From: Olivia Wen-Mei Lang Date: Tue, 29 Jun 2021 08:44:09 -0400 Subject: [PATCH 1/4] Add transparent colors3 color heatmap This relates to issue #66 where we are adding colors to enable the creation of a trace heatmap. The addition of this capability is fairly straightforward: -set the base image to fully transparent (white) -calculate an alpha gradient value for each square in the same way the red, green, and blue gradients are calculated -use this calculated alpha value to set the pixel-wise color -there are two places this is computed in three color heatmap so this will need to be updated in two places. --- src/scripts/Figure_Generation/ThreeColorHeatMap.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/scripts/Figure_Generation/ThreeColorHeatMap.java b/src/scripts/Figure_Generation/ThreeColorHeatMap.java index 59a85241c..179506e16 100644 --- a/src/scripts/Figure_Generation/ThreeColorHeatMap.java +++ b/src/scripts/Figure_Generation/ThreeColorHeatMap.java @@ -175,7 +175,7 @@ public static BufferedImage generateHeatMap(ArrayList matrix) throws F BufferedImage im = new BufferedImage(pixwidth, pixheight, BufferedImage.TYPE_INT_ARGB); Graphics g = im.getGraphics(); Graphics2D g2 = (Graphics2D) g; - g2.setColor(new Color(255, 255, 255)); + g2.setColor(new Color(255, 255, 255, 0)); g2.fillRect(0, 0, pixwidth, pixheight); int count = 0; @@ -196,7 +196,8 @@ public static BufferedImage generateHeatMap(ArrayList matrix) throws F int red = (int) (MAXCOLOR.getRed() * sVal + MIDCOLOR.getRed() * (1 - sVal)); int green = (int) (MAXCOLOR.getGreen() * sVal + MIDCOLOR.getGreen() * (1 - sVal)); int blue = (int) (MAXCOLOR.getBlue() * sVal + MIDCOLOR.getBlue() * (1 - sVal)); - g.setColor(new Color(red, green, blue)); + int alpha = (int) (MAXCOLOR.getAlpha() * sVal + MIDCOLOR.getAlpha() * (1 - sVal)); + g.setColor(new Color(red, green, blue, alpha)); } else if (IDj < MIDVAL) { double v = (MIDVAL - IDj) / LOWER_RATIO; double sVal = v > 1 ? 1 : v; @@ -206,7 +207,8 @@ public static BufferedImage generateHeatMap(ArrayList matrix) throws F int red = (int) (MINCOLOR.getRed() * sVal + MIDCOLOR.getRed() * (1 - sVal)); int green = (int) (MINCOLOR.getGreen() * sVal + MIDCOLOR.getGreen() * (1 - sVal)); int blue = (int) (MINCOLOR.getBlue() * sVal + MIDCOLOR.getBlue() * (1 - sVal)); - g.setColor(new Color(red, green, blue)); + int alpha = (int) (MINCOLOR.getAlpha() * sVal + MIDCOLOR.getAlpha() * (1 - sVal)); + g.setColor(new Color(red, green, blue, alpha)); } else { g.setColor(MIDCOLOR); } From 7727d94d1ed432062f38d531858e6430cfaefbc5 Mon Sep 17 00:00:00 2001 From: Olivia Wen-Mei Lang Date: Tue, 21 Dec 2021 10:24:14 -0500 Subject: [PATCH 2/4] Add transparent colors to 2ColorHM This adjustment to the TwoColorHeatMap script allows the heatmap graphics to use the alpha channel value for the color sent from the GUI and display custom levels of transparency to the heatmap colors. This is updated to mimic ThreeColorHeatMap changes (#66). --- src/scripts/Figure_Generation/TwoColorHeatMap.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scripts/Figure_Generation/TwoColorHeatMap.java b/src/scripts/Figure_Generation/TwoColorHeatMap.java index 923ad9326..d7cb6189d 100644 --- a/src/scripts/Figure_Generation/TwoColorHeatMap.java +++ b/src/scripts/Figure_Generation/TwoColorHeatMap.java @@ -120,7 +120,7 @@ public static BufferedImage generateHeatMap(ArrayList matrix) throws F BufferedImage im = new BufferedImage(pixwidth, pixheight, BufferedImage.TYPE_INT_ARGB); Graphics g = im.getGraphics(); Graphics2D g2 = (Graphics2D) g; - g2.setColor(new Color(255, 255, 255)); + g2.setColor(new Color(255, 255, 255, 0)); g2.fillRect(0, 0, pixwidth, pixheight); int count = 0; @@ -134,7 +134,8 @@ public static BufferedImage generateHeatMap(ArrayList matrix) throws F int red = (int) (MAXCOLOR.getRed() * sVal + MINCOLOR.getRed() * (1 - sVal)); int green = (int) (MAXCOLOR.getGreen() * sVal + MINCOLOR.getGreen() * (1 - sVal)); int blue = (int) (MAXCOLOR.getBlue() * sVal + MINCOLOR.getBlue() * (1 - sVal)); - g.setColor(new Color(red, green, blue)); + int alpha = (int) (MAXCOLOR.getAlpha() * sVal + MINCOLOR.getAlpha() * (1 - sVal)); + g.setColor(new Color(red, green, blue, alpha)); } else { g.setColor(Color.WHITE); } From 73ca966add57e118716f7142f1856ebe22eec75c Mon Sep 17 00:00:00 2001 From: Olivia Wen-Mei Lang Date: Tue, 21 Dec 2021 15:36:17 -0500 Subject: [PATCH 3/4] handle alpha colors in CLI heatmaps Both TwoColorHeatMap and ThreeColorHeatMap CLI should also handle alpha channel color values so that CLI mimics GUI functionality (#66). Both CLI contain lines that validate alpha value as numeric 0 to 255 and update the color's alpha channel. Their flags are related to the letter "t" for transparency. Also contains bug fix in ThreeColorHM such that more than one color can be specified in a single call (before there was a restriction imposed for one color being changed at a time). TwoColorHM was also adjusted to avoid redundancy. The check for custom color being selected occurred more than once so the hexcode decoding block was moved. --- .../ThreeColorHeatMapCLI.java | 27 +++++++++++++++++-- .../Figure_Generation/TwoColorHeatMapCLI.java | 23 +++++++++------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/cli/Figure_Generation/ThreeColorHeatMapCLI.java b/src/cli/Figure_Generation/ThreeColorHeatMapCLI.java index 40303a069..abf29e6a6 100644 --- a/src/cli/Figure_Generation/ThreeColorHeatMapCLI.java +++ b/src/cli/Figure_Generation/ThreeColorHeatMapCLI.java @@ -76,7 +76,7 @@ static class MaxGroup { @Option(names = {"-0", "--include-zeros"}, description = "used with `-p` flag, indicating exclusion of zero values when calculating percentile thresholds") private boolean includeZeros = false; - @ArgGroup(multiplicity = "0..1", heading = "%nSelect heatmap colors:%n") + @ArgGroup(multiplicity = "0..1", exclusive=false, heading = "%nSelect heatmap colors:%n") private ColorGroup color = new ColorGroup(); static class ColorGroup { @Option(names = {"-cn", "--color-min"}, description = "Color indicating minimum values (default=YELLOW) For custom color: type hexadecimal string to represent colors (e.g. \"FF0000\" is hexadecimal for red).\n See for some color options with their corresponding hex strings.\n") @@ -88,7 +88,20 @@ static class ColorGroup { @Option(names = {"-ca", "--color-nan"}, description = "Color indicating not-a-number values (default=GRAY) For custom color: type hexadecimal string to represent colors (e.g. \"FF0000\" is hexadecimal for red).\n See for some color options with their corresponding hex strings.\n") private String nan = null; } - + + @ArgGroup(multiplicity = "0..1", exclusive=false, heading = "%nSelect transparency of heatmap colors (alpha channel):%n") + private AlphaGroup alpha = new AlphaGroup(); + static class AlphaGroup { + @Option(names = {"-tn", "--transparent-min"}, description = "Value indicating transparency of minimum values, 0 to 255 (default=255)\n") + private int min = 255; + @Option(names = {"-td", "--transparent-mid"}, description = "Value indicating transparency of middle values, 0 to 255 (default=255)\n") + private int mid = 255; + @Option(names = {"-tx", "--transparent-max"}, description = "Value indicating transparency of maximum values, 0 to 255 (default=255)\n") + private int max = 255; + @Option(names = {"-ta", "--transparent-nan"}, description = "Value indicating transparency of not-a-number values, 0 to 255 (default=255)\n") + private int nan = 255; + } + String scaleType = "treeview"; //Colors from JavaTreeview microarray software Color CMAX = new Color(254,255,0,255); @@ -217,6 +230,16 @@ private String validateInput() throws IOException { System.err.println("Decoding NaN color: 0x" + color.nan); CNAN = Color.decode("0x" + color.nan); } + // check that Alpha channel/transparency values are formatted properly and decode/assign colors + if (alpha.max<0 || alpha.max>255) { r += "(!)Alpha/transparency value for higher values (max) must be a numeric 0 to 255\n"; } + else { CMAX = new Color(CMAX.getRed(), CMAX.getGreen(), CMAX.getBlue(), alpha.max); } + if (alpha.mid<0 || alpha.mid>255) { r += "(!)Alpha/transparency value for middling values (mid) must be a numeric 0 to 255\n"; } + else { CMID = new Color(CMID.getRed(), CMID.getGreen(), CMID.getBlue(), alpha.mid); } + if (alpha.min<0 || alpha.min>255) { r += "(!)Alpha/transparency value for lower values(min) must be a numeric 0 to 255\n"; } + else { CMIN = new Color(CMIN.getRed(), CMIN.getGreen(), CMIN.getBlue(), alpha.min); } + if (alpha.nan<0 || alpha.nan>255) { r += "(!)Alpha/transparency value for invalid/non-numeric values(NaN) must be a numeric 0 to 255\n"; } + else { CNAN = new Color(CNAN.getRed(), CNAN.getGreen(), CNAN.getBlue(), alpha.nan); } + // assign vals for contrast thresholds and set bools if(maxGroup.percentile!=null) { MAX = maxGroup.percentile; diff --git a/src/cli/Figure_Generation/TwoColorHeatMapCLI.java b/src/cli/Figure_Generation/TwoColorHeatMapCLI.java index 89088644c..6f8c85d1c 100644 --- a/src/cli/Figure_Generation/TwoColorHeatMapCLI.java +++ b/src/cli/Figure_Generation/TwoColorHeatMapCLI.java @@ -56,7 +56,6 @@ public class TwoColorHeatMapCLI implements Callable { @ArgGroup(exclusive = true, multiplicity = "0..1", heading = "%nSelect heatmap color:%n\t@|fg(red) (select no more than one of these options)|@%n") private ColorGroup color = new ColorGroup(); - static class ColorGroup { @Option(names = { "--black" }, description = "Use the color black for generating the heatmap (default)") private boolean black = false; @@ -68,6 +67,9 @@ static class ColorGroup { "--color" }, description = "For custom color: type hexadecimal string to represent colors (e.g. \"FF0000\" is hexadecimal for red).\n See for some color options with their corresponding hex strings.\n") private String custom = null; } + @Option(names = { "-t", + "--transparent" }, description = "Value indicating transparency of heatmap, 0 to 255 (default=255)\\n") + private int alpha = 255; String scaleType = "treeview"; Color MAXCOLOR = Color.BLACK; @@ -140,14 +142,7 @@ private String validateInput() throws IOException { if (compression < 1 || compression > 4) { r += "(!)Compression must be integer 1-4. Please select from the available compression types."; } - // check that hex string is formatted properly - if (color.custom != null) { - Pattern hexColorPat = Pattern.compile("[0-9A-Fa-f]{6}"); - Matcher m = hexColorPat.matcher(color.custom); - if (!m.matches()) { - r += "(!)Color must be formatted as a hexidecimal String!\n\tExpected input string format: \"[0-9A-Fa-f]{6}\""; - } - } + // check scaling is valid input if (absolute == -999 && percentile == -999) { absolute = 10; @@ -169,8 +164,16 @@ private String validateInput() throws IOException { MAXCOLOR = Color.BLUE; } else if (color.custom != null) { System.err.println("Decoding color: 0x" + color.custom); - MAXCOLOR = Color.decode("0x" + color.custom); + // check that hex string is formatted properly + Pattern hexColorPat = Pattern.compile("[0-9A-Fa-f]{6}"); + Matcher m = hexColorPat.matcher(color.custom); + if (!m.matches()) { + r += "(!)Color must be formatted as a hexidecimal String!\n\tExpected input string format: \"[0-9A-Fa-f]{6}\""; + } else { MAXCOLOR = Color.decode("0x" + color.custom); } } + // check that Alpha channel/transparency values are formatted properly and decode/assign colors + if (alpha<0 || alpha>255) { r += "(!)Alpha/transparency value for higher values (max) must be a numeric 0 to 255\n"; } + else { MAXCOLOR = new Color(MAXCOLOR.getRed(), MAXCOLOR.getGreen(), MAXCOLOR.getBlue(), alpha); } return (r); } From 5ea57adddae9dd469e9270427d5060d09afce540 Mon Sep 17 00:00:00 2001 From: owlang Date: Mon, 17 Oct 2022 00:32:05 -0400 Subject: [PATCH 4/4] add support for transparent background 2-color HM TwoColorHeatMapWindow -add checkbox for toggling background transparency TwoColorHeatMapOutput -pass along parameter flagging transparent background -remove leftover print statement (for output status flag) TwoColorHeatMap -add boolean parameter to toggle transparency of background by determining mincolor -minor fix to account for NaN values when determining quantiles TwoColorHeatMapCLI -add flag to support transparent background heatmaps -Remove extension requirements for Galaxy compatibility --- .../Figure_Generation/TwoColorHeatMapCLI.java | 23 +++++-------------- .../Figure_Generation/TwoColorHeatMap.java | 12 ++++++---- .../TwoColorHeatMapOutput.java | 8 +++---- .../TwoColorHeatMapWindow.java | 14 +++++++---- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/cli/Figure_Generation/TwoColorHeatMapCLI.java b/src/cli/Figure_Generation/TwoColorHeatMapCLI.java index 6f8c85d1c..5f756eb28 100644 --- a/src/cli/Figure_Generation/TwoColorHeatMapCLI.java +++ b/src/cli/Figure_Generation/TwoColorHeatMapCLI.java @@ -67,10 +67,13 @@ static class ColorGroup { "--color" }, description = "For custom color: type hexadecimal string to represent colors (e.g. \"FF0000\" is hexadecimal for red).\n See for some color options with their corresponding hex strings.\n") private String custom = null; } - @Option(names = { "-t", - "--transparent" }, description = "Value indicating transparency of heatmap, 0 to 255 (default=255)\\n") + @Option(names = { "-t", "--transparent" }, description = "Value indicating transparency of heatmap, 0 to 255 (default=255)\n") private int alpha = 255; + @Option(names = { "-b", "--background" }, description = "Set a transparent background for the heatmap minimum values (default=white)\n") + private boolean transparentBackground = false; + + String scaleType = "treeview"; Color MAXCOLOR = Color.BLACK; @@ -86,7 +89,7 @@ public Integer call() throws Exception { // Generate HeatMap TwoColorHeatMap script_object = new TwoColorHeatMap(CDT, MAXCOLOR, startROW, startCOL, pixelHeight, pixelWidth, - scaleType, absolute, percentile, output, true); + scaleType, absolute, percentile, output, true, transparentBackground); script_object.run(); System.err.println("Image Generated."); @@ -110,26 +113,12 @@ private String validateInput() throws IOException { r += "(!)CDT file does not exist: " + CDT.getName() + "\n"; return (r); } - // check input extensions - if (!"cdt".equals(ExtensionFileFilter.getExtension(CDT))) { - r += "(!)Is this a CDT file? Check extension: " + CDT.getName() + "\n"; - } // set default output filename if (output == null) { String NAME = ExtensionFileFilter.stripExtension(CDT); output = new File(NAME + "_" + scaleType + ".png"); // check output filename is valid } else { - // check ext - try { - if (!"png".equals(ExtensionFileFilter.getExtension(output))) { - r += "(!)Use PNG extension for output filename. Try: " + ExtensionFileFilter.stripExtension(output) - + ".png\n"; - } - } catch (NullPointerException e) { - r += "(!)Output filename must have extension: use PNG extension for output filename. Try: " + output - + ".png\n"; - } // check directory if (output.getParent() == null) { // System.err.println("default to current directory"); diff --git a/src/scripts/Figure_Generation/TwoColorHeatMap.java b/src/scripts/Figure_Generation/TwoColorHeatMap.java index d7cb6189d..9bb83687f 100644 --- a/src/scripts/Figure_Generation/TwoColorHeatMap.java +++ b/src/scripts/Figure_Generation/TwoColorHeatMap.java @@ -47,7 +47,7 @@ public class TwoColorHeatMap { private JLabel picLabel = null; public TwoColorHeatMap(File in, Color c, int startR, int startC, int pHeight, int pWidth, String scale, double abs, - double quant, File output, boolean outstatus) { + double quant, File output, boolean outstatus, boolean trans) { SAMPLE = in; MAXCOLOR = c; @@ -62,6 +62,10 @@ public TwoColorHeatMap(File in, Color c, int startR, int startC, int pHeight, in OUTFILE = output; OUTPUTSTATUS = outstatus; + MINCOLOR = new Color(255, 255, 255, 255); + if (trans) { + MINCOLOR = new Color(MAXCOLOR.getRed(), MAXCOLOR.getGreen(), MAXCOLOR.getBlue(), 0); + } } public void run() throws IOException { @@ -120,7 +124,7 @@ public static BufferedImage generateHeatMap(ArrayList matrix) throws F BufferedImage im = new BufferedImage(pixwidth, pixheight, BufferedImage.TYPE_INT_ARGB); Graphics g = im.getGraphics(); Graphics2D g2 = (Graphics2D) g; - g2.setColor(new Color(255, 255, 255, 0)); + g2.setColor(MINCOLOR); g2.fillRect(0, 0, pixwidth, pixheight); int count = 0; @@ -137,7 +141,7 @@ public static BufferedImage generateHeatMap(ArrayList matrix) throws F int alpha = (int) (MAXCOLOR.getAlpha() * sVal + MINCOLOR.getAlpha() * (1 - sVal)); g.setColor(new Color(red, green, blue, alpha)); } else { - g.setColor(Color.WHITE); + g.setColor(MINCOLOR); } g.fillRect(j * width, count * height, width, height); } @@ -353,7 +357,7 @@ public static double getQuantile(ArrayList matrix, double percent) { ArrayList nonZero = new ArrayList(); for (int x = 0; x < matrix.size(); x++) { for (int y = 0; y < matrix.get(x).length; y++) { - if (matrix.get(x)[y] != 0) { + if (matrix.get(x)[y] != 0 && !Double.isNaN(matrix.get(x)[y])) { nonZero.add(Double.valueOf(matrix.get(x)[y])); } } diff --git a/src/window_interface/Figure_Generation/TwoColorHeatMapOutput.java b/src/window_interface/Figure_Generation/TwoColorHeatMapOutput.java index 2275a212a..dd8cf320b 100644 --- a/src/window_interface/Figure_Generation/TwoColorHeatMapOutput.java +++ b/src/window_interface/Figure_Generation/TwoColorHeatMapOutput.java @@ -28,8 +28,8 @@ public class TwoColorHeatMapOutput extends JFrame { protected static double quantile = 0.9; protected static double absolute = -999; - public static Color MINCOLOR = new Color(255, 255, 255); public static Color MAXCOLOR = new Color(255, 0, 0); + public boolean transparentBackground = false; protected static boolean OUTPUTSTATUS = false; protected static File OUT_DIR = null; @@ -39,7 +39,7 @@ public class TwoColorHeatMapOutput extends JFrame { JTabbedPane newpane; public TwoColorHeatMapOutput(ArrayList in, Color c, int startR, int startC, int pHeight, int pWidth, - String scale, double abs, double quant, File out_dir, boolean outstatus) { + String scale, double abs, double quant, File out_dir, boolean outstatus, boolean trans) { setTitle("Heatmap"); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setBounds(150, 150, 600, 800); @@ -49,6 +49,7 @@ public TwoColorHeatMapOutput(ArrayList in, Color c, int startR, int startC SAMPLE = in; MAXCOLOR = c; + transparentBackground = trans; startROW = startR; startCOL = startC; pixelHeight = pHeight; @@ -60,7 +61,6 @@ public TwoColorHeatMapOutput(ArrayList in, Color c, int startR, int startC OUT_DIR = out_dir; OUTPUTSTATUS = outstatus; - System.out.println(OUTPUTSTATUS); } public void run() throws IOException { @@ -72,7 +72,7 @@ public void run() throws IOException { // Execute script TwoColorHeatMap script_object = new TwoColorHeatMap(SAMPLE.get(x), MAXCOLOR, startROW, startCOL, - pixelHeight, pixelWidth, scaleType, absolute, quantile, OUTPUT, OUTPUTSTATUS); + pixelHeight, pixelWidth, scaleType, absolute, quantile, OUTPUT, OUTPUTSTATUS, transparentBackground); script_object.run(); JLabel picLabel = script_object.getImg(); diff --git a/src/window_interface/Figure_Generation/TwoColorHeatMapWindow.java b/src/window_interface/Figure_Generation/TwoColorHeatMapWindow.java index 8ec5aeebe..b010f48da 100644 --- a/src/window_interface/Figure_Generation/TwoColorHeatMapWindow.java +++ b/src/window_interface/Figure_Generation/TwoColorHeatMapWindow.java @@ -60,6 +60,7 @@ public class TwoColorHeatMapWindow extends JFrame implements ActionListener, Pro private JTextField txtHeight; private JTextField txtWidth; private JButton btnColor; + private JCheckBox chckbxTransparentBackground; private JRadioButton rdbtnAbsoluteValue; private JRadioButton rdbtnPercentileValue; private JRadioButton rdbtnTreeview; @@ -125,7 +126,7 @@ public Void doInBackground() throws IOException { double quantile = Double.parseDouble(txtPercent.getText()); TwoColorHeatMapOutput heat = new TwoColorHeatMapOutput(txtFiles, COLOR, startR, startC, pHeight, pWidth, - scaletype, absolute, quantile, OUT_DIR, chckbxOutputHeatmap.isSelected()); + scaletype, absolute, quantile, OUT_DIR, chckbxOutputHeatmap.isSelected(), chckbxTransparentBackground.isSelected()); heat.addPropertyChangeListener("heat", new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent propertyChangeEvent) { @@ -333,9 +334,14 @@ public void itemStateChanged(ItemEvent e) { } }); + chckbxTransparentBackground = new JCheckBox("Use transparent background"); + sl_contentPane.putConstraint(SpringLayout.NORTH, chckbxTransparentBackground, 8, SpringLayout.SOUTH, lblSelectColor); + sl_contentPane.putConstraint(SpringLayout.WEST, chckbxTransparentBackground, 10, SpringLayout.WEST, lblSelectColor); + contentPane.add(chckbxTransparentBackground); + JLabel lblPixelHeight = new JLabel("Image Height:"); - sl_contentPane.putConstraint(SpringLayout.NORTH, lblPixelHeight, 20, SpringLayout.SOUTH, btnColor); - sl_contentPane.putConstraint(SpringLayout.WEST, lblPixelHeight, 0, SpringLayout.WEST, lblSelectColor); + sl_contentPane.putConstraint(SpringLayout.NORTH, lblPixelHeight, 8, SpringLayout.SOUTH, chckbxTransparentBackground); + sl_contentPane.putConstraint(SpringLayout.WEST, lblPixelHeight, 15, SpringLayout.WEST, contentPane); contentPane.add(lblPixelHeight); JLabel lblPixelWidth = new JLabel("Image Width:"); @@ -425,7 +431,7 @@ public void itemStateChanged(ItemEvent e) { }); JLabel lblImageCompression = new JLabel("Image Compression:"); - sl_contentPane.putConstraint(SpringLayout.NORTH, lblImageCompression, 10, SpringLayout.SOUTH, txtAbsolute); + sl_contentPane.putConstraint(SpringLayout.NORTH, lblImageCompression, 5, SpringLayout.SOUTH, txtAbsolute); sl_contentPane.putConstraint(SpringLayout.WEST, lblImageCompression, 10, SpringLayout.WEST, contentPane); contentPane.add(lblImageCompression);