Пользовательская функция поворота в C с SDL 1.2 не работает
Я должен сделать OCR для научных целей. Я не знаю, смогу ли я использовать встроенные функции вращения в SDL, поэтому я написал базовую функцию вращения. Кажется, что это работает, но у меня есть некоторые проблемы: он работает только с некоторым изображением, и когда он работает, новое изображение выглядит довольно грязно. Пример:
Изображение до поворота:
Изображение после поворота на 60 градусов:
Вот мой код:
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <math.h>
#include "image.h"
double deg_to_rad(int angle)
{
return (angle*0.017453292519943);
}
SDL_Surface *rotate(SDL_Surface *image, int angle)
{
/* Trigo */
double cosa = cos(deg_to_rad(angle));
double sina = sin(deg_to_rad(angle));
int wo = abs((image->w)*cosa + (image->h)*sina);
int ho = abs((image->h)*cosa + (image->w)*sina);
/* Création d'une nouvelle image */
SDL_Surface *new_img;
Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
new_img = SDL_CreateRGBSurface(0,wo,ho,32, rmask, gmask, bmask, amask);
int center_x = image->w / 2;
int center_y = image->h / 2;
int new_center_x = wo/2;
int new_center_y = ho/2;
for (int x = 0; x < wo; x++)
{
for (int y = 0; y < ho; y++)
{
int xo = abs(cosa*(x - new_center_x) + sina*(y - new_center_y) + center_x);
int yo = abs((-1)*sina*(x - new_center_x) + cosa*(y - new_center_y) + center_y);
lockSurface(image);
lockSurface(new_img);
Uint8 r,g,b;
Uint32 pixel;
Uint32 color;
if (xo >= 0 && yo >= 0 && xo < image->w && yo < image->h
&& x >= 0 && x < wo && y >=0 && y < ho)
{
pixel = getPixel(image, xo, yo);
SDL_GetRGB(pixel, image->format, &r, &g, &b);
color = SDL_MapRGB(image->format, r, g, b);
setPixel(new_img, x, y, color);
}
unlockSurface(image);
unlockSurface(new_img);
}
}
return new_img;
}
Что я делаю неправильно?
1 ответ
Если вы представляете изображение как "сетку" пикселей, будет понятно, почему ваша функция искажает его - вращение этой сетки не отображает пиксели в пиксели, а также путем взятия значения только одного ближайшего пикселя перед вращением и вставки его в пиксель после поворота вы буквально "режете углы". Вы захотите использовать алгоритм картирования областей или суперсэмплинга, чтобы избежать визуальных артефактов, которые вы видите - это означает, что нужно учитывать "форму" пикселя в первом случае и смешивать части "квадратов пикселей", если это имеет смысл?
Фотографии (и код!) В "Быстром алгоритме поворота общего растра" Алана У. Паэта стоят многих слов.