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

按alpha角度旋转2D图像数组的Java代码输出黑图,问题出在哪?

图像旋转代码全黑问题排查

你代码存在多个逻辑错误,其中直接导致全黑的是循环遍历范围错误,其余错误也会导致旋转结果不符合预期,具体问题如下:

  • 最直接原因:你没有遍历目标图像的全部像素。内层循环起始值设置为height - i - 1,导致大量目标像素没有被赋值,int数组默认初始化值为0,对应图像就是纯黑色。
  • 坐标变换没有做中心对齐。图像默认的坐标原点在左上角,旋转是绕图像中心进行的,你直接对左上角为原点的坐标做旋转变换,会导致绝大多数像素旋转后超出原图像范围,取不到有效值。
  • 目标图像尺寸设置错误。图像旋转后外接矩形的宽高会发生变化,计算公式为新宽度 = 原宽度 * |cosα| + 原高度 * |sinα|,新高度 = 原宽度 * |sinα| + 原高度 * |cosα|,你沿用原始图像的宽高会直接裁掉大部分旋转后的内容。
  • 坐标计算逻辑错误。你用img[i].length、img[j].length取值,二维图像每一行的宽度是固定的,直接用提前计算好的width即可,img[j].length当j超过原图像高度时会直接触发数组越界;同时你混淆了x/y坐标和宽高的对应关系,旋转变换的公式应用完全错误。
  • 没有做坐标有效性校验。计算得到的原图像坐标如果超出原图像范围,应该直接赋值为透明/黑色,你没有做校验直接下标取值,要么触发越界崩溃,要么取到错误值。

下面是修正后的参考实现(针对ARGB格式的二维int像素数组):

public static int[][] rotate(int[][] img, double alpha) {
    double rad = Math.toRadians(alpha);
    double sin = Math.abs(Math.sin(rad));
    double cos = Math.abs(Math.cos(rad));

    int originalHeight = img.length;
    int originalWidth = img[0].length;

    // 计算旋转后新图像的宽高
    int newWidth = (int) Math.floor(originalWidth * cos + originalHeight * sin);
    int newHeight = (int) Math.floor(originalWidth * sin + originalHeight * cos);

    int[][] rotated = new int[newHeight][newWidth];

    // 原图像和新图像的中心坐标
    double originalCenterX = originalWidth / 2.0;
    double originalCenterY = originalHeight / 2.0;
    double newCenterX = newWidth / 2.0;
    double newCenterY = newHeight / 2.0;

    // 遍历新图像所有像素,反向映射找原图像对应坐标
    for (int y = 0; y < newHeight; y++) {
        for (int x = 0; x < newWidth; x++) {
            // 把新图像坐标转换到以中心为原点的坐标系
            double offsetX = x - newCenterX;
            double offsetY = y - newCenterY;

            // 旋转变换,得到原图像的相对坐标
            double originalOffsetX = offsetX * cos + offsetY * sin;
            double originalOffsetY = -offsetX * sin + offsetY * cos;

            // 转换回原图像左上角为原点的坐标系
            int originalX = (int) Math.round(originalOffsetX + originalCenterX);
            int originalY = (int) Math.round(originalOffsetY + originalCenterY);

            // 校验坐标在原图像范围内才取值,否则保留默认黑色
            if (originalX >= 0 && originalX < originalWidth && originalY >=0 && originalY < originalHeight) {
                rotated[y][x] = img[originalY][originalX];
            }
        }
    }
    return rotated;
}

如果你传入的是RGB三通道的3D数组,只需要把参数和返回值改为int[][][],赋值的时候对应三个通道分别赋值即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 01:24:06