Skip to content

Practice 01 Loading Images

squid233 edited this page Feb 1, 2024 · 4 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 = stbImage.load("Local.png", pw, ph, pc, STBImage.RGB_ALPHA);
gl.texImage2D(..., img);
stbImage.free(img);

or

try (var stack = MemoryStack.stackPush()) {
    var pw = stack.malloc(JAVA_INT);
    var ph = stack.malloc(JAVA_INT);
    var pc = stack.malloc(JAVA_INT);
    var img = stbImage.load("Local.png", pw, ph, pc, STBImage.RGB_ALPHA);
    gl.texImage2D(..., img);
    stbImage.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::free);

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

Note that you always need to use STBImage::free to release the memory, because OverrunGL doesn't track it in the debug allocator.

Using BufferedImage (Not Recommended)

Using BufferedImage to load images on classpath is easier than STB, but seems like slower.

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