Saving SDL-native images

I’d like to try to save images to disc in SDL_surface format for fast loading. I’ve got most of it figured out, but there are a couple things I need to know.

  1. What’s the formula for calculating the total size of the Pixels member? Would “h * pitch * format.BytesPerPixel” work, or is it more complicated?
  2. Are there any fields in the SDL_surface record that don’t need to be (or shouldn’t be) saved and reloaded at runtime? It looks to me like the hwdata, blitmap, locked, clip_rect, format_version and refcount fields are things that should be generated by SDL at runtime, and format should be checked carefully to make sure it’s compatible with the pixels you’ve got saved. Are these correct? Anything else?

Mason

The real SDL pros will probably shoo me out, but I’ll ask, what’s so
wrong with regular image loading? o_O

Mason Wheeler wrote:> I’d like to try to save images to disc in SDL_surface format for fast

loading. I’ve got most of it figured out, but there are a couple
things I need to know.

  1. What’s the formula for calculating the total size of the Pixels
    member? Would “h * pitch * format.BytesPerPixel” work, or is it more
    complicated?
  2. Are there any fields in the SDL_surface record that don’t need to
    be (or shouldn’t be) saved and reloaded at runtime? It looks to me
    like the hwdata, blitmap, locked, clip_rect, format_version and
    refcount fields are things that should be generated by SDL at runtime,
    and format should be checked carefully to make sure it’s compatible
    with the pixels you’ve got saved. Are these correct? Anything else?

Mason


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

I’m going to have to second this.

If the purpose of doing this is faster image loading, you will
probably be disappointed. Since reading from the disk is so slow, I
would gladly wager that saving the images as (smaller, losslessly
compressed) .png files and loading these with SDL Image would be much
faster than using the (larger, but computationally simpler)
SDL_surface internal format. Or even use .bmp … the performance
difference between this and what you’re proposing will be negligible.

  • HolmesOn Jun 8, 2008, at 1:13 PM, Leo Cabrera wrote:

The real SDL pros will probably shoo me out, but I’ll ask, what’s so
wrong with regular image loading? o_O

Mason Wheeler wrote:

I’d like to try to save images to disc in SDL_surface format for
fast loading. I’ve got most of it figured out, but there are a
couple things I need to know.

  1. What’s the formula for calculating the total size of the Pixels
    member? Would “h * pitch * format.BytesPerPixel” work, or is it
    more complicated?
  2. Are there any fields in the SDL_surface record that don’t need
    to be (or shouldn’t be) saved and reloaded at runtime? It looks to
    me like the hwdata, blitmap, locked, clip_rect, format_version and
    refcount fields are things that should be generated by SDL at
    runtime, and format should be checked carefully to make sure it’s
    compatible with the pixels you’ve got saved. Are these correct?
    Anything else?

Mason


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


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

I’m aware of the disc issues. The images will be saved into an archive with a good compression algorithm, and can be read fairly quickly from the disc and decompressed, comparable to PNG loading. The question then becomes one of how many steps to take:

PNG: Load from disc. Decompress. Convert image data to SDL native-compatible version. Load into SDL_Surface struct. Finished.
SDL native: Read from disc. Decompress. Create empty SDL_Surface and memcopy the image data in (very fast). Finished.

The format conversion is a lot slower, and I’d prefer to have to do it as little as possible, especially considering that my program is going to be processing quite a few different images from different files. (What can I say? I’m a perfectionist and a bit OCD about optimizations.)>----- Original Message ----

From: Holmes Futrell
To: A list for developers using the SDL library. (includes SDL-announce)
Sent: Sunday, June 8, 2008 5:49:33 PM
Subject: Re: [SDL] Saving SDL-native images

I’m going to have to second this.

If the purpose of doing this is faster image loading, you will
probably be disappointed. Since reading from the disk is so slow, I
would gladly wager that saving the images as (smaller, losslessly
compressed) .png files and loading these with SDL Image would be much
faster than using the (larger, but computationally simpler)
SDL_surface internal format. Or even use .bmp … the performance
difference between this and what you’re proposing will be negligible.

  • Holmes

On Jun 8, 2008, at 1:13 PM, Leo Cabrera wrote:

The real SDL pros will probably shoo me out, but I’ll ask, what’s so
wrong with regular image loading? o_O

Mason Wheeler wrote:

I’d like to try to save images to disc in SDL_surface format for
fast loading. I’ve got most of it figured out, but there are a
couple things I need to know.

  1. What’s the formula for calculating the total size of the Pixels
    member? Would “h * pitch * format.BytesPerPixel” work, or is it
    more complicated?
  2. Are there any fields in the SDL_surface record that don’t need
    to be (or shouldn’t be) saved and reloaded at runtime? It looks to
    me like the hwdata, blitmap, locked, clip_rect, format_version and
    refcount fields are things that should be generated by SDL at
    runtime, and format should be checked carefully to make sure it’s
    compatible with the pixels you’ve got saved. Are these correct?
    Anything else?

Mason

I also agree that you generally shouldn’t do this, except for a single
case. If you are running embedded (handheld) and have limited
physical memory, it’s okay to MMAP the file and use
SDL_CreateSurfaceFrom so that you don’t have the image living in both
RAM and ROM.

If it’s just an optimization, remember the First Rule: Don’t Do It.
Profile your code and see if it really is a problem. The way you
describe this particular optimization doesn’t even win you much for
the cost, especially if the regular image loading code is fairly
efficient (as I suspect).

Tim

I think you could create a loader that uses for example LZF
http://www.goof.com/pcg/marc/liblzf.html to compress data (faster than
GIF or PNG), but since surface data is organized in memory-aligned lines
(hence the use of pitch), you may not benefit much in terms of speed.
Also, depending on you image data, the compression ratio may be very poor.

–AS

Mason Wheeler wrote:> I’d like to try to save images to disc in SDL_surface format for fast

loading. I’ve got most of it figured out, but there are a couple
things I need to know.

  1. What’s the formula for calculating the total size of the Pixels
    member? Would “h * pitch * format.BytesPerPixel” work, or is it more
    complicated?
  2. Are there any fields in the SDL_surface record that don’t need to
    be (or shouldn’t be) saved and reloaded at runtime? It looks to me
    like the hwdata, blitmap, locked, clip_rect, format_version and
    refcount fields are things that should be generated by SDL at runtime,
    and format should be checked carefully to make sure it’s compatible
    with the pixels you’ve got saved. Are these correct? Anything else?

Mason


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

Andreas Schiffler wrote:

I think you could create a loader that uses for example LZF
http://www.goof.com/pcg/marc/liblzf.html to compress data (faster than
GIF or PNG), but since surface data is organized in memory-aligned lines
(hence the use of pitch), you may not benefit much in terms of speed.
Also, depending on you image data, the compression ratio may be very poor.

Some information that might help with eval of liblzf for your needs:

LZF is very fast, but the last time I looked, it has a fixed
sliding dictionary of 8KB, a block size of 64KB, and rather
inefficient (but fast) literal run encoding. It’s designed for
read/write speed. The trouble is the write speed. LZF must
sacrifice lots of compression size performance for speed.

I assume that a loader should care more about read speed. For
write, in order to be blindingly fast, LZF does a single hash
lookup for each byte position, plus IIRC, optional limited hash
table updates. This is pretty inefficient compression.

For the Canterbury Corpus, LZF with a 16 bit hash is 38% larger
than the worst gzip (gzip -1), or 63% larger than gzip -9. Well,
incidentally I have modified LZF to pick best matches, and the
best it can do is still 23% larger than gzip -1, and 46% versus
gzip -9.

So from the looks of it, LZF will not come remotely close to PNG,
if you are evaluating in terms of compression ratio. What LZF can
give you is, since it is so fast, your loads will be dominated by
I/O performance and the processor load will be low, but which the
average user will probably not notice unless they use a CPU monitor.> Mason Wheeler wrote:

I’d like to try to save images to disc in SDL_surface format for fast
loading. I’ve got most of it figured out, but there are a couple
things I need to know.

  1. What’s the formula for calculating the total size of the Pixels
    member? Would “h * pitch * format.BytesPerPixel” work, or is it more
    complicated?
  2. Are there any fields in the SDL_surface record that don’t need to
    be (or shouldn’t be) saved and reloaded at runtime? It looks to me
    like the hwdata, blitmap, locked, clip_rect, format_version and
    refcount fields are things that should be generated by SDL at runtime,
    and format should be checked carefully to make sure it’s compatible
    with the pixels you’ve got saved. Are these correct? Anything else?


Cheers,
Kein-Hong Man (esq.)
Kuala Lumpur, Malaysia

Andreas Schiffler wrote:

I think you could create a loader that uses for example LZF
http://www.goof.com/pcg/marc/liblzf.html to compress data (faster than
GIF or PNG), but since surface data is organized in memory-aligned lines
(hence the use of pitch), you may not benefit much in terms of speed.
Also, depending on you image data, the compression ratio may be very poor.

–AS

Mason Wheeler wrote:

I’d like to try to save images to disc in SDL_surface format for fast
loading. I’ve got most of it figured out, but there are a couple
things I need to know.

Oops, my bad, you are looking at save performance too. I know too
little to say anything about SDL_surface, but I had crunched at
one time rough compress+save speeds for the Canterbury Corpus
which might be useful for evaluation purposes. Read times were
subtracted so the “Speed Ratio” below is a rough measure of
compress+save times. Higher ratio is faster. UCL, LZO and LZF were
the three most well-known fast and free data compression libraries.

    Speed   Output
    Ratio   Size

copy 1.00 2810784 – Canterbury Corpus
gzip-1 1.11 865535
gzip-9 0.20 730732 – best gzip is 5X slower than fastest
bzip-1 0.41 575983
bzip-9 0.39 542710
ucl-1 0.70 1011258
ucl-7 0.17 828886
lzo-1 2.21 1164742 – LZO more than double copy speed
lzo-9 0.08 929578
lzf 1.97 1193552 – LZF is slightly slower than LZO-1
lzf* 0.04 1066845 – experimental lzf with best match

Machine is a Sempron 3000+.

Note that if your images have continuous tones, then compression
size performance for all of the above methods will be pretty bad.>> [snip]

Mason


Cheers,
Kein-Hong Man (esq.)
Kuala Lumpur, Malaysia

Hi Mason,

To add weight to the concensus, I’m sure you’ve thought of this, but you
do realise that “SDL-native format” is different on every platform?

That is, it may well be the same on Windows and Linux/x86, but it’s
definitely different on B.E. systems, such as PPC, vs. x86. It’s almost
certainly different between x86 & AMD64. Lets not forget that you’ll
also have to re-write your code when SDL changes (maybe not today, maybe
not tomorrow…)

So as someone else pointed out, unless you’re doing this on exactly ONE
platform, with MASSIVE memory constraints (even phones have oodles of
RAM these days…), then this is (almost certainly) not the way forward.

Of course, it will help you learn about the internals of SDL, which can
only be a Good Thing. :slight_smile:

I’m curious… was there a particular platform you had in mind?

A general note on optimisation: IO optimisations (i.e. level-loading)
are generally less important than processing optimisations (i.e. game
play), because people EXPECT there to be a pause while a level loads.

Jitsu Love,

Eddy

Mason Wheeler wrote:> I’d like to try to save images to disc in SDL_surface format for fast

loading. I’ve got most of it figured out, but there are a couple things
I need to know.

  1. What’s the formula for calculating the total size of the Pixels
    member? Would “h * pitch * format.BytesPerPixel” work, or is it more
    complicated?
  2. Are there any fields in the SDL_surface record that don’t need to be
    (or shouldn’t be) saved and reloaded at runtime? It looks to me like the
    hwdata, blitmap, locked, clip_rect, format_version and refcount fields
    are things that should be generated by SDL at runtime, and format should
    be checked carefully to make sure it’s compatible with the pixels you’ve
    got saved. Are these correct? Anything else?

Mason



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

Hi Mason,

To add weight to the concensus, I’m sure you’ve thought of this, but you
do realise that “SDL-native format” is different on every platform?

That is, it may well be the same on Windows and Linux/x86, but it’s
definitely different on B.E. systems, such as PPC, vs. x86. It’s almost
certainly different between x86 & AMD64.

Ack. Actually, I wasn’t aware of that particular monkey-wrench. Probably should have been, though. :frowning:

Here’s my rationale for wanting to do this:
Among other things, I’m creating a converter to open sprite sheets from other sources and rearrange them into a format that would work well with my game engine. SDL has a very simple way to do this: Load source image to a surface, create a blank surface, blit things into the right places, and save the destination surface. Except for the last step. SDL_Image is quite noticeably missing Save counterparts for its Load functions. Sure, SDL can save to BMP format, but BMP is uncompressed. We’ve got no support for saving to truly useful image formats like PNG and JPEG. And the idea of saving to a temporary BMP and then reopening that with a PNG library, converting it, and saving AGAIN… just bugs me. So I figured it would be simpler just to eliminate all the conversions after the first one.

Mason>----- Original Message ----

From: Edward Cullen

Hello !

format, but BMP is uncompressed. We’ve got no support for saving to
truly useful image formats like PNG and JPEG. And the idea of
saving to a temporary BMP and then reopening that with a PNG
library, converting it, and saving AGAIN… just bugs me. So I
figured it would be simpler just to eliminate all the conversions
after the first one.

In the mailinglist archives somewhere there should be code snippets
how to save SDL Surfaces in PNG and JPEG format using the official
JPEG and PNG libs.

CU

Mason Wheeler wrote:

SDL_Image is quite noticeably missing Save counterparts for its Load functions.

Sounds like a perfect opportunity to contribute to SDL_Image to me, as
in, that’s the whole OSS model - someone does something useful, someone
else finds something that needs adding, adds it and passes it back to
the community.

It seems reasonable to me that, especially as SDL is not just used for
games any more, SDL_Image should support saving as well as loading…

Eddy

hi,

Note, that pygame(SDL in python) has jpeg, and png saving C functions
if you want to copy them from there:
http://www.seul.org/viewcvs/viewcvs.cgi/trunk/src/imageext.c?root=PyGame&view=markup

cheers,On Tue, Jun 10, 2008 at 10:45 AM, Edward Cullen wrote:

Mason Wheeler wrote:

SDL_Image is quite noticeably missing Save counterparts for its Load
functions.

Sounds like a perfect opportunity to contribute to SDL_Image to me, as in,
that’s the whole OSS model - someone does something useful, someone else
finds something that needs adding, adds it and passes it back to the
community.

It seems reasonable to me that, especially as SDL is not just used for
games any more, SDL_Image should support saving as well as loading…

Eddy


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

Thanks! Only one problem. I write in Delphi, which has its own PNG library that’s not syntax-compaitble with C’s libpng. I’ll look over your code, though, and see if it’s helpful…> ----- Original Message -----

From: renesd@gmail.com (Rene Dudfield)
To: A list for developers using the SDL library. (includes SDL-announce)
Sent: Monday, June 9, 2008 9:03:17 PM
Subject: Re: [SDL] Saving SDL-native images

hi,

Note, that pygame(SDL in python) has jpeg, and png saving C functions
if you want to copy them from there:
http://www.seul.org/viewcvs/viewcvs.cgi/trunk/src/imageext.c?root=PyGame&view=markup

cheers,

On Tue, Jun 10, 2008 at 10:45 AM, Edward Cullen wrote:

Mason Wheeler wrote:

SDL_Image is quite noticeably missing Save counterparts for its Load
functions.

Sounds like a perfect opportunity to contribute to SDL_Image to me, as in,
that’s the whole OSS model - someone does something useful, someone else
finds something that needs adding, adds it and passes it back to the
community.

It seems reasonable to me that, especially as SDL is not just used for
games any more, SDL_Image should support saving as well as loading…

Eddy


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


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