'Rotating an image by x angle in c
I am rotating the image by x(45 degres) angle, But I am getting some black spots in the rotated image.
How to avoid those black spots!!
The logic I have used as below
double sinx = sin((M_PI/4)*(180.0/M_PI)); //45 degrees
double cosx = cos((M_PI/4)*(180.0/M_PI));
xCenter = height/2; // Rotate image by its center.
yCenter = width/2;
for(x=0; x<height; x++) {
for(y=0; y<width; y++) {
xt = x-xCenter; yt=y-yCenter;
xRotate = (int) round( ((xt*cosx)-(yt*sinx)) + xCenter );
yRotate = (int) round( ((yt*cosx)+(xt*sinx)) + yCenter );
if( (x >= 0) && (x < height) && (y >= 0) && (y < width) ) {
rotatedImage[xRotate][yRotate] = inputImage[x][y];
}
}
}
Solution 1:[1]
Rather than looping over the un-rotated image's pixels, loop over the rotated image instead. This will mean you won't miss pixels due to rounding the rotated coordinates to int
.
Solution 2:[2]
sin((M_PI/4)*(180.0/M_PI));
is not the the sine of "45 degrees". It is the sine of 45 radians. Same about double cosx
Suggest double sinx = sin(45.0/180.0*M_PI);
Also consider lround()
vs. (int) round()
.
Further, the range of xRotate, yRotate
is about sqrt(2) time more than the range of height, width
. Code should watch out for integer overflow when converting from double
.
Iterate as answered by @Chris Turner and commented by @M Oehm
Below uses OP-like code but with a -45 rotation as code is mapping from inputImage
.
#defined SIND(a) (sin((a)/180.0 * M_PI)
#defined COSD(a) (cos((a)/180.0 * M_PI)
double sinx = SIND(-45); // -degrees
double cosx = COSD(-45);
xCenter = height; // Rotate image by its center.
yCenter = width;
for(x=0; x<height; x++) {
xt = x - xCenter;
double xt_cosx = xt*cosx;
double xt_sinx = xt*sinx;
for(y=0; y<width; y++) {
yt = y - yCenter;
long xRotate = lround(xt_cosx - (yt*sinx)) + xCenter;
long yRotate = lround((yt*cosx) + xt_sinx) + yCenter;
if( (xRotate >= 0) && (xRotate < height) && (yRotate >= 0) && (yRotate < width) ) {
rotatedImage[x][y] = inputImage[xRotate][yRotate];
} else {
rotatedImage[x][y] = Default_Pixel;
}
}
}
Solution 3:[3]
I recommend that looping over the rotated image with the inverse transform matrix of rotation according to meet the EMPATHY of coordinate transformation.
This is sample code for your reference.
void rotate(uint8_t* dst, uint8_t* src, int w, int h, int depth, int theta) {
if (depth != 8) {
printf("Only support 8bits image !\n");
return;
}
memset(dst, 0, sizeof(uint8_t)*w*h);
float phi = theta/180.0*PI;
float T_inv[2][2] = { cos(phi), sin(phi),
-sin(phi), cos(phi)};
int i_;
int j_;
int center_i = round(w/2.0);
int center_j = round(h/2.0);
//v' = Tinv * v
for (int j=0; j<h; j++) {
for (int i=0; i<w; i++) {
i_ = round(T_inv[0][0]*(i-center_i) + T_inv[0][1]*(j-center_j)) + center_i;
j_ = round(T_inv[1][0]*(i-center_i) + T_inv[1][1]*(j-center_j)) + center_j;
if (i_ < 0 || j_ < 0)
continue;
if (i_ >= w)
continue;
if (j_ >= h)
continue;
dst[i+j*w] = src[i_+j_*w];
}
}
return;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Chris Turner |
Solution 2 | |
Solution 3 | Mou |