Skip to content

Practice 01 Loading Images

squid233 edited this page Jan 3, 2025 · 5 revisions

We often need to load images such as creating a textures. There are 2 methods to do it.

Using STB

Using STB to load images is very easy.

// ref pw, ph, pc for width, height and components
int[] pw = new int[1], ph = new int[1], pc = new int[1];
var img = stbi_load("Local.png", pw, ph, pc, STBI_rgb_alpha);
gl.TexImage2D(..., img);
stbi_image_free(img);

or

try (var stack = MemoryStack.pushLocal()) {
    var pw = stack.allocate(JAVA_INT);
    var ph = stack.allocate(JAVA_INT);
    var pc = stack.allocate(JAVA_INT);
    var img = stbi_load("Local.png", pw, ph, pc, STBI_rgb_alpha);
    gl.TexImage2D(..., img);
    stbi_image_free(img);
}

You should check if the result data is NULL or not. If it is NULL, print the failure reason.

A best practice is to reassociate the result data with an arena and a cleanup action.

img = load(...).reinterpret(arena, STBImage::stbi_image_free);

To load images on classpath, check Practice 02 and use STBImage::stbi_load_from_memory.

Note that you can use STBImage::stbi_image_free or MemoryUtil::free to release the memory.

Using BufferedImage

Using BufferedImage to load images on classpath is easier than STB, but might be slower since it loads AWT.

Note: It's default little-endian in C, so if you use RGBA type of C functions, the array must be reordered in ABGR.

// Get input stream
try (var is = ClassLoader.getSystemResourceAsStream("Classpath.png")) {
    var img = ImageIO.read(is);
    // ---
    // 1. GL_RGBA
    int[] arr = img.getRGB(0, 0, w, h, new int[w * h], 0, w);
    // Convert to ABGR
    for (int i = 0; i < arr.length; i++) {
        int a = arr[i] >> 24 & 0xff;
        int r = arr[i] >> 16 & 0xff;
        int g = arr[i] >> 8 & 0xff;
        int b = arr[i] & 0xff;
        arr[i] = a << 24 | b << 16 | g << 8 | r;
    }
    gl.TexImage2D(..., GL_RGBA, arr);
    // ---
    // 2. GL_BGRA
    int[] arr = img.getRGB(0, 0, w, h, new int[w * h], 0, w);
    // Required order is ARGB so no need to re-order
    gl.TexImage2D(..., GL_BGRA, arr);
}
Clone this wiki locally