Image scaling with scanlines effect

Started by
6 comments, last by e-u-l-o-g-y 18 years, 8 months ago
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.
Advertisement
Your going to have to explain your method in better detail, some code/pseudo code would help.
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

//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)];			}		}	}
http://www.8ung.at/basiror/theironcross.html
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.
my-eulogy - A blog about coding and gfxsdgi - Semi-Daily Game IdeaChunkyHacker - Viewer for Relic chunky formats (used in DOW)
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&#261;ca grafik&#281; (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..
my-eulogy - A blog about coding and gfxsdgi - Semi-Daily Game IdeaChunkyHacker - Viewer for Relic chunky formats (used in DOW)
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

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.
my-eulogy - A blog about coding and gfxsdgi - Semi-Daily Game IdeaChunkyHacker - Viewer for Relic chunky formats (used in DOW)

This topic is closed to new replies.

Advertisement