Jump to content

  • Log In with Google      Sign In   
  • Create Account


SOIL: new lightweight image loading lib


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
130 replies to this topic

#1 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 30 July 2007 - 05:43 PM

Hi, All. This is an announcement, but I think it fits better in this forum. If I'm wrong, feel free to move it [8^) I've been looking for a tiny image loading library for some hobby OpenGL game projects I'm working on, but never really found exactly what I wanted. Then I found Sean Barrett's awesome C code for loading BMP/PNG/JPG files (here). I took that, added TGA loading support (except for indexed TGA images), wrapped some common functions like upsizing to power-of-two sizes, MIPmap generation, pre-multiplying alpha, etc. all into a single function call for easy loading of textures into OpenGL. Presenting the Simple OpenGL Image Library (yes, I'm sorry SOIL is such a lame acronym [8^) Features: Loads PNG, JPG, TGA, BMP, DDS (a subset of each type) Saves TGA, BMP, DDS Loads an image file directly into an OpenGL texture Can automatically rescale the image to the next largest power-of-two size Can automatically create MIPmaps Can multiply alpha on load (for more correct blending / compositing) Can flip the image vertically Can compress to DXT1 or DXT5 (if EXT_texture_compression_s3tc is available) Will downsize the image if necessary to fit GL_MAX_TEXTURE_SIZE No external dependencies Tiny Public Domain If anybody is willing to give some feedback, I'd really appreciate it (I'm keeping this a C project, and my C skills are extremely rusty). Feature requests are also welcome. [edited to add new features] [Edited by - lonesock on August 16, 2007 11:59:53 AM]

Sponsor:

#2 ForestMaster   Members   -  Reputation: 164

Like
0Likes
Like

Posted 30 July 2007 - 07:13 PM

I've found it such a neat, tidy and useful drop i can't help saying thanks, good job!

#3 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 31 July 2007 - 09:26 AM

Quote:
Original post by ForestMaster
I've found it such a neat, tidy and useful drop i can't help saying thanks, good job!

Thanks!

I updated SOIL a bit: you can now pass in a flag to specify that you want the image flipped vertically, and you can flag that you want the image compressed to use DXT(1 for RGB, 5 for RGBA), if EXT_texture_compression_s3tc is available. Note that this could be slow, depending on your OpenGL drivers. I'm looking into writing my own (hopefully faster) DXT1/3/5 compressor, but that's down the road. Next step is just loading already compressed DDS files.


#4 scgames   Members   -  Reputation: 1965

Like
0Likes
Like

Posted 31 July 2007 - 12:32 PM

Looks very cool - bookmarked for future reference :)

#5 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 02 August 2007 - 01:39 PM

Quote:
Original post by jyk
Looks very cool - bookmarked for future reference :)

[8^)

OK, I have written my own DXT1 compressor, decent quality, very fast (about 31ms for a 512x512 RGB image). I'm planning to add this to SOIL this weekend, so if a user specifies that they want the image loaded as DXT, SOIL will do the conversion without relying on the (very slow, for me at least) OpenGL driver to do the conversion.

A sample:
Here is the original image, and
here is the one done in 31ms, and
here is the DXT1 file from ATI's Compressonator (~1.5 seconds)

#6 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 07 August 2007 - 08:34 AM

SOIL can now load compressed DDS files directly as an OpenGL texture! It also has its own DXT compressor now, so no reliance on the OpenGL driver for uploading uncompressed images in S3TC format. Any image file SOIL can load can be quickly compressed (~26ms for a 512x512 image on my Athlon64 3000+). You can also save any file as a DDS file (SOIL will use the internal compressor). This works for screenshots too.

The testSOIL.exe file takes an image specified on the command line, then resizes it to the nearest larger power-of-two (if needed), pre-multiplies alpha, generates the MIPmaps, compresses to DXT1 (for RGB images) or DXT5 (for RGBA images), uploads the image to OpenGL then displays 2 quads, 1 stationary and 1 spinning with that texture on it. When you hit [Esc] the program will exit after saving a screenshot in TGA format.

The exe was compiled with MinGW 3.4.5, as was the libSOIL.a file. The SOIL_vc8.lib file was compiled with Microsoft's very nifty free VS2005 Express edition.

Please let me know if anybody gets it to work under a new compiler or has any feedback / feature requests.

#7 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 11 August 2007 - 04:57 AM

Oops, SOIL's MIPmap generator used to die on non-square textures...fixed now.

#8 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 14 August 2007 - 07:29 AM

I just uploaded a new SOIL version, here are the changes:

Updated to stb_image version 0.97

SOIL can now decompress DDS files (allows regular file loading, e.g. for heightmaps, etc, allows image flipping, resizing, pre-multiplying alpha, etc. It also means that there is no need to have an alternate art asset path in case the user's machine doesn't support DXT compression)

You can still force the DDS files to be loaded directly if supported (and everything GeForce2 and above will support it), but you lose all the other nifty options.

There is some simple error reporting, in case an image fails to load.

#9 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 14 August 2007 - 12:02 PM

SOIL can now load Indexed TGA images.

So, basically, except for bug fixes and porting, I'm pretty much ready to call it a day.

Feedback is always appreciated.

#10 zerotri   Members   -  Reputation: 274

Like
0Likes
Like

Posted 14 August 2007 - 03:41 PM

This is a very nice, clean library you have here, lonesock.
I'm going to be using it to replace SDL_Image as my image loading library in my game engine.
thanks for the awesome work!

#11 Kylotan   Moderators   -  Reputation: 3324

Like
0Likes
Like

Posted 15 August 2007 - 09:05 AM

Quote:
Original post by lonesock
SOIL can now load Indexed TGA images.

So, basically, except for bug fixes and porting, I'm pretty much ready to call it a day.


Inevitably some fool will later spurn your library, claiming it's "unmaintained... no updates since 2007". :)

Sounds good. I'll get it up on my library list when I get around to the next update.

Just a thought though; how good is the mip-map generation algorithm? Someone might want something better than the typical bilinear filtering. (eg. bicubic)

#12 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 15 August 2007 - 10:48 AM

Quote:
Original post by Kylotan
Inevitably some fool will later spurn your library, claiming it's "unmaintained... no updates since 2007". :)

[8^)
Not to mention I spoke too soon! On my laptop's S3 chipset I ran into a 1024x1024 texture size limit. So SOIL now queries GL_MAX_TEXTURE_SIZE, and will automatically downsize the image to fit the implementation limits (only the offending dimension(s), and only when uploading a texture to OpenGL, nothing is touched when you load an image by itself). I'll try to get the fix up on my website today or tomorrow.

Quote:
Original post by Kylotan
Just a thought though; how good is the mip-map generation algorithm? Someone might want something better than the typical bilinear filtering. (eg. bicubic)

Hmm, I cheat. If the user wants MIPmaps, I force the image to be a power-of-two size (upsizing it if necessary using simple bilinear sampling). Then for each MIPmap I do a simple average over the appropriate block. So for MIPmap 1, each pixel is an average over the associated 2x2 block. For MIPmap 2, each pixel is an average over 4x4 blocks, etc. I do this to try to keep from propagating errors at each level (i.e. I build MIP 2 from MIP 0, not just from MIP 1).

If you have any links pointing to literature on the proper / better / best way to do MIPmaps, I'd be more than happy to implement a different method.

#13 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 15 August 2007 - 10:51 AM

Quote:
Original post by zerotri
This is a very nice, clean library you have here, lonesock.
I'm going to be using it to replace SDL_Image as my image loading library in my game engine.
thanks for the awesome work!

Thanks! And you're welcome [8^)


#14 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 16 August 2007 - 05:57 AM

Soil is updated once again:

* Will now downsize the image if necessary to fit GL_MAX_TEXTURE_SIZE

* Added SOIL_create_OGL_texture() to upload raw image data that isn't from an image file. Basically I just split the standard SOIL_load_OGL_texture() out so I could upload my own generated/modified image data straight from RAM, with all of the other nifty features still available to me, like DXT compression, MIPmap generation, etc.


#15 DeathCarrot   Members   -  Reputation: 188

Like
0Likes
Like

Posted 18 August 2007 - 12:54 PM

Great library, thanks =D
For *nix (X11) systems, you need to #include <GL/glx.h> for glXGetProcAddressARB() in SOIL.c, otherwise it works perfectly under linux.
Also, it won't compile ansi-strict as there isn't enough implicit casting (generally mallocs), also you're using C++ style comments in C code, and possibly one or two other bits and bobs, but that isn't really much of an issue (I just prefer to compile all my code ansi-strict, just a habit).
If you're looking of ways to extend this, you could add loaders for cube (and possibly sphere and dual-paraboloid) environment maps =)

Great work! I'll definitely be using this for my projects.

#16 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 20 August 2007 - 07:01 PM

Quote:
Original post by DeathCarrot
Great library, thanks =D
For *nix (X11) systems, you need to #include <GL/glx.h> for glXGetProcAddressARB() in SOIL.c, otherwise it works perfectly under linux.
Also, it won't compile ansi-strict as there isn't enough implicit casting (generally mallocs), also you're using C++ style comments in C code, and possibly one or two other bits and bobs, but that isn't really much of an issue (I just prefer to compile all my code ansi-strict, just a habit).
If you're looking of ways to extend this, you could add loaders for cube (and possibly sphere and dual-paraboloid) environment maps =)

Great work! I'll definitely be using this for my projects.

Thanks! OK, I cleaned up the C++ style comments and the malloc/free casts (in SOIL proper, I'm pretty much leaving the stb_image code alone, sorry). I also put in the include for glx.h for *nix extension loading (now I just need to verify on Apple!)

I'm also adding in a function for loading 6 images into a cube map texture. After that is working, I'll extend the DDS loader to handle cube map loading so you can do a direct load of DDS cube map files. Adding these features will probably take a while, between my limited time right now and possible code complexity (I haven't actually used cube maps before, so it may be easy, I just don't know).

As to sphere maps, doesn't OpenGL just load them as regular textures, then you use the appropriate texture generation mode? I haven't used sphere maps either, but that seems to be something you would actually enable/set-up outside of SOIL. Please let me know if I'm wrong, and thanks for the feedback and suggestions!



#17 Kylotan   Moderators   -  Reputation: 3324

Like
0Likes
Like

Posted 22 August 2007 - 01:19 AM

Quote:
Original post by lonesock

Quote:
Original post by Kylotan
Just a thought though; how good is the mip-map generation algorithm? Someone might want something better than the typical bilinear filtering. (eg. bicubic)

Hmm, I cheat. If the user wants MIPmaps, I force the image to be a power-of-two size (upsizing it if necessary using simple bilinear sampling). Then for each MIPmap I do a simple average over the appropriate block. So for MIPmap 1, each pixel is an average over the associated 2x2 block. For MIPmap 2, each pixel is an average over 4x4 blocks, etc. I do this to try to keep from propagating errors at each level (i.e. I build MIP 2 from MIP 0, not just from MIP 1).

If you have any links pointing to literature on the proper / better / best way to do MIPmaps, I'd be more than happy to implement a different method.


Yeah, that average is just a typical box filter, and is fine in most cases. It's what gluBuild2DMipmaps() uses, apparently. There's a little more info here but thinking about it, it's probably not a big deal, as long as people can still generate their own mipmaps if they need to.

#18 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 22 August 2007 - 01:18 PM

Some SOIL updates:
* can now load 6 faces into a cube map (needs testing)
* can now compress 1 or 2 channel images to DXT1/5 (before it would just leave them uncompressed)
* can hopefully compile/work under *nix and Mac (please let me know if there is anything more I need to fix...I don't have access to these platforms right now)

Upcoming:
* ability to load uncompressed and cube map DDS files

Quote:
Original post by Kylotan
Yeah, that average is just a typical box filter, and is fine in most cases. It's what gluBuild2DMipmaps() uses, apparently. There's a little more info here but thinking about it, it's probably not a big deal, as long as people can still generate their own mipmaps if they need to.

SOIL is mostly about raw image loading/saving, and having a dirt-simple path for uploading image files to OpenGL textures...if what I'm doing is the common standard I'll probably just keep it as is. Thanks for the info and feedback.

#19 DeathCarrot   Members   -  Reputation: 188

Like
0Likes
Like

Posted 23 August 2007 - 09:13 PM

Great stuff =D

Got around to trying the cube map importing, and it works wonderfully (I'm at work now and I only have windows to play around with here, but I guess there's nothing new enough for it to not work on *nix).

If anyone hasn't used cube maps before and wants to try it out but doesn't want to go hunting for tutorials for how to bind them, get 6 cube maps, load them using SOIL:

tex = SOIL_load_OGL_cubemap(
"tex/xp.bmp",
"tex/xn.bmp",
"tex/yp.bmp",
"tex/yn.bmp",
"tex/zp.bmp",
"tex/zn.bmp",
0,0,SOIL_FLAG_MIPMAPS
);

And bind:

glEnable(GL_TEXTURE_CUBE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);

Easy as pie =)



#20 lonesock   Members   -  Reputation: 799

Like
0Likes
Like

Posted 24 August 2007 - 05:15 AM

Quote:
Original post by DeathCarrot
If anyone hasn't used cube maps before and wants to try it out but doesn't want to go hunting for tutorials for how to bind them, get 6 cube maps, load them using SOIL:
...
Easy as pie =)

You rock!

I've updated the website a bit, especially the usage examples...so now it's easier to see what SOIL can do. (note that the 'SOIL_CREATE_NEW_ID' enum is new, and not in the uploaded source yet, but it is just = 0. I will be uploading a new version in a bit, once I finish a few things on the TODO list)




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS