Что вызывает плохое качество изображения в иконках Java JLabel? - PullRequest
8 голосов
/ 07 июня 2019

Java JLabel значки отображаются с искаженными пикселями в JFrame. Это происходит последовательно с различными изображениями PNG (все 32x32). Я не масштабирую изображения, они отображаются в программе 32x32, которую я проверил, используя getWidth и getHeight на JLabel. При каждом запуске программы искажения появляются в одном и том же месте, а не случайно.

Снимок экрана с использованием приведенного ниже примера кода.
example screenshot (1)

На этом скриншоте вы видите массив значков JLabel, каждый из которых влияет по-своему.
example screenshot (2)

При изменении размера окна сбоку, когда значок перемещается вместе с окном, искажения перемещаются по значку в виде вертикальной линии.

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

public class FrameApp extends JFrame
{
    public static void main(String[] args) throws IOException
    {
        FrameApp frameApp = new FrameApp();
    }

    private FrameApp() throws IOException
    {
        BufferedImage image;

        URL url = new URL("http://i.stack.imgur.com/L5DGx.png");
        image = ImageIO.read(url);

        JLabel label = new JLabel(new ImageIcon(image));

        add(label);

        pack();
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }
}

Edit:
Я использую JDK 11.0.3, Java SE Runtime Environment, сборка 1.8.0_202, в 64-битной Windows 8.1.

Ответы [ 3 ]

3 голосов
/ 14 июня 2019

Может показаться, что вы отображаете изображения размером 32x32, но ваш пример мозаичных изображений говорит, что это не так. У вас есть сетка иконок 9x2, которая должна быть 288x64 пикселей, но в вашем образце изображения сетка 302x66.

Если вы внимательно изучите свое мозаичное изображение, вы увидите, что отдельные плитки отображаются шириной 34 пикселя - см. Пурпурную границу, которая простирается от 32 до 66 пикселей. (Обратите внимание, что некоторые из плиток отображаются шириной 33px; кажется, что это 33, 34, 34, 33, 34 ...)

Чтобы растянуть плитки на более широкую ширину, некоторые столбцы удваиваются (красные границы), и это создает визуальные сбои, которые вы видите.

marked up portion of provided sample image

Вы пытались исправить размер JLabel вместо того, чтобы разрешить его размер в зависимости от его содержимого?

1 голос
/ 12 июня 2019

Первый вариант: Вместо использования ImageIcon вы можете попытаться создать свой собственный класс значков для рисования изображения с использованием graphics.drawImage (x, y, width, height, null), управляющего качеством рендеринга (https://docs.oracle.com/javase/tutorial/2d/advanced/quality.html)

пример будет выглядеть примерно так:

public class Icon32 extends ImageIcon {
    public Icon32(String f) {
      super(f);

      BufferedImage i= new BufferedImage(32, 32, 
           BufferedImage.TYPE_INT_RGB);


      Graphics2D g2d = (Graphics2D) i.getGraphics();
                g2d.setRenderingHint(
                    RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);

                g2d.setRenderingHint(
                    RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);

      g2d.drawImage(getImage(), 0, 0, 32, 32, null);
      setImage(i);
    }

    public int getIconHeight() {
      return 32;
    }

    public int getIconWidth() {
      return 32;
    }

    public void paintIcon(Component c, Graphics g, int x, int y) {
      g.drawImage(getImage(), x, y, c);
    }
  }

, где метод:

getImage()

загружает ваше изображение / иконку ...

Второй вариант : если вы недовольны результатом, вы можете попробовать использовать эту библиотеку: https://github.com/mortennobel/java-image-scaling заявляет, что она обеспечивает лучшие параметры масштабирования изображения, чем среда выполнения Java.

0 голосов
/ 11 июня 2019

Answer is from this link to generate high quality image: https://componenthouse.com/2008/02/08/high-quality-image-resize-with-java/

Соответствующий класс по ссылке :

public class ImageResize {

    public static void main(String[] args) {
        try {
            URL url = new URL("http://i.stack.imgur.com/L5DGx.png");
            BufferedImage image = ImageIO.read(url);
            ImageIO.write(resizeImage(image, 32, 32), "png", new File("D:/picture3.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static BufferedImage resize(BufferedImage image, int width, int height) {
        int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
        BufferedImage resizedImage = new BufferedImage(width, height, type);
        Graphics2D g = resizedImage.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.drawImage(image, 0, 0, width, height, null);
        g.dispose();
        return resizedImage;
    }

    private static BufferedImage resizeImage(BufferedImage image, int width, int height) {
        image = createCompatibleImage(image);
        image = resize(image, 100, 100);
        image = blurImage(image);
        return resize(image, width, height);
    }

    public static BufferedImage blurImage(BufferedImage image) {
        float ninth = 1.0f/9.0f;
        float[] blurKernel = {
                ninth, ninth, ninth,
                ninth, ninth, ninth,
                ninth, ninth, ninth
        };

        Map<RenderingHints.Key, Object> map = new HashMap<RenderingHints.Key, Object>();
        map.put(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        map.put(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
        map.put(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        RenderingHints hints = new RenderingHints(map);
        BufferedImageOp op = new ConvolveOp(new Kernel(3, 3, blurKernel), ConvolveOp.EDGE_NO_OP, hints);
        return op.filter(image, null);
    }

    private static BufferedImage createCompatibleImage(BufferedImage image) {
        GraphicsConfiguration gc = BufferedImageGraphicsConfig.getConfig(image);
        int w = image.getWidth();
        int h = image.getHeight();
        BufferedImage result = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
        Graphics2D g2 = result.createGraphics();
        g2.drawRenderedImage(image, null);
        g2.dispose();
        return result;
    }

}
...