#define SDL_MAIN_HANDLED #include #include #include #include #define SURF_W 640 #define SURF_H 640 void draw_img_line( SDL_Surface* surf, uint32_t* img_data, uint16_t img_w, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1 ) { int16_t dx = x1 - x0; int16_t dy = y1 - y0; uint16_t dist_x = abs(dx); uint16_t dist_y = abs(dy); int16_t step_x = dx < 0 ? -1 : 1; int16_t step_y = dy < 0 ? -surf->pitch / 4 : surf->pitch / 4; uint16_t dist = dist_y > dist_x ? dist_y : dist_x; uint32_t* addr = (uint32_t*)(surf->pixels + y0 * surf->pitch + x0 * 4); uint16_t err_x = 0; uint16_t err_y = 0; uint16_t err_img = 0; for (uint16_t i = 0; i < dist; i++) { *addr = *img_data; err_x += dist_x; err_y += dist_y; if (err_x >= dist) { err_x -= dist; addr += step_x; *addr = *img_data; } if (err_y >= dist) { err_y -= dist; addr += step_y; } err_img += img_w; while (err_img >= dist) { err_img -= dist; img_data++; } } } void draw_rotated_img( SDL_Surface* surf, SDL_Surface* img_surf, uint16_t x, uint16_t y, uint16_t w, uint16_t h, float rotation ) { int16_t cx = x + (w >> 1); int16_t cy = y + (h >> 1); int16_t x0 = x - cx; int16_t y0 = y - cy; int16_t x1 = x0 + w - 1; int16_t y1 = y0; int16_t x2 = x0; int16_t y2 = y0 + h - 1; float cos_val = cos(rotation); float sin_val = sin(rotation); int16_t rx0 = (int16_t) (cos_val * x0 + sin_val * y0); int16_t ry0 = (int16_t) (cos_val * y0 - sin_val * x0); int16_t rx1 = (int16_t) (cos_val * x1 + sin_val * y1); int16_t ry1 = (int16_t) (cos_val * y1 - sin_val * x1); int16_t rx2 = (int16_t) (cos_val * x2 + sin_val * y2); int16_t ry2 = (int16_t) (cos_val * y2 - sin_val * x2); int16_t dx = rx2 - rx0; int16_t dy = ry2 - ry0; int16_t step_x = dx < 0 ? -1 : 1; int16_t step_y = dy < 0 ? -1 : 1; uint16_t dist_x = abs(dx); uint16_t dist_y = abs(dy); uint16_t dist = dist_x > dist_y ? dist_x : dist_y; uint16_t err_x = 0; uint16_t err_y = 0; uint16_t err_img = 0; rx0 += cx; ry0 += cy; rx1 += cx; ry1 += cy; uint8_t* img_data = (uint8_t*) img_surf->pixels; for (uint16_t i = 0; i < dist; i++) { draw_img_line(surf, (uint32_t*)img_data, img_surf->w, rx0, ry0, rx1, ry1); err_img += h; while (err_img >= dist) { img_data += img_surf->pitch; err_img -= dist; } err_x += dist_x; err_y += dist_y; if (err_x >= dist) { err_x -= dist; rx0 += step_x; rx1 += step_x; } if (err_y >= dist) { err_y -= dist; ry0 += step_y; ry1 += step_y; } } } int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage: rotate image.bmp\n"); return 1; } SDL_Init(SDL_INIT_VIDEO); SDL_Window *window = SDL_CreateWindow( "Rotation", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SURF_W, SURF_H, SDL_WINDOW_ALLOW_HIGHDPI ); if (window == NULL) { printf("Could not create window: %s\n", SDL_GetError()); return 1; } SDL_Surface *bmpSurface = SDL_LoadBMP(argv[1]); if (!bmpSurface) { SDL_Quit(); printf("Error: %s\n", SDL_GetError()); return 1; } if (bmpSurface->w > 512 || bmpSurface->h > 512 || bmpSurface->w < 32 || bmpSurface->h < 32) { printf("Image dimensions must be 32..512 pixels\n"); SDL_FreeSurface(bmpSurface); SDL_Quit(); return 1; } SDL_Surface *screenSurface = SDL_GetWindowSurface(window); SDL_Surface *imgSurface = SDL_ConvertSurface(bmpSurface, screenSurface->format, 0); SDL_FreeSurface(bmpSurface); float rot = 0.0; SDL_Event event; uint16_t w = imgSurface->w; uint16_t h = imgSurface->h; int in_game = 1; while (in_game) { SDL_FillRect(screenSurface, NULL, 0); draw_rotated_img(screenSurface, imgSurface, (SURF_W - w) / 2, (SURF_H - h) / 2, w, h, rot); rot += M_PI / 180; if (rot > M_PI * 2) { rot -= M_PI * 2; } SDL_UpdateWindowSurface(window); while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { in_game = 0; break; } } SDL_Delay(10); } SDL_FreeSurface(imgSurface); SDL_FreeSurface(screenSurface); SDL_DestroyWindow(window); SDL_Quit(); return 0; }