Java 重新着色 BufferedImage 不适用于更大高度的图像

Java recoloring BufferedImage not working with an image of a larger height

我有一个程序应该获取图像的 RGB 值,然后将它们乘以一些常数,然后在 JPanel 上绘制新图像。问题是如果我的图像超过一定高度,特别是超过 187 像素,新的彩色图像与高度小于 187px 的图像不同。

JPanel 显示如下:example。

注意较长的重新着色图像与较短的图像有何不同。我确信较短的图像的颜色是正确的,但我不知道它是怎么弄乱的。

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);
}

我的原始图像:tall image and short image。感谢您的帮助!

您的源图像有不同的颜色模型:

  • 短图每个像素使用 4 个字节(RGB 和 alpha)
  • 高图像每个像素使用 1 个字节(索引到 256 种颜色的调色板)

重新着色的图像使用与源图像相同的颜色模型(感谢 deepCopy 方法),因此高图像的重新着色图像也使用与源图像相同的调色板,这意味着它不能包含您想要的所有颜色。

由于您的重新着色代码无论如何都会覆盖输出图像的每个像素,因此不需要深度复制操作。相反,您最好像这样创建一个全彩色图像作为目标图像:

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