Mysterious vertical lines in SDL_Surface

Hi all,

I am working with SDL v1.2.9 and I’ve written a simple program to help me view detail in large images.
It takes in a jpeg, then makes several copies of it, each shrunk by a larger scale factor, such that the smallest fits the application window.

The user then moves the mouse over the smallest image, and an area around the mouse displays one of the larger images i.e. a zoomed in view.

The problem is this:
For a certain input image mysterious vertical lines of incorrect colour appear on one of the shrunken images.
The problem is consistent in that the lines always appear for this image and the same zoom level.
However it is inconsistent in that

  1. If the input image is changed by in width, the problem does not occur.
  2. If the scale factor is changed even slightly the problem does not occur.
  3. If I simply run the image shrinking code (for the same input image and scale factor) outside of this program, then the problem does not occur.

Other details:
The lines occur at 1/6, 1/3 and 2/3 of the image width.

I’ll not bother to post the code, since I have no idea where the problem is located.
I am hoping that this problem is familiar to someone or the location is clear from its character.

Any ideas?

Thanks,
rps

Please describe the shrink algorithm that you are using,
and how you are manipulating the surfaces. If the mysterious
lines appear for particular zoom values and for precise values
of X (k*0.3333), then it may reveal something fishy
in the way the algorithm is built or in the way you are doing the blits.

Maybe posting a screenshot would help see how strange are the colors.
Don’t send the whole code but the chunk of interest.

Julien CLEMENT

Hi Julian,

It seems that the particular image does not matter, just the dimensions, so here are those details.
The original size was 1536x1152.
The scale factor was 1.3 for both dimensions.
This gives a final image of 1182x886.
The lines appear at x = 197, 394, 788. (roughly 1/6, 1/3 and 2/3 of the width)

The shrink algorithm is something I have written myself. There is no blitting, just pixel level manipulation.
I don’t think the error is in the shrinking algorithm though, because as I said, if I independantly run the shrink algorithm on the same image with the same scale factor, then no error occurs.

I can think of only one other place for the error to be, and that is in the memory management, creating and freeing surfaces. So here is the way the code goes for that.

Code:

const int zoom_max = 4; // Number of zoom levels.
SDL_Surface src;
SDL_Surface
* src_zooms; // Zoomed images.
double* sf_zooms; // Scale factors of each zoom level.

// Load source image.
SDL_Surface* src = IMG_Load(file_name.c_str());
/////////////////////////

// Convert source image to 32 bpp
SDL_Surface* convert = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, 1, 32, 0, 0, 0, 0);
SDL_Surface* fin = SDL_ConvertSurface(src, convert->format, SDL_HWSURFACE);
SDL_FreeSurface(src);
SDL_FreeSurface(convert);
src = fin;
////////////////////////////////////////

// Create copies of source image.
src_zooms = new SDL_Surface* [zoom_max];
for (int z_i=0; z_i < (zoom_max - 1); z_i++)
{
src_zooms[z_i] = SDL_ConvertSurface(src, src->format, SDL_HWSURFACE);
}
///////////////////////////////////////

// Resize copies of source image.
sf_zooms = new double [zoom_max];
for (int z_i=0; z_i < (zoom_max - 1); z_i++)
{
sf_zooms[z_i] = (1 + ((sfx - 1) * (zoom_max - z_i - 1) / zoom_max));
src_zooms[z_i] = shrink_algorithm(src_zooms[z_i], sf_zooms[z_i], sf_zooms[z_i]);
}
//////////////////////////////////////

The shrink_algorithm does the following in terms of memory:
// Create Surface with scaled dimensions.
// Free source surface.

I’ve uploaded an example of the effect. I have to save it as a jpg, but you get the idea.
[Image: http://j.imagehost.org/t/0617/e_1_3.jpg ] (http://j.imagehost.org/view/0617/e_1_3)

Thanks,
rps

Have you tried with a more recent version of SDL? It is at 1.2.14,
currently. What OS are you on? I experienced a bug in an older version of
SDL for Ubuntu which didn’t handle the 127 alpha optimization correctly, for
example.

Jonny DOn Fri, Sep 3, 2010 at 6:21 AM, rps <sdlf.20.icewater at spamgourmet.com>wrote:

Hi Julian,

It seems that the particular image does not matter, just the dimensions, so
here are those details.
The original size was 1536x1152.
The scale factor was 1.3 for both dimensions.
This gives a final image of 1182x886.
The lines appear at x = 197, 394, 788. (roughly 1/6, 1/3 and 2/3 of the
width)

The shrink algorithm is something I have written myself. There is no
blitting, just pixel level manipulation.
I don’t think the error is in the shrinking algorithm though, because as I
said, if I independantly run the shrink algorithm on the same image with the
same scale factor, then no error occurs.

I can think of only one other place for the error to be, and that is in the
memory management, creating and freeing surfaces. So here is the way the
code goes for that.

Code:

const int zoom_max = 4; // Number of zoom levels.
SDL_Surface src;
SDL_Surface
* src_zooms; // Zoomed images.
double* sf_zooms; // Scale factors of each zoom level.

// Load source image.
SDL_Surface* src = IMG_Load(file_name.c_str());
/////////////////////////

// Convert source image to 32 bpp
SDL_Surface* convert = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, 1, 32, 0, 0,
0, 0);
SDL_Surface* fin = SDL_ConvertSurface(src, convert->format, SDL_HWSURFACE);
SDL_FreeSurface(src);
SDL_FreeSurface(convert);
src = fin;
////////////////////////////////////////

// Create copies of source image.
src_zooms = new SDL_Surface* [zoom_max];
for (int z_i=0; z_i < (zoom_max - 1); z_i++)
{
src_zooms[z_i] = SDL_ConvertSurface(src, src->format, SDL_HWSURFACE);
}
///////////////////////////////////////

// Resize copies of source image.
sf_zooms = new double [zoom_max];
for (int z_i=0; z_i < (zoom_max - 1); z_i++)
{
sf_zooms[z_i] = (1 + ((sfx - 1) * (zoom_max - z_i - 1) / zoom_max));
src_zooms[z_i] = shrink_algorithm(src_zooms[z_i], sf_zooms[z_i],
sf_zooms[z_i]);
}
//////////////////////////////////////

The shrink_algorithm does the following in terms of memory:
// Create Surface with scaled dimensions.
// Free source surface.

I’ve uploaded an example of the effect. I have to save it as a jpg, but you
get the idea.
http://j.imagehost.org/view/0617/e_1_3

Thanks,
rps


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

Jonny D wrote:

Have you tried with a more recent version of SDL? ?It is at 1.2.14, currently. ?What OS are you on? ?I experienced a bug in an older version of SDL for Ubuntu which didn’t handle the 127 alpha optimization correctly, for example.

Hi Jonny D,

I have updated to 1.2.14, and there has been no change.
The error is present on operating systems XP & Vista.
My IDE is Visual C++ 2008 Express Edition.

Thanks,
rps

It really seems like a problem with the shrinking code. Is the effect that
it skips vertical lines, leaving them black? Are you iterating over the
pixels in the source surface and putting them onto the destination or are
you iterating over the pixels in the destination surface and grabbing the
appropriate colors from the source? Sometimes the former can give you funny
results because of incremental arithmetic error. You could use a surface
scaling function from either SDL_gfx or Sprig instead.

Jonny DOn Sun, Sep 12, 2010 at 6:36 AM, rps <sdlf.20.icewater at spamgourmet.com>wrote:

Jonny D wrote:

Have you tried with a more recent version of SDL? It is at 1.2.14,
currently. What OS are you on? I experienced a bug in an older version of
SDL for Ubuntu which didn’t handle the 127 alpha optimization correctly, for
example.

Hi Jonny D,

I have updated to 1.2.14, and there has been no change.
The error is present on operating systems XP & Vista.
My IDE is Visual C++ 2008 Express Edition.

Thanks,
rps


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

My shrinking function iterates over the destination image. And because it has to handle non-integer scale factors, it has to average the RGB values over an area that may include fractions of pixels.

The image I posted earlier gives a good idea of the error - the lines are not left blank they are given the wrong colour.

As I have said, when I run the shrinking code independently with the same image and parameters there is no error.
So I do not see how the shrinking code can be the problem. May I ask what makes you think that?

In any case, I will try with an alternative shrinking code. (Although if that works, it may be because it handles memory differently)

rps

Eh, I just figure it’s the shrinking code (not necessarily the algorithm)
because what you showed is not a problem that would go unnoticed if it were
due to SDL, the code you’ve shown is not suspicious (though I would try
using software surfaces and it looks like you end your loops early: you
don’t need the -1 in the tests), memory issues don’t typically behave so
well, and you haven’t shown the scaling code yet. What exactly do you mean
by running the shrinking code independently? It’s the same code, using SDL,
just in a different program?

Jonny DOn Sun, Sep 12, 2010 at 12:13 PM, rps <sdlf.20.icewater at spamgourmet.com>wrote:

My shrinking function iterates over the destination image. And because it
has to handle non-integer scale factors, it has to average the RGB values
over an area that may include fractions of pixels.

The image I posted earlier gives a good idea of the error - the lines are
not left blank they are given the wrong colour.

As I have said, when I run the shrinking code independently with the same
image and parameters there is no error.
So I do not see how the shrinking code can be the problem. May I ask what
makes you think that?

In any case, I will try with an alternative shrinking code. (Although if
that works, it may be because it handles memory differently)

rps


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

Jonny D wrote:

Eh, I just figure it’s the shrinking code (not necessarily the algorithm) because what you showed is not a problem that would go unnoticed if it were due to SDL, the code you’ve shown is not suspicious (though I would try using software surfaces and it looks like you end your loops early: you don’t need the -1 in the tests), memory issues don’t typically behave so well, and you haven’t shown the scaling code yet. ?What exactly do you mean by running the shrinking code independently? ?It’s the same code, using SDL, just in a different program?

Well observed on the “-1 in the tests”. The reason for that is not apparent in the code I’ve shown. It is because the maximum zoom level is just the original image, so does not need to be processed in those loops. Later on, it is useful to have all the zoom levels in an array rather than the maximum zoom level being a special case.

I had tried switching to software surfaces. It had no effect.

Yep, that is exactly what I mean by running the shrinking code independently. This program is more complex as it makes multiple surfaces, blits to the screen and takes user input. The independent program has exactly the same shrinking algorithm but very little else to complicate things.

I’ve been working on another project today, so I haven’t tried an alternative shrinking code yet. I’ll report on that when I’ve done it.

Thanks for your help,
rps