Java перекрашивает BufferedImage не работает с изображением большей высоты - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть программа, которая должна принимать значения RGB изображения, а затем умножать их на некоторые константы, а затем рисовать новое изображение на JPanel.Проблема заключается в том, что если мое изображение имеет определенную высоту, в частности более 187 пикселей, новое цветное изображение отличается от изображения с высотой менее 187 пикселей.

JPanel показывает это: пример.

Обратите внимание, как длиннее перекрашенное изображение отличается от более короткого.Я уверен, что цвета более короткого изображения правильные, и я понятия не имею, как оно испортилось.

public class RecolorImage extends JPanel {
public static int scale = 3;

public static BufferedImage walk, walkRecolored;
public static BufferedImage shortWalk, shortWalkRecolored;

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(200*scale, 400*scale);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new RecolorImage());

    walk = ImageLoader.loadImage("/playerWalk.png");
    walkRecolored = recolor(walk);  
    shortWalk = ImageLoader.loadImage("/playerWalkShort.png");
    shortWalkRecolored = recolor(shortWalk);

    frame.setVisible(true);
}

@Override
public void paint(Graphics graphics) {
    Graphics2D g = (Graphics2D) graphics;
    g.scale(scale, scale);  
    g.drawImage(walk, 10, 10, null);
    g.drawImage(walkRecolored, 40, 10, null);
    g.drawImage(shortWalk, 70, 10, null);
    g.drawImage(shortWalkRecolored, 100, 10, null);
}

Метод перекраски:

public static BufferedImage recolor(BufferedImage image) {
    BufferedImage outputImage = deepCopy(image);

    for (int y = 0; y < image.getHeight(); y++) {
        for (int x = 0; x < image.getWidth(); x++) {

            int rgb = image.getRGB(x, y);
            Color c = new Color(rgb);

            int r = c.getRed();
            int g = c.getGreen();
            int b = c.getBlue();

            r *= 0.791;
            g *= 0.590;
            b *= 0.513;

            int newRGB = (rgb & 0xff000000) | (r << 16) | (g << 8) | b;
            outputImage.setRGB(x, y, newRGB);
        }
    }

    return outputImage;
}

Как я загружаю изображенияи сделайте глубокие копии:

public static BufferedImage loadImage(String path) {
    try {
        return ImageIO.read(ImageLoader.class.getResource(path));
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

public static BufferedImage deepCopy(BufferedImage image) {
    ColorModel colorModel = image.getColorModel();
    boolean isAlphaPremultiplied = colorModel.isAlphaPremultiplied();
    WritableRaster raster = image.copyData(null);
    return new BufferedImage(colorModel, raster, isAlphaPremultiplied, null);
}

Мои оригинальные изображения: высокое изображение и короткое изображение .Спасибо за любую помощь!

1 Ответ

0 голосов
/ 27 февраля 2019

Исходные изображения имеют разные цветовые модели:

  • короткое изображение использует 4 байта на пиксель (RGB и альфа) * ​​1004 *
  • высокое изображение использует 1 байт на пиксель (индекс впалитра из 256 цветов)

Ваши повторно окрашенные изображения используют ту же цветовую модель, что и исходные изображения (благодаря методу deepCopy), поэтому в повторно окрашенном изображении для высокого изображения также используется тот же цветпалитра как исходное изображение, означающее, что оно не может содержать все нужные цвета.

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

public static BufferedImage recolor(BufferedImage image) {
    BufferedImage outputImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
    //... code as before
}
...