Bitmap Scaling - an API proposal

the criterion for including surface scaling functions is whether it
can be accelerated in hardware on sufficiently common platforms.
I have a feeling this is the case so this is something we’ll probably
add at some point in the future (probably in 1.3)

as usual the hard part isn’t in writing the code but designing a good
api

I think it is a good idea to include scaling functions into SDL. It is a
common operation on 2D images (simple but not trivial to implement). There
are two ways to embed a picture into a screen layout:

1.) the picture dimensions determine the size of the displayed image
2.) the screen layout determines the size of the displayed image

For case 2, there is a need to adapt the picture size. Again, there are
two ways I am aware of:

1.) crop the image
2.) scale the image

I assume that it might be important for some applications to show the
whole picture and fit into a predetermined layout. Thus there is a need
for a scaling operation. I would like to see it in SDL 1.3 if possible.

In Windows GDI, there are two functions taking care of it, StretchBlt and
SetStretchBltMode. The signature of StretchBlt() is

bool StretchBlt(hdc dest, int xorigdest, yorigdest, widthdest, heightdest,
hdc src, int xorigsrc, yorigsrc, widthsrc, heightsrc,
unsigned long rasterop);

There are two surfaces (device contexts in GDI speak), the source and
destination rectangles (x,y,w,h), and a raster operation which controls
the blitter. The needed raster operation in this example is SRCCOPY, where
the source rectangle is directly copied to the destination rectangle (and
stretched, of course). GDI scales the bitmap in memory, then copies the
result
to the destination surface. The color data for patterns/destination
pixels is
merged afterwards. Color format conversion is also done if required.

Is it possible to use the front/back scalers of the graphics
card to speed it up? Video memory is not a problem anymore, I think.
But let’s look at the API which is more important at the moment.

The interface is similar to SDL_BlitSurface(), and it feels to be very
intuitive:

int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect);

I’ll show two versions, the first being simpler than the last:

int SDL_ScaleSurface(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect);

or

int SDL_ScaleSurface(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect,
unsigned long rasterop);

and, to keep it consistent:

int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect,
unsigned long rasterop)

[or SDL_ScaleSurfaceROP and SDL_BlitSurfaceROP to keep backward
compatibility]

The raster operations would be supported by the blitter AFAIK, some
examples:

  • MERGECOPY: Merges the colors of the source rectangle with the specified
    pattern by using the Boolean AND operator
  • SRCPAINT: Combines the colors of the source and destination rectangles
    by using the Boolean OR operator.

I don’t know if it really makes sense to provide the raster operation for
scaling. Some demo coders could comment on this I think.

Another problem is color conversion. There is another call in GDI which
allows color images to be converted nicely:

int SetStretchBltMode(hdc, int StretchMode);

These modes are offered:

  • STRETCH_DELETESCANS: simply deletes eliminated pixels
  • STRETCH_ANDSCANS: color values of eliminated and existing pixels
    are ANDed
  • STRETCH_ORSCANS: color values of eliminated and existing pixels
    are ORed
  • STRETCH_HALFTONE: maps pixels from src rect into blocks of pixels
    in dest rect so that average color over dest block
    of pixels approximates color of src pixel

Halftone works very well, a color difference is not visible. I think
it is not hardware supported and very slow, but that is the choice of
the programmer, not of the library. Showing still images allows to
enhance quality at the expense of speed, whereas an animation has to
be fast. So SDL could be used for several different applications,
leaving the policy to the application. A default could opt for speed,
so it would be DELETESCANS in this case.

In SDL, this could be

int SDL_SetScaleSurfaceMode(SDL_Surface *dst, Uint8 flag);

or

int SDL_SetScaleSurfaceMode(SDL_Surface *dst, Uint32 flag);

with ‘flag’ being an enumeration:

SDL_SCALE_DELETESCANS
SDL_SCALE_ANDSCANS
SDL_SCALE_ORSCANS
SDL_SCALE_HALFTONE

Any comments?

Andri HeynatzOn Fri, 16 Mar 2001, “Mattias Engdegard” wrote

int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect,
unsigned long rasterop)

[or SDL_ScaleSurfaceROP and SDL_BlitSurfaceROP to keep backward
compatibility]

The raster operations would be supported by the blitter AFAIK, some
examples:

  • MERGECOPY: Merges the colors of the source rectangle with the
    specified
    pattern by using the Boolean AND operator
  • SRCPAINT: Combines the colors of the source and destination
    rectangles
    by using the Boolean OR operator.

It seems to me that these wouldn’t be used too much. I’d rather suggest
NEAREST, LINEAR (and BICUBIC or TRILINEAR?) as rasterop so that
developer could request for best scaling quality or speed. This should
be interpreted as minimum requirement and SDL should be allowed to use
LINEAR instead of requested NEAREST if possible (most graphic cards get
full speed with both, no reason to use the ugly one).

I think it should be defined explicit wheter or not this supports alpha
blending or not. Or perhaps there should be a flag to request that:
BLEND_DESIRED, BLEND_REQUIRED, BLEND_IF_ACCELERATED or something like
that.

  • Mikko

Andre Heynatz wrote:

any particular reason you are replying to a 9-month old message? Some readers
might have lost the thread by now

I don’t know if it really makes sense to provide the raster operation for
scaling. Some demo coders could comment on this I think.

as I wrote just a couple of days ago, raster ops are not useful in SDL
anywhere, and there are no plans to support them

  • STRETCH_DELETESCANS: simply deletes eliminated pixels
  • STRETCH_ANDSCANS: color values of eliminated and existing pixels
    are ANDed
  • STRETCH_ORSCANS: color values of eliminated and existing pixels
    are ORed
  • STRETCH_HALFTONE: maps pixels from src rect into blocks of pixels
    in dest rect so that average color over dest block
    of pixels approximates color of src pixel

no, these are hardly useful. Think in terms of the reconstruction filter
used instead (scaling a raster image is a resampling operation)

On the whole, image scaling is likely to be worthwhile in SDL, so you
don’t have to convince me at least>On Fri, 16 Mar 2001, “Mattias Engdegard” wrote

the criterion for including surface scaling functions is whether it
can be accelerated in hardware on sufficiently common platforms.
I have a feeling this is the case so this is something we’ll probably
add at some point in the future (probably in 1.3)

Hooray!

int SDL_ScaleSurface(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect);

This prototype would be nice since I wouldn’t have to change any of my
code except for the function name. :slight_smile:
(My *ScaleBlit() functions take those arguments exactly.)On Tue, Dec 11, 2001 at 11:08:22AM +0100, Andre Heynatz wrote:

On Fri, 16 Mar 2001, “Mattias Engdegard” wrote


Greg V. (hmaon)