Image scaling with scanlines effect
Hi - I'm looking for some fast scaling algotythm. I'm writing a game, that normally runs in 320x240 (arcade style), but I want it to resize into 640x480 with scanlines effect (just like in the most of the emulators). The algorythm I wrote works perfectly fine, the thing is it runs 8fps (while when non-scaled it runs about 130fps) on Athlon 1.7Ghz.
if you are interested look at the graphics programming forum into my thread about image enlargement with bicubic interpolation
as for your problem which algorithem to you use?
if you have scanlines how many pixel do you put between scanlines?
did you use the nearest neightbour scaling algorithm? you only scale up by a factor of2 sp nearest neighbour should do the job here is a piece of code from my library i am currently working on
as for your problem which algorithem to you use?
if you have scanlines how many pixel do you put between scanlines?
did you use the nearest neightbour scaling algorithm? you only scale up by a factor of2 sp nearest neighbour should do the job here is a piece of code from my library i am currently working on
//sample image up( powers of 2) template<class U, class W> void sample_up_nearest(const U& x, W& y) { uint32 i; uint32 j; uint32 xcoord; float flFactor = 1/static_cast<float>(W::MAP_SIZE / U::MAP_SIZE); for(i=0;i<W::MAP_SIZE;i++) { xcoord = static_cast<uint32>(i*flFactor) for(j=0;j<W::MAP_SIZE;j++) { y.m_Map[j]=x.m_Map[xcoord][static_cast<uint32>(j*flFactor)]; } } }
How do you render the screen? SDL? GDI?
I haven't got my compiler here, but I have some pretty good resizing code at home. You can use a rewritten bresenham line algorithm to prevent all the casting from float to int.
I haven't got my compiler here, but I have some pretty good resizing code at home. You can use a rewritten bresenham line algorithm to prevent all the casting from float to int.
You could use stencil testing to block out every other line after scaling as been done. Just pre-load the stencil buffer with alternating white & black horizontal lines. And set up the stencil test to fail on black and pass on white
This is my graphics class, the scaling loop is in graphics::blitMap function.
#include "headers.h"graphics::graphics(void) { //funkcja inicjująca grafikę (konstruktor) SDL_Init(SDL_INIT_VIDEO); Uint32 SDL_FLAGS; const SDL_VideoInfo *video_Probe; // pobieram informacje na temat dostepnego trybu video video_Probe = SDL_GetVideoInfo(); cout << "sprawdzenie czy jest accel:..." << endl; if (video_Probe->hw_available) { // czy dostepna jest akceleracja sprzetowa ekranu SDL_FLAGS = SDL_HWSURFACE; cout << "HWACCEL AVAILABLE" << endl; } else { SDL_FLAGS = SDL_SWSURFACE; printf("Software mode only...\n"); } if (video_Probe->blit_hw) { // sprawdzenie czy zadziala sprzetowy blitter SDL_FLAGS |= SDL_HWACCEL; SDL_FLAGS |= SDL_DOUBLEBUF; } window = SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_BPP, SDL_FLAGS); screen = SDL_CreateRGBSurface(SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, window->format->Rmask, window->format->Gmask, window->format->Bmask, window->format->Amask); //screen = SDL_DisplayFormat(window); scalemask = (Uint32 *) malloc ((640 * 480) * sizeof(Uint32));; //ta tablica posluzyc ma do szybkiego przeskalowania //obrazu z 320x240 do 640x480 for(iy=0; iy < window->h; iy++){ for(ix=0; ix < window->w; ix++){ scalemask[ix + (iy * window->w)] = (ix/2 + ((iy/2)* (window->w/2))); } } SDL_WM_SetCaption(CAPTION, CAPTION); next_time = SDL_GetTicks(); //inicjalizacja tajmera :) frame =0;}void graphics::blitMap( void ){ //SDL_BlitSurface(screen, NULL, window, NULL); if (SDL_MUSTLOCK(window) != 0) SDL_LockSurface(window); //Ten kod skaluje obraz do 640x480 if (SDL_MUSTLOCK(screen) != 0) SDL_LockSurface(screen); for (iy=0; iy < ((window->w*window->h)) ; iy++){ ((Uint16*)window->pixels)[iy]=((Uint16*)screen->pixels)[scalemask[iy]]; } //SDL_UpdateRect(window, 0,0,0,0); if (SDL_MUSTLOCK(screen) != 0) SDL_UnlockSurface(screen); if (SDL_MUSTLOCK(window) != 0) SDL_UnlockSurface(window);};
Well.. the code shouldn't give such an inpact. What kind of computer do you run it on? When you run the unscaled version, do you still lock the buffers? When using hardware rendering, locking a buffer is extremely slow. Another thing is that using a lookup table usually is slower than simple calculations. I've just installed SDL to test out some code..
ok... here's a modified version that compiles to about 2-4 times faster then the other version (in msvs 2005). I've just changed some names when coding my test
pWindow = pointer to screen/window surface
PSurface = the image to scale
By commenting out the line:
pDest[WINDOW_WIDTH] = color;
You'll get a simple scanline effect. This is the simplest scanline effect you can get. A method that might be visually more pleasing is to darken the color (though this didn't seem necessary in my test), but this requires some bit fiddling. This isn't difficult, but you'll end up with some different versions if you want different screen formats.
pWindow = pointer to screen/window surface
PSurface = the image to scale
uint16* pDest = reinterpret_cast<uint16*>(pWindow->pixels);uint16* pSrc = reinterpret_cast<uint16*>(pSurface->pixels);for (int y = 0; y < WINDOW_HEIGHT; y += 2){ for (int x = 0; x < WINDOW_WIDTH; ++x) { int color = *pSrc; *pDest = color; pDest[WINDOW_WIDTH] = color; pSrc += (x & 1); ++pDest; } pDest += WINDOW_WIDTH;}
By commenting out the line:
pDest[WINDOW_WIDTH] = color;
You'll get a simple scanline effect. This is the simplest scanline effect you can get. A method that might be visually more pleasing is to darken the color (though this didn't seem necessary in my test), but this requires some bit fiddling. This isn't difficult, but you'll end up with some different versions if you want different screen formats.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement