Loading images with STB
Almost every graphics application requires texture images to be loaded from files in some image file formats. Let's take a look at the STB image loader and discuss how we can use it to support popular formats, such as .jpeg
, .png
, and a floating point format .hdr
for high dynamic range texture data.
Getting ready
The STB project consists of multiple header-only libraries. The entire up-to-date package can be downloaded from https://github.com/nothings/stb:
{ "name": "stb", "source": { "type": "git", "url": "https://github.com/nothings/stb.git", "revision": "c9064e317699d2e495f36ba4f9ac037e88ee371a" } }
The demo source code for this recipe can be found in Chapter2/03_STB
.
How to do it...
Let's add texture mapping to the previous recipe. Perform the following steps:
- The STB library has separate headers for loading and saving images. Both can be included within your project, as follows:
#define STB_IMAGE_IMPLEMENTATION #include <stb/stb_image.h> #define STB_IMAGE_WRITE_IMPLEMENTATION #include <stb/stb_image_write.h>
- To load an image as a 3-channel RGB image from any supported graphics file format, use this short code snippet:
int w, h, comp; const uint8_t* img = stbi_load( "data/ch2_sample3_STB.jpg", &w, &h, &comp, 3);
- Besides that, we can save images into various image file formats. Here is a snippet that enables you to save a screenshot from an OpenGL GLFW application:
int width, height; glfwGetFramebufferSize(window, &width, &height); uint8_t* ptr = (uint8_t*)malloc(width * height * 4); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptr); stbi_write_png( "screenshot.png", width, height, 4, ptr, 0); free(ptr);
Please check
stb_image.h
andstb_image_write.h
for a list of supported file formats. - The loaded
img
image can be used as an OpenGL texture in a DSA fashion, as follows:GLuint texture; glCreateTextures(GL_TEXTURE_2D, 1, &texture); glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, 0); glTextureParameteri( texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTextureParameteri( texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTextureStorage2D(texture, 1, GL_RGB8, w, h); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTextureSubImage2D(texture, 0, 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, img); glBindTextures(0, 1, &texture);
Please refer to the source code in Chapter2/03_STB
for a complete working example and the GLSL shader changes that are necessary to apply the texture to our cube.
There's more...
STB supports the loading of high-dynamic-range images in Radiance .HDR
file format. Use the stbi_loadf()
function to load files as floating-point images. This will preserve the full dynamic range of the image and will be useful to load high-dynamic-range light probes for physically-based lighting in the Chapter 6, Physically Based Rendering Using the glTF2 Shading Model.