Java 像素阵列旋转

Java rotation of pixel array

我试图在 java 中制作一个算法来旋转二维像素阵列(不限于 90 度),我遇到的唯一问题是:最终结果让我 dots/holes在图像中。


这是代码:

    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < height; y++)
        {
            int xp = (int) (nx + Math.cos(rotation) * (x - width / 2) + Math
                    .cos(rotation + Math.PI / 2) * (y - height / 2));
            int yp = (int) (ny + Math.sin(rotation) * (x - width / 2) + Math
                    .sin(rotation + Math.PI / 2) * (y - height / 2));
            int pixel = pixels[x + y * width];
            Main.pixels[xp + yp * Main.WIDTH] = pixel;
        }
    }

'Main.pixels' 是连接到 canvas 显示器的数组,这就是显示器上显示的内容。

'pixels' 和函数本身在精灵 class 中。精灵 class 在程序初始化时从 '.png' 图像中抓取像素。


我试过查看 'Rotation Matrix' 解决方案。但它们对我来说太复杂了。我注意到当图像接近 45 度时,图像会有些拉伸?出了什么问题?什么是正确的代码;将像素添加到更大比例的数组(例如 Main.pixels[])。

需要java!并且相对于上面的代码格式。我不是在寻找复杂的例子,只是因为我不明白(如上所述)。简单明了,正是我要找的。


我喜欢这个问题的答案。

  1. 你的公式是错误的,因为....
  2. 这样做,效果会是...
  3. 简化这个...
  4. 我推荐...

对不起,如果我问的太多了,但我已经在寻找与这个问题相关的答案,我可以理解和使用。但是总是要么给出 90 度的旋转,要么给出来自另一种编程语言的示例。

您正在推动像素向前,并不是每个像素都被离散化旋转贴图击中。您可以通过计算每个像素的来源来消除间隙。

而不是

for each pixel p in the source
    pixel q = rotate(p, theta)
    q.setColor(p.getColor())

尝试

for each pixel q in the image
    pixel p = rotate(q, -theta)
    q.setColor(p.getColor())

这仍然会有视觉瑕疵。您可以通过插值而不是将源像素 p 的坐标四舍五入为整数值来改进这一点。


编辑:您的旋转公式看起来很奇怪,但在使用像 cos(r+pi/2) = -sin(r) 和 sin(r+pi/2)=cos( r)。它们不应该是任何拉伸的原因。

要避免漏洞,您可以:

  1. 从目标计算源坐标

    (只需将计算反转为您当前的状态)它与 Douglas Zare 的答案相同

  2. 使用双线性或更好的过滤

  3. 使用更少的单像素步长

    通常 0.75 像素足以覆盖孔,但您需要使用 floats 而不是 ints,这有时是不可能的(由于性能和/或缺少实现或其他原因)

失真

如果您的图像变形,那么您没有正确应用纵横比,因此 x 像素大小与 y 像素大小不同。您需要向一个轴添加刻度,使其与应用的 device/transforms 相匹配。这里有一些提示:

  • 源图和目的图是否分离(不在位)?所以 Main.pixelspixels 不是一回事......否则你会在使用之前覆盖一些像素,这可能是造成失真的另一个原因。

  • 刚意识到你在旋转公式中有 cos,cossin,sin,这是非标准的,可能是你在某处错误地签署了角度增量所以

这里只是为了确定子弹的例子 #1。 (反向)使用标准旋转公式 (C++):

float c=Math.cos(-rotation);
float s=Math.sin(-rotation);
int x0=Main.width/2;
int y0=Main.height/2;
int x1=      width/2;
int y1=      height/2;
for (int a=0,y=0; y < Main.height; y++)
 for (int     x=0; x < Main.width; x++,a++)
  {
  // coordinate inside dst image rotation center biased
  int xp=x-x0;
  int yp=y-y0;
  // rotate inverse
  int xx=int(float(float(xp)*c-float(yp)*s));
  int yy=int(float(float(xp)*s+float(yp)*c));
  // coordinate inside src image
  xp=xx+x1;
  yp=yy+y1;
  if ((xp>=0)&&(xp<width)&&(yp>=0)&&(yp<height))
       Main.pixels[a]=pixels[xp + yp*width]; // copy pixel
  else Main.pixels[a]=0; // out of src range pixel is black
  }