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

为什么这段Java代码绘制图像到自身时出现类循环的重复绘制效果?

问题原因分析

你遇到的现象本质是读写同一块图像内存导致的递归覆盖问题:你直接从原图自身读取像素,同时往原图的偏移位置写入像素,整个绘制过程是逐行实时写入的,并不会先缓存整张原图的原始像素再完成绘制。当绘制到Y坐标大于100的区域时,你读取的源像素已经是前一步刚写入到偏移位置的新像素,而非原始图像素,最终就会生成一层一层往右下角偏移的重复小图,也就是你观察到的隧道效应。

逻辑复现拆解
  • 初始化读取的img内存中存储的是原始测试图的全部像素
  • 执行g.drawImage(img,100,100,null)时,绘制逻辑默认从img的左上角(0,0)读像素,依次写入到img从(100,100)开始的对应位置
  • 当绘制到第101行目标像素时,此时读取的源位置第1行像素,已经是前一步刚写入的修改后像素,不再是原始图的第1行像素
  • 该逻辑持续循环,就会生成不断嵌套的重复小图效果
修复方案

如果要实现仅把原图绘制一次到自身的偏移位置,需要先对原始图像素做独立拷贝,用拷贝版本作为绘制源,避免读写同一块内存。修复后的代码如下:

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Swapper{
    public static void main(String[] args) throws IOException {
        try{
            BufferedImage originalImg = ImageIO.read(new File("picture2.jpg"));
            // 先创建原始图像的独立拷贝,作为绘制源
            BufferedImage sourceImg = new BufferedImage(originalImg.getWidth(), originalImg.getHeight(), originalImg.getType());
            Graphics sourceG = sourceImg.getGraphics();
            sourceG.drawImage(originalImg, 0, 0, null);
            sourceG.dispose();
            
            // 用独立的源图绘制到原图上,不会出现递归覆盖问题
            Graphics targetG = originalImg.getGraphics();
            targetG.drawImage(sourceImg, 100, 100, null);
            targetG.dispose();

            File file = new File("aaaimage3.png");
            ImageIO.write(originalImg,"png", file);
        } catch(IOException e){
            e.printStackTrace();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 08:54:00