Somethng wrong with my scaling function?

Hi.

I’m not sure if this problem is due to misunderstanding of
the way SDL works or just a stupid error on my part. For
some reason, this vanilla “nearest neighbour” scaling function
I’ve written correctly scales in the X direction but not in
the Y direction (the image appears interlaced or totally
corrupted with fractional scaling values):

void
scale(SDL_Surface *dst, const SDL_Surface *src, double scale_x, double
scale_y)
{
unsigned int dst_w = dst->w;
unsigned int dst_h = dst->h;
unsigned int src_w = src->w;
unsigned int x;
unsigned int y;
unsigned int src_y;
unsigned int src_x;
unsigned int dst_y;
uint32 *dst_pix = dst->pixels;
uint32 *src_pix = src->pixels;

scale_x = 1 / scale_x;
scale_y = 1 / scale_y;

for (y = 0; y < dst_h; ++y) {
src_y = (y * src_w) * scale_y;
dst_y = y * dst_w;
for (x = 0; x < dst_w; ++x) {
src_x = x * scale_x;
dst_pix[dst_y + x] = src_pix[src_y + src_x];
}
}
}

I have made sure that dst is large enough to hold the scaled
pixels and that both surfaces are in 32 bit RGBA format.

Is there some glaring error here?

Any help appreciated.–

@mir_ctx_at_imap.cc


http://www.fastmail.fm - One of many happy users:
http://www.fastmail.fm/docs/quotes.html

Hey,

I think something is wrong with this line:
src_y = (y * src_w) * scale_y;
Here, you’re scaling the source y-coord, but you should be more careful. The part in parentheses is giving you an integer that represents the index of the beginning of a line. Then you scale this index by a double. That will end up giving you fractions of a line as the apparent beginning of the line. You would probably be best off by scaling the y-coordinate, rounding or flooring it, then finding the start of the line.
Try replacing that line similar to this:
src_y = int(y * scale_y) * src_w;

Good luck,
Jonny D> From: mir_ctx at imap.cc

To: sdl at lists.libsdl.org
Date: Fri, 14 Dec 2007 08:29:12 -0800
Subject: [SDL] Somethng wrong with my scaling function?

Hi.

I’m not sure if this problem is due to misunderstanding of
the way SDL works or just a stupid error on my part. For
some reason, this vanilla “nearest neighbour” scaling function
I’ve written correctly scales in the X direction but not in
the Y direction (the image appears interlaced or totally
corrupted with fractional scaling values):

void
scale(SDL_Surface *dst, const SDL_Surface *src, double scale_x, double
scale_y)
{
unsigned int dst_w = dst->w;
unsigned int dst_h = dst->h;
unsigned int src_w = src->w;
unsigned int x;
unsigned int y;
unsigned int src_y;
unsigned int src_x;
unsigned int dst_y;
uint32 *dst_pix = dst->pixels;
uint32 *src_pix = src->pixels;

scale_x = 1 / scale_x;
scale_y = 1 / scale_y;

for (y = 0; y < dst_h; ++y) {
src_y = (y * src_w) * scale_y;
dst_y = y * dst_w;
for (x = 0; x < dst_w; ++x) {
src_x = x * scale_x;
dst_pix[dst_y + x] = src_pix[src_y + src_x];
}
}
}

I have made sure that dst is large enough to hold the scaled
pixels and that both surfaces are in 32 bit RGBA format.

Is there some glaring error here?

Any help appreciated.

mir_ctx at imap.cc


http://www.fastmail.fm - One of many happy users:
http://www.fastmail.fm/docs/quotes.html


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


Don’t get caught with egg on your face. Play Chicktionary!
http://club.live.com/chicktionary.aspx?icid=chick_wlhmtextlink1_dec

On Fri, 14 Dec 2007 21:22:27 -0500, “Jonathan Dearborn”
said:

Hey,

I think something is wrong with this line:
src_y = (y * src_w) * scale_y;
Here, you’re scaling the source y-coord, but you should be more careful.
The part in parentheses is giving you an integer that represents the
index of the beginning of a line. Then you scale this index by a double.
That will end up giving you fractions of a line as the apparent
beginning of the line. You would probably be best off by scaling the
y-coordinate, rounding or flooring it, then finding the start of the
line.
Try replacing that line similar to this:
src_y = int(y * scale_y) * src_w;

Hello.

Yes, you’re most likely right. I gave up trying it this way and
ended up with the following code instead (which works flawlessly):

static inline void
scale(SDL_Surface *dst, const SDL_Surface *src, double scale_x, double
scale_y)
{
unsigned int dst_w = dst->w;
unsigned int dst_h = dst->h;
unsigned int src_w = src->w;
unsigned int x;
unsigned int y;
unsigned int sx;
unsigned int sy;
unsigned int s_off;
unsigned int d_off;
unsigned int dy_off;
unsigned int sy_off;
uint32 *dst_pix = dst->pixels;
uint32 *src_pix = src->pixels;

scale_x = 1 / scale_x;
scale_y = 1 / scale_y;

for (y = 0; y < dst_h; ++y) {
sy = FLOATCAST_DTL(floor(y * scale_y));
sy_off = sy * src_w;
dy_off = y * dst_w;
for (x = 0; x < dst_w; ++x) {
sx = FLOATCAST_DTL(floor(x * scale_x));
d_off = dy_off + x;
s_off = sy_off + sx;
dst_pix[d_off] = src_pix[s_off];
}
}
}

FLOATCAST_DTL() is a macro which evaluates to ‘lrintf()’ if the
host system has it, or a plain cast from double to long otherwise.

thanks for listening!–

@mir_ctx_at_imap.cc


http://www.fastmail.fm - One of many happy users:
http://www.fastmail.fm/docs/quotes.html