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

Java如何按指定像素数裁剪/创建非矩形形状图像?

Java中实现非矩形图像裁剪或指定像素区域提取的方法

嘿,我懂你现在的痛点——BufferedImage.getSubimage()确实只能处理矩形/正方形区域,要是想搞非矩形形状,或者精准提取指定的像素集合,得换个路子。下面给你两种实用的实现方案:

方案一:创建带透明通道的非矩形图像(最常用场景)

这种方法的核心是:先创建一个支持透明的BufferedImage(带Alpha通道),然后遍历原图像的像素,把你想要保留的区域(比如圆形、多边形)的像素复制过去,不需要的区域设为完全透明。

举个创建圆形裁剪图像的代码例子:

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

public class CustomImageCrop {
    public static void main(String[] args) throws IOException {
        // 读取原图像
        BufferedImage originalImg = ImageIO.read(new File("input.png"));
        int width = originalImg.getWidth();
        int height = originalImg.getHeight();
        
        // 创建带Alpha通道的目标图像(TYPE_INT_ARGB支持透明)
        BufferedImage croppedImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        
        // 定义圆形的参数:中心坐标和半径
        int centerX = width / 2;
        int centerY = height / 2;
        int radius = Math.min(width, height) / 2;
        
        // 遍历每个像素
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                // 判断当前像素是否在圆形内
                double distanceSq = Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2);
                if (distanceSq <= Math.pow(radius, 2)) {
                    // 保留原像素
                    croppedImg.setRGB(x, y, originalImg.getRGB(x, y));
                } else {
                    // 设置为完全透明(Alpha通道为0)
                    croppedImg.setRGB(x, y, 0x00000000);
                }
            }
        }
        
        // 保存图像(必须用PNG,JPG不支持透明)
        ImageIO.write(croppedImg, "PNG", new File("circular_crop.png"));
    }
}

你可以把圆形的判断逻辑换成任何你需要的形状——比如多边形的话,就用java.awt.Polygon的contains(x,y)方法来判断像素是否在区域内。

方案二:提取指定像素集合的自定义图像

如果你的需求是精准提取特定坐标的像素(比如不是规则形状,就是零散的像素点),可以先收集这些像素的坐标,然后创建一个刚好能容纳它们的图像,再逐个复制像素:

import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.ArrayList;
import javax.imageio.ImageIO;

public class SpecificPixelExtract {
    public static void main(String[] args) throws IOException {
        BufferedImage originalImg = ImageIO.read(new File("input.png"));
        
        // 假设你已经收集了需要提取的像素坐标(x,y)
        List<int[]> targetPixels = new ArrayList<>();
        targetPixels.add(new int[]{10, 10});
        targetPixels.add(new int[]{15, 20});
        targetPixels.add(new int[]{30, 5});
        // 可以继续添加更多坐标...
        
        // 计算目标图像的最小宽高(可选,也可以直接用原图像大小)
        int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE;
        int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE;
        for (int[] pixel : targetPixels) {
            minX = Math.min(minX, pixel[0]);
            maxX = Math.max(maxX, pixel[0]);
            minY = Math.min(minY, pixel[1]);
            maxY = Math.max(maxY, pixel[1]);
        }
        int targetWidth = maxX - minX + 1;
        int targetHeight = maxY - minY + 1;
        
        // 创建带透明通道的目标图像
        BufferedImage extractedImg = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_ARGB);
        
        // 复制指定像素到目标图像
        for (int[] pixel : targetPixels) {
            int x = pixel[0] - minX;
            int y = pixel[1] - minY;
            extractedImg.setRGB(x, y, originalImg.getRGB(pixel[0], pixel[1]));
        }
        
        // 保存图像
        ImageIO.write(extractedImg, "PNG", new File("specific_pixels.png"));
    }
}

一些额外的小提示

  • 处理大图像时,直接遍历像素可能有点慢,你可以考虑用Raster或者BufferedImageOp相关的类来优化性能
  • 保存非矩形图像时,一定要选择支持透明的格式(比如PNG),JPG格式会把透明区域变成黑色,达不到预期效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:37:03