Jump to content
  • Advertisement
Sign in to follow this  
kroopson

Image scaling with scanlines effect

This topic is 4844 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
Advertisement
Your going to have to explain your method in better detail, some code/pseudo code would help.

Share this post


Link to post
Share on other sites
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)];
}
}
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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);
};

Share this post


Link to post
Share on other sites
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..

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!