You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Kristopher Ives的Multiply合成效果时TYPE_INT类型不匹配问题

问题:Multiply合成效果抛出"Expected integer sample type"异常

我尝试使用Multiply合成效果类实现图片叠加,但运行时始终抛出Expected integer sample type异常,触发条件是(r.getSampleModel().getDataType() != DataBuffer.TYPE_INT)。我怀疑问题出在图片不是32位整数缓冲区,但不知道怎么解决,也不清楚SampleModel的含义和DataType=3代表什么。


MultiplyComposite类代码

import java.awt.*;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

public class MultiplyComposite implements Composite, CompositeContext {
    protected void checkRaster(Raster r) {
        if (r.getSampleModel().getDataType() != DataBuffer.TYPE_INT) {
            throw new IllegalStateException("Expected integer sample type");
        }
    }

    @Override
    public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
        checkRaster(src);
        checkRaster(dstIn);
        checkRaster(dstOut);

        int width = Math.min(src.getWidth(), dstIn.getWidth());
        int height = Math.min(src.getHeight(), dstIn.getHeight());
        int x, y;
        int[] srcPixels = new int[width];
        int[] dstPixels = new int[width];

        for (y=0; y < height; y++) {
            src.getDataElements(0, y, width, 1, srcPixels);
            dstIn.getDataElements(0, y, width, 1, dstPixels);

            for (x=0; x < width; x++) {
                dstPixels[x] = mixPixel(srcPixels[x], dstPixels[x]);
            }

            dstOut.setDataElements(0, y, width, 1, dstPixels);
        }
    }

    private static int mixPixel(int x, int y) {
        int xb = (x) & 0xFF;
        int yb = (y) & 0xFF;
        int b = (xb * yb) / 255;

        int xg = (x >> 8) & 0xFF;
        int yg = (y >> 8) & 0xFF;
        int g = (xg * yg) / 255;

        int xr = (x >> 16) & 0xFF;
        int yr = (y >> 16) & 0xFF;
        int r = (xr * yr) / 255;

        int xa = (x >> 24) & 0xFF;
        int ya = (y >> 24) & 0xFF;
        int a = Math.min(255, xa + ya);

        return (b) | (g << 8) | (r << 16) | (a << 24);
    }


    @Override
    public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) {
        return this;
    }

    @Override
    public void dispose() {

    }

    public static final MultiplyComposite Multiply = new MultiplyComposite();

}

图片混合代码

public static BufferedImage photosBlender(BufferedImage SS, BufferedImage Overlay) {
    try {
        BufferedImage base = SS;
        BufferedImage overlay = Overlay;

        Graphics2D g2d = base.createGraphics();
        g2d.setComposite(MultiplyComposite.Multiply);
        int x = (base.getWidth() - overlay.getWidth()) / 2;
        int y = (base.getHeight() - overlay.getHeight()) / 2;
        g2d.drawImage(overlay, x, y, null);
        g2d.dispose();

        File f = new File("resources/OutputImages/OutputBlended.png");
        ImageIO.write((RenderedImage) base, "png", f);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

获取Overlay图片代码

public static BufferedImage OverlayProcess(String args) {
    BufferedImage OverlayInput = null;
    JFrame OverlayFrame = null;
    try {
        OverlayInput = ImageIO.read(new File(args));
        ImageIcon screenShotIcon = new ImageIcon(OverlayInput);
        
        //To Display selected Overlay for Testing purposes
        
        /*OverlayFrame = new JFrame();
        OverlayFrame.setLayout(new FlowLayout());
        OverlayFrame.setSize(1500, 800);
        JLabel lbl = new JLabel();
        lbl.setIcon(screenShotIcon);
        OverlayFrame.add(lbl);
        OverlayFrame.setVisible(true);
        OverlayFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);*/

    } catch (IOException e) {

    }

    return OverlayInput;

}

截图灰度化代码

public class GreyscaleTheImage {

    public static BufferedImage main(String args) throws IOException {
        BufferedImage img = null;
        File f = null;

        //read image
        try {
            f = new File(args);
            img = ImageIO.read(f);
        } catch (IOException e) {
            System.out.println(e);
        }

        //get image width and height
        int width = img.getWidth();
        int height = img.getHeight();

        //convert to grayscale
        int x = 0;
        int y;
        for (y = 0; y < height; y++) {
            for (x = 0; x < width; x++) {
                int p = img.getRGB(x, y);

                int a = (p >> 24) & 0xff;
                int r = (p >> 16) & 0xff;
                int g = (p >> 8) & 0xff;
                int b = p & 0xff;

                //calculate average
                int avg = (r + g + b) / 3;

                //replace RGB value with avg
                p = (a << 24) | (avg << 16) | (avg << 8) | avg;

                img.setRGB(x, y, p);
            }
        }

        BufferedImage finalImage = null;
        try {
            finalImage = img;
        } catch (Exception e) {
            System.out.println(e);
        }

        //write image
        try {
            f = new File("resources/OutputImages/Output.png");
            ImageIO.write(img, "png", f);
        } catch (IOException e) {
            System.out.println(e);
        }


        return finalImage;
    }//main() ends here

}//class ends here

问题原因

DataBuffer.TYPE_INT对应32位整数格式(每个像素用一个int存储ARGB通道),而你加载/处理的图片可能是其他格式(比如8位灰度、24位RGB,或者DataBuffer.TYPE_BYTE,对应DataType=3),导致Raster的SampleModel数据类型不匹配。

解决方法

核心思路:确保所有参与合成的BufferedImage都转换为32位ARGB整数格式(BufferedImage.TYPE_INT_ARGB),这样Raster的SampleModel就会是DataBuffer.TYPE_INT。

1. 新增图片格式转换工具方法

public static BufferedImage convertToIntARGB(BufferedImage image) {
    if (image.getType() == BufferedImage.TYPE_INT_ARGB) {
        return image; // 已经是目标格式,直接返回
    }
    // 创建32位ARGB格式的新图片,复制原图片内容
    BufferedImage converted = new BufferedImage(
        image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB
    );
    Graphics2D g = converted.createGraphics();
    g.drawImage(image, 0, 0, null);
    g.dispose();
    return converted;
}

2. 修改图片混合代码,先转换格式

在photosBlender方法中,先对base和overlay做格式转换:

public static BufferedImage photosBlender(BufferedImage SS, BufferedImage Overlay) {
    try {
        // 先转换为32位ARGB格式,确保数据类型匹配
        BufferedImage base = convertToIntARGB(SS);
        BufferedImage overlay = convertToIntARGB(Overlay);

        Graphics2D g2d = base.createGraphics();
        g2d.setComposite(MultiplyComposite.Multiply);
        int x = (base.getWidth() - overlay.getWidth()) / 2;
        int y = (base.getHeight() - overlay.getHeight()) / 2;
        g2d.drawImage(overlay, x, y, null);
        g2d.dispose();

        File f = new File("resources/OutputImages/OutputBlended.png");
        ImageIO.write(base, "png", f);
        return base; // 改成返回处理后的图片,原代码返回null不合理
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

3. 灰度化代码优化(可选)

原灰度化代码直接修改原图片,如果原图片不是TYPE_INT_ARGB,也会导致格式问题,建议在灰度化前先转换格式:

public class GreyscaleTheImage {
    public static BufferedImage main(String args) throws IOException {
        BufferedImage img = null;
        File f = new File(args);
        img = ImageIO.read(f);

        // 先转换为32位ARGB格式
        img = convertToIntARGB(img);

        int width = img.getWidth();
        int height = img.getHeight();

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int p = img.getRGB(x, y);
                int a = (p >> 24) & 0xff;
                int r = (p >> 16) & 0xff;
                int g = (p >> 8) & 0xff;
                int b = p & 0xff;

                int avg = (r + g + b) / 3;
                p = (a << 24) | (avg << 16) | (avg << 8) | avg;
                img.setRGB(x, y, p);
            }
        }

        f = new File("resources/OutputImages/Output.png");
        ImageIO.write(img, "png", f);
        return img;
    }
}

补充说明

  • SampleModel是描述图片像素数据存储方式的类,包括每个像素的通道数、数据类型等。
  • DataBuffer.TYPE_BYTE(对应DataType=3)是用字节数组存储像素,每个通道占1字节;而DataBuffer.TYPE_INT是用int数组存储,每个像素(含ARGB)占1个int,这也是MultiplyComposite类要求的格式。

内容的提问来源于stack exchange,提问作者TheRatKing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 21:50:38