Java rotation of pixel array

余生长醉 提交于 2019-11-30 23:57:00

To avoid holes you can:

  1. compute the source coordinate from destination

    (just reverse the computation to your current state) it is the same as Douglas Zare answer

  2. use bilinear or better filtering

  3. use less then single pixel step

    usually 0.75 pixel is enough for covering the holes but you need to use floats instead of ints which sometimes is not possible (due to performance and or missing implementation or other reasons)

Distortion

if your image get distorted then you do not have aspect ratio correctly applied so x-pixel size is different then y-pixel size. You need to add scale to one axis so it matches the device/transforms applied. Here few hints:

  • Is the source image and destination image separate (not in place)? so Main.pixels and pixels are not the same thing... otherwise you are overwriting some pixels before their usage which could be another cause of distortion.

  • Just have realized you have cos,cos and sin,sin in rotation formula which is non standard and may be you got the angle delta wrongly signed somewhere so

Just to be sure here an example of the bullet #1. (reverse) with standard rotation formula (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
  }

You are pushing the pixels forward, and not every pixel is hit by the discretized rotation map. You can get rid of the gaps by calculating the source of each pixel instead.

Instead of

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

try

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

This will still have visual artifacts. You can improve on this by interpolating instead of rounding the coordinates of the source pixel p to integer values.


Edit: Your rotation formulas looked odd, but they appear ok after using trig identities like cos(r+pi/2) = -sin(r) and sin(r+pi/2)=cos(r). They should not be the cause of any stretching.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!