-
Bug
-
Resolution: Fixed
-
P3
-
6
Setting a scaled image as an icon for frame leads to wrong painting of icon that appears on ALT+TAB and of icon in the task bar. First one contains two vertical lines, second one vertical line in the center.
See you should use image with size different from 32x32 pixels.
Run test with image say 30x30 and press ALT+TAB. Also note vert. line in the icon from the task bar.
This seen only on Windows platform.
Pretty well noticeable on Windows2000. Less visible on WindowsXP.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.Iterator;
public class TestScale extends Frame{
// public static Frame frame;
private Button buttonSimple;
public static Image image; // = frame.getIconImage();
public static java.util.List<Image> images;
static String fileBase;
static String fileName;
public static void main (String s[]){
if (System.getProperty("test.src") == null){
fileBase = "";
} else {
fileBase = System.getProperty("test.src") + System.getProperty("file.separator");
}
fileName = "images"+System.getProperty("file.separator") + "cross.jpg";
Frame frame = new TestScale();
frame.setSize(500, 500);
frame.setVisible(true);
}
public void paint(Graphics g){
g.setColor(Color.black);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
Image image;
Image scaledImage;
try {
image = Toolkit.getDefaultToolkit().getImage(fileName);
// if ( != null){
System.out.println("setting to frame");
this.setIconImage(image);
// }
g.drawImage(image, 100, 100, null);
System.out.println("Loaded image.");
java.util.List imageList = new java.util.ArrayList();
imageList.add(image);
scaledImage = getScaledIconImage(imageList, 100, 100);
g.drawImage(scaledImage, 300, 300, null);
scaledImage = getScaledIconImage(imageList, 16, 16);
g.drawImage(scaledImage, 400, 400, null);
scaledImage = getScaledIconImage(imageList, 32, 32);
g.drawImage(scaledImage, 450, 400, null);
scaledImage = getScaledIconImage(imageList, 48, 48);
g.drawImage(scaledImage, 450, 450, null);
} catch (Exception e) {
e.printStackTrace();
}
}
public static BufferedImage getScaledIconImage(java.util.List<Image> imageList, int width, int height) {
if (width == 0 || height == 0) {
return null;
}
Image bestImage = null;
int bestWidth = 0;
int bestHeight = 0;
double bestSimilarity = 3; //Impossibly high value
double bestScaleFactor = 0;
for (Iterator<Image> i = imageList.iterator();i.hasNext();) {
Image im = i.next();
if (im == null) {
continue;
}
int iw;
int ih;
try {
iw = im.getWidth(null);
ih = im.getHeight(null);
} catch (Exception e){
continue;
}
if (iw > 0 && ih > 0) {
//Calc scale factor
double scaleFactor = Math.min((double)width / (double)iw,
(double)height / (double)ih);
//Calculate scaled image dimensions
//adjusting scale factor to nearest "good" value
int adjw = 0;
int adjh = 0;
double scaleMeasure = 1; //0 - best (no) scale, 1 - impossibly bad
if (scaleFactor >= 2) {
//Need to enlarge image more than twice
//Round down scale factor to multiply by integer value
scaleFactor = Math.floor(scaleFactor);
adjw = iw * (int)scaleFactor;
adjh = ih * (int)scaleFactor;
scaleMeasure = 1.0 - 0.5 / scaleFactor;
} else if (scaleFactor >= 1) {
//Don't scale
scaleFactor = 1.0;
adjw = iw;
adjh = ih;
scaleMeasure = 0;
} else if (scaleFactor >= 0.75) {
//Multiply by 3/4
scaleFactor = 0.75;
adjw = iw * 3 / 4;
adjh = ih * 3 / 4;
scaleMeasure = 0.3;
} else if (scaleFactor >= 0.6666) {
//Multiply by 2/3
scaleFactor = 0.6666;
adjw = iw * 2 / 3;
adjh = ih * 2 / 3;
scaleMeasure = 0.33;
} else {
//Multiply size by 1/scaleDivider
//where scaleDivider is minimum possible integer
//larger than 1/scaleFactor
double scaleDivider = Math.ceil(1.0 / scaleFactor);
scaleFactor = 1.0 / scaleDivider;
adjw = (int)Math.round((double)iw / scaleDivider);
adjh = (int)Math.round((double)ih / scaleDivider);
scaleMeasure = 1.0 - 1.0 / scaleDivider;
}
double similarity = ((double)width - (double)adjw) / (double)width +
((double)height - (double)adjh) / (double)height + //Large padding is bad
scaleMeasure; //Large rescale is bad
if (similarity < bestSimilarity) {
bestSimilarity = similarity;
bestScaleFactor = scaleFactor;
bestImage = im;
bestWidth = adjw;
bestHeight = adjh;
}
if (similarity == 0) break;
}
}
if (bestImage == null) {
//No images were found, possibly all are broken
return null;
}
BufferedImage bimage =
new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bimage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
try {
int x = (width - bestWidth) / 2;
int y = (height - bestHeight) / 2;
g.drawImage(bestImage, x, y, bestWidth, bestHeight, null);
} finally {
g.dispose();
}
return bimage;
}
}
See you should use image with size different from 32x32 pixels.
Run test with image say 30x30 and press ALT+TAB. Also note vert. line in the icon from the task bar.
This seen only on Windows platform.
Pretty well noticeable on Windows2000. Less visible on WindowsXP.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.Iterator;
public class TestScale extends Frame{
// public static Frame frame;
private Button buttonSimple;
public static Image image; // = frame.getIconImage();
public static java.util.List<Image> images;
static String fileBase;
static String fileName;
public static void main (String s[]){
if (System.getProperty("test.src") == null){
fileBase = "";
} else {
fileBase = System.getProperty("test.src") + System.getProperty("file.separator");
}
fileName = "images"+System.getProperty("file.separator") + "cross.jpg";
Frame frame = new TestScale();
frame.setSize(500, 500);
frame.setVisible(true);
}
public void paint(Graphics g){
g.setColor(Color.black);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
Image image;
Image scaledImage;
try {
image = Toolkit.getDefaultToolkit().getImage(fileName);
// if ( != null){
System.out.println("setting to frame");
this.setIconImage(image);
// }
g.drawImage(image, 100, 100, null);
System.out.println("Loaded image.");
java.util.List imageList = new java.util.ArrayList();
imageList.add(image);
scaledImage = getScaledIconImage(imageList, 100, 100);
g.drawImage(scaledImage, 300, 300, null);
scaledImage = getScaledIconImage(imageList, 16, 16);
g.drawImage(scaledImage, 400, 400, null);
scaledImage = getScaledIconImage(imageList, 32, 32);
g.drawImage(scaledImage, 450, 400, null);
scaledImage = getScaledIconImage(imageList, 48, 48);
g.drawImage(scaledImage, 450, 450, null);
} catch (Exception e) {
e.printStackTrace();
}
}
public static BufferedImage getScaledIconImage(java.util.List<Image> imageList, int width, int height) {
if (width == 0 || height == 0) {
return null;
}
Image bestImage = null;
int bestWidth = 0;
int bestHeight = 0;
double bestSimilarity = 3; //Impossibly high value
double bestScaleFactor = 0;
for (Iterator<Image> i = imageList.iterator();i.hasNext();) {
Image im = i.next();
if (im == null) {
continue;
}
int iw;
int ih;
try {
iw = im.getWidth(null);
ih = im.getHeight(null);
} catch (Exception e){
continue;
}
if (iw > 0 && ih > 0) {
//Calc scale factor
double scaleFactor = Math.min((double)width / (double)iw,
(double)height / (double)ih);
//Calculate scaled image dimensions
//adjusting scale factor to nearest "good" value
int adjw = 0;
int adjh = 0;
double scaleMeasure = 1; //0 - best (no) scale, 1 - impossibly bad
if (scaleFactor >= 2) {
//Need to enlarge image more than twice
//Round down scale factor to multiply by integer value
scaleFactor = Math.floor(scaleFactor);
adjw = iw * (int)scaleFactor;
adjh = ih * (int)scaleFactor;
scaleMeasure = 1.0 - 0.5 / scaleFactor;
} else if (scaleFactor >= 1) {
//Don't scale
scaleFactor = 1.0;
adjw = iw;
adjh = ih;
scaleMeasure = 0;
} else if (scaleFactor >= 0.75) {
//Multiply by 3/4
scaleFactor = 0.75;
adjw = iw * 3 / 4;
adjh = ih * 3 / 4;
scaleMeasure = 0.3;
} else if (scaleFactor >= 0.6666) {
//Multiply by 2/3
scaleFactor = 0.6666;
adjw = iw * 2 / 3;
adjh = ih * 2 / 3;
scaleMeasure = 0.33;
} else {
//Multiply size by 1/scaleDivider
//where scaleDivider is minimum possible integer
//larger than 1/scaleFactor
double scaleDivider = Math.ceil(1.0 / scaleFactor);
scaleFactor = 1.0 / scaleDivider;
adjw = (int)Math.round((double)iw / scaleDivider);
adjh = (int)Math.round((double)ih / scaleDivider);
scaleMeasure = 1.0 - 1.0 / scaleDivider;
}
double similarity = ((double)width - (double)adjw) / (double)width +
((double)height - (double)adjh) / (double)height + //Large padding is bad
scaleMeasure; //Large rescale is bad
if (similarity < bestSimilarity) {
bestSimilarity = similarity;
bestScaleFactor = scaleFactor;
bestImage = im;
bestWidth = adjw;
bestHeight = adjh;
}
if (similarity == 0) break;
}
}
if (bestImage == null) {
//No images were found, possibly all are broken
return null;
}
BufferedImage bimage =
new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bimage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
try {
int x = (width - bestWidth) / 2;
int y = (height - bestHeight) / 2;
g.drawImage(bestImage, x, y, bestWidth, bestHeight, null);
} finally {
g.dispose();
}
return bimage;
}
}
- relates to
-
JDK-6489946 Win32: JVM fastdebug build crashes when Frame uses custom icon.
- Closed
-
JDK-6339074 Improve icon support
- Resolved