如何通过并行计算从BufferedImage获取int[]型RGB像素并解决错位问题
核心问题1:getRGB的写入偏移量参数设置错误
你调用image.getRGB时第6个offset参数固定传了0,该参数的作用是指定当前块的像素写入目标数组rgb的起始下标,你所有并行线程都从数组起始位置写入,导致不同块的像素互相覆盖,自然出现像素错位的问题。同时由于并行线程的执行顺序不固定,覆盖写入的结果每次都有差异,也对应了你观察到的每次运行输出图像不一致的现象。
对应BufferedImage.getRGB的参数定义:
public int[] getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
你要写入第chunk个64像素宽度的块,写入起始下标应该等于块的起始X坐标startX,因为扫描行宽度scansize设置为图像总宽度width,刚好匹配你按宽度分块的逻辑。
核心问题2:(可选注意项)BufferedImage的线程安全限制
Java官方未声明BufferedImage的线程安全性,如果你调用getRGBFast方法的过程中,存在其他线程修改输入的BufferedImage对象的操作,也会导致读取结果异常。如果仅做并行读取、无写入操作,该场景下不存在安全问题。
修正后的代码:
public static int[] getRGBFast(@NotNull final BufferedImage image) { final int width = image.getWidth(); final int height = image.getHeight(); final int[] rgb = new int[width * height]; final int chunkSize = 64; final int chunkCount = (width + chunkSize - 1) / chunkSize; // 简化分块数计算 IntStream.range(0, chunkCount) .parallel() .forEach(chunk -> { final int startX = chunk * chunkSize; final int currentChunkWidth = Math.min(chunkSize, width - startX); // 修复offset参数为startX,写入到数组对应位置 image.getRGB(startX, 0, currentChunkWidth, height, rgb, startX, width); }); return rgb; }
内容的提问来源于stack exchange,提问作者Brandon Li
相关产品推荐
相关产品推荐

