Last active
December 13, 2025 10:49
-
-
Save moomerman/2009445e6ee4ca59e9eafce511f29f7d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* stb_image - v2.30 - public domain image loader - http://nothings.org/stb | |
| no warranty implied; use at your own risk | |
| Do this: | |
| #define STB_IMAGE_IMPLEMENTATION | |
| before you include this file in *one* C or C++ file to create the implementation. | |
| // i.e. it should look like this: | |
| #include ... | |
| #include ... | |
| #include ... | |
| #define STB_IMAGE_IMPLEMENTATION | |
| #include "stb_image.h" | |
| You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. | |
| And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free | |
| QUICK NOTES: | |
| Primarily of interest to game developers and other people who can | |
| avoid problematic images and only need the trivial interface | |
| JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) | |
| PNG 1/2/4/8/16-bit-per-channel | |
| TGA (not sure what subset, if a subset) | |
| BMP non-1bpp, non-RLE | |
| PSD (composited view only, no extra channels, 8/16 bit-per-channel) | |
| GIF (*comp always reports as 4-channel) | |
| HDR (radiance rgbE format) | |
| PIC (Softimage PIC) | |
| PNM (PPM and PGM binary only) | |
| Animated GIF still needs a proper API, but here's one way to do it: | |
| http://gist.github.com/urraka/685d9a6340b26b830d49 | |
| - decode from memory or through FILE (define STBI_NO_STDIO to remove code) | |
| - decode from arbitrary I/O callbacks | |
| - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) | |
| Full documentation under "DOCUMENTATION" below. | |
| LICENSE | |
| See end of file for license information. | |
| RECENT REVISION HISTORY: | |
| 2.30 (2024-05-31) avoid erroneous gcc warning | |
| 2.29 (2023-05-xx) optimizations | |
| 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff | |
| 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes | |
| 2.26 (2020-07-13) many minor fixes | |
| 2.25 (2020-02-02) fix warnings | |
| 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically | |
| 2.23 (2019-08-11) fix clang static analysis warning | |
| 2.22 (2019-03-04) gif fixes, fix warnings | |
| 2.21 (2019-02-25) fix typo in comment | |
| 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs | |
| 2.19 (2018-02-11) fix warning | |
| 2.18 (2018-01-30) fix warnings | |
| 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings | |
| 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes | |
| 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC | |
| 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs | |
| 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes | |
| 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes | |
| 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 | |
| RGB-format JPEG; remove white matting in PSD; | |
| allocate large structures on the stack; | |
| correct channel count for PNG & BMP | |
| 2.10 (2016-01-22) avoid warning introduced in 2.09 | |
| 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED | |
| See end of file for full revision history. | |
| ============================ Contributors ========================= | |
| Image formats Extensions, features | |
| Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) | |
| Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) | |
| Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) | |
| Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) | |
| Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) | |
| Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) | |
| Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) | |
| github:urraka (animated gif) Junggon Kim (PNM comments) | |
| Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) | |
| socks-the-fox (16-bit PNG) | |
| Jeremy Sawicki (handle all ImageNet JPGs) | |
| Optimizations & bugfixes Mikhail Morozov (1-bit BMP) | |
| Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) | |
| Arseny Kapoulkine Simon Breuss (16-bit PNM) | |
| John-Mark Allen | |
| Carmelo J Fdez-Aguera | |
| Bug & warning fixes | |
| Marc LeBlanc David Woo Guillaume George Martins Mozeiko | |
| Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski | |
| Phil Jordan Dave Moore Roy Eltham | |
| Hayaki Saito Nathan Reed Won Chun | |
| Luke Graham Johan Duparc Nick Verigakis the Horde3D community | |
| Thomas Ruf Ronny Chevalier github:rlyeh | |
| Janez Zemva John Bartholomew Michal Cichon github:romigrou | |
| Jonathan Blow Ken Hamada Tero Hanninen github:svdijk | |
| Eugene Golushkov Laurent Gomila Cort Stratton github:snagar | |
| Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex | |
| Cass Everitt Ryamond Barbiero github:grim210 | |
| Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw | |
| Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus | |
| Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo | |
| Julian Raschke Gregory Mullen Christian Floisand github:darealshinji | |
| Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 | |
| Brad Weinberger Matvey Cherevko github:mosra | |
| Luca Sas Alexander Veselov Zack Middleton [reserved] | |
| Ryan C. Gordon [reserved] [reserved] | |
| DO NOT ADD YOUR NAME HERE | |
| Jacko Dirks | |
| To add your name to the credits, pick a random blank space in the middle and fill it. | |
| 80% of merge conflicts on stb PRs are due to people adding their name at the end | |
| of the credits. | |
| */ | |
| module stb_image::stbi; | |
| const int STBI_VERSION = 1; | |
| const int STBI_DEFAULT = 0; | |
| const int STBI_GREY_ALPHA = 2; | |
| const int STBI_GREY = 1; | |
| const int STBI_RGB = 3; | |
| const int STBI_RGB_ALPHA = 4; | |
| // | |
| // load image by filename, open file, or memory buffer | |
| // | |
| alias StbiIoCallbacksReadFn = fn int(void*, ZString, int); | |
| alias StbiIoCallbacksSkipFn = fn void(void*, int); | |
| alias StbiIoCallbacksEofFn = fn int(void*); | |
| struct StbiIoCallbacks | |
| { | |
| StbiIoCallbacksReadFn read; // fill 'data' with 'size' bytes. return number of bytes actually read | |
| StbiIoCallbacksSkipFn skip; // skip the next 'n' bytes, or 'unget' the last -n bytes if negative | |
| StbiIoCallbacksEofFn eof; // returns nonzero if we are at end of file/data | |
| } | |
| // | |
| // load image by filename, open file, or memory buffer | |
| // | |
| //////////////////////////////////// | |
| // | |
| // 8-bits-per-channel interface | |
| // | |
| extern fn char* load_from_memory(char* buffer, int len, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_load_from_memory"); | |
| extern fn char* load_from_callbacks(StbiIoCallbacks* clbk, void* user, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_load_from_callbacks"); | |
| extern fn char* load(ZString filename, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_load"); | |
| extern fn char* load_from_file(int* f, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_load_from_file"); | |
| extern fn char* load_gif_from_memory(char* buffer, int len, int** delays, int* x, int* y, int* z, int* comp, int req_comp) @cname("stbi_load_gif_from_memory"); | |
| //////////////////////////////////// | |
| // | |
| // 16-bits-per-channel interface | |
| // | |
| extern fn ushort* load_16_from_memory(char* buffer, int len, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_load_16_from_memory"); | |
| extern fn ushort* load_16_from_callbacks(StbiIoCallbacks* clbk, void* user, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_load_16_from_callbacks"); | |
| extern fn ushort* load_16(ZString filename, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_load_16"); | |
| extern fn ushort* load_from_file_16(int* f, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_load_from_file_16"); | |
| extern fn float* loadf_from_memory(char* buffer, int len, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_loadf_from_memory"); | |
| extern fn float* loadf_from_callbacks(StbiIoCallbacks* clbk, void* user, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_loadf_from_callbacks"); | |
| extern fn float* loadf(ZString filename, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_loadf"); | |
| extern fn float* loadf_from_file(int* f, int* x, int* y, int* channels_in_file, int desired_channels) @cname("stbi_loadf_from_file"); | |
| extern fn void hdr_to_ldr_gamma(float gamma) @cname("stbi_hdr_to_ldr_gamma"); | |
| extern fn void hdr_to_ldr_scale(float scale) @cname("stbi_hdr_to_ldr_scale"); | |
| extern fn void ldr_to_hdr_gamma(float gamma) @cname("stbi_ldr_to_hdr_gamma"); | |
| extern fn void ldr_to_hdr_scale(float scale) @cname("stbi_ldr_to_hdr_scale"); | |
| // stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR | |
| extern fn int is_hdr_from_callbacks(StbiIoCallbacks* clbk, void* user) @cname("stbi_is_hdr_from_callbacks"); | |
| extern fn int is_hdr_from_memory(char* buffer, int len) @cname("stbi_is_hdr_from_memory"); | |
| extern fn int is_hdr(ZString filename) @cname("stbi_is_hdr"); | |
| extern fn int is_hdr_from_file(int* f) @cname("stbi_is_hdr_from_file"); | |
| // get a VERY brief reason for failure | |
| // on most compilers (and ALL modern mainstream compilers) this is threadsafe | |
| extern fn ZString failure_reason() @cname("stbi_failure_reason"); | |
| // free the loaded image -- this is just free() | |
| extern fn void image_free(void* retval_from_stbi_load) @cname("stbi_image_free"); | |
| // get image dimensions & components without fully decoding | |
| extern fn int info_from_memory(char* buffer, int len, int* x, int* y, int* comp) @cname("stbi_info_from_memory"); | |
| extern fn int info_from_callbacks(StbiIoCallbacks* clbk, void* user, int* x, int* y, int* comp) @cname("stbi_info_from_callbacks"); | |
| extern fn int is_16_bit_from_memory(char* buffer, int len) @cname("stbi_is_16_bit_from_memory"); | |
| extern fn int is_16_bit_from_callbacks(StbiIoCallbacks* clbk, void* user) @cname("stbi_is_16_bit_from_callbacks"); | |
| extern fn int info(ZString filename, int* x, int* y, int* comp) @cname("stbi_info"); | |
| extern fn int info_from_file(int* f, int* x, int* y, int* comp) @cname("stbi_info_from_file"); | |
| extern fn int is_16_bit(ZString filename) @cname("stbi_is_16_bit"); | |
| extern fn int is_16_bit_from_file(int* f) @cname("stbi_is_16_bit_from_file"); | |
| // for image formats that explicitly notate that they have premultiplied alpha, | |
| // we just return the colors as stored in the file. set this flag to force | |
| // unpremultiplication. results are undefined if the unpremultiply overflow. | |
| extern fn void set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) @cname("stbi_set_unpremultiply_on_load"); | |
| // indicate whether we should process iphone images back to canonical format, | |
| // or just pass them through "as-is" | |
| extern fn void convert_iphone_png_to_rgb(int flag_true_if_should_convert) @cname("stbi_convert_iphone_png_to_rgb"); | |
| // flip the image vertically, so the first pixel in the output array is the bottom left | |
| extern fn void set_flip_vertically_on_load(int flag_true_if_should_flip) @cname("stbi_set_flip_vertically_on_load"); | |
| // as above, but only applies to images loaded on the thread that calls the function | |
| // this function is only available if your compiler supports thread-local variables; | |
| // calling it will fail to link if your compiler doesn't | |
| extern fn void set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) @cname("stbi_set_unpremultiply_on_load_thread"); | |
| extern fn void convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) @cname("stbi_convert_iphone_png_to_rgb_thread"); | |
| extern fn void set_flip_vertically_on_load_thread(int flag_true_if_should_flip) @cname("stbi_set_flip_vertically_on_load_thread"); | |
| // ZLIB client - used by PNG, available for other purposes | |
| extern fn ZString zlib_decode_malloc_guesssize(ZString buffer, int len, int initial_size, int* outlen) @cname("stbi_zlib_decode_malloc_guesssize"); | |
| extern fn ZString zlib_decode_malloc_guesssize_headerflag(ZString buffer, int len, int initial_size, int* outlen, int parse_header) @cname("stbi_zlib_decode_malloc_guesssize_headerflag"); | |
| extern fn ZString zlib_decode_malloc(ZString buffer, int len, int* outlen) @cname("stbi_zlib_decode_malloc"); | |
| extern fn int zlib_decode_buffer(ZString obuffer, int olen, ZString ibuffer, int ilen) @cname("stbi_zlib_decode_buffer"); | |
| extern fn ZString zlib_decode_noheader_malloc(ZString buffer, int len, int* outlen) @cname("stbi_zlib_decode_noheader_malloc"); | |
| extern fn int zlib_decode_noheader_buffer(ZString obuffer, int olen, ZString ibuffer, int ilen) @cname("stbi_zlib_decode_noheader_buffer"); | |
| // Idiomatic C3 wrapper macros for stb_image | |
| // These provide optional-based error handling for a more C3-native feel | |
| faultdef IMAGE_LOAD_FAILED, IMAGE_INFO_FAILED; | |
| // Load an image file, returning an optional that fails on error | |
| macro char*? load_image(ZString filename, int* x, int* y, int* channels_in_file, int desired_channels = 0) | |
| { | |
| char* res = load(filename, x, y, channels_in_file, desired_channels); | |
| if (!res) return IMAGE_LOAD_FAILED?; | |
| return res; | |
| } | |
| // Load a 16-bit image file, returning an optional that fails on error | |
| macro ushort*? load_image_16(ZString filename, int* x, int* y, int* channels_in_file, int desired_channels = 0) | |
| { | |
| ushort* res = load_16(filename, x, y, channels_in_file, desired_channels); | |
| if (!res) return IMAGE_LOAD_FAILED?; | |
| return res; | |
| } | |
| // Load an HDR image file, returning an optional that fails on error | |
| macro float*? load_imagef(ZString filename, int* x, int* y, int* channels_in_file, int desired_channels = 0) | |
| { | |
| float* res = loadf(filename, x, y, channels_in_file, desired_channels); | |
| if (!res) return IMAGE_LOAD_FAILED?; | |
| return res; | |
| } | |
| // Load image from memory buffer, returning an optional that fails on error | |
| macro char*? load_image_from_memory(char[] buffer, int* x, int* y, int* channels_in_file, int desired_channels = 0) | |
| { | |
| char* res = load_from_memory(buffer.ptr, (int)buffer.len, x, y, channels_in_file, desired_channels); | |
| if (!res) return IMAGE_LOAD_FAILED?; | |
| return res; | |
| } | |
| // Load 16-bit image from memory buffer, returning an optional that fails on error | |
| macro ushort*? load_image_16_from_memory(char[] buffer, int* x, int* y, int* channels_in_file, int desired_channels = 0) | |
| { | |
| ushort* res = load_16_from_memory(buffer.ptr, (int)buffer.len, x, y, channels_in_file, desired_channels); | |
| if (!res) return IMAGE_LOAD_FAILED?; | |
| return res; | |
| } | |
| // Load HDR image from memory buffer, returning an optional that fails on error | |
| macro float*? load_imagef_from_memory(char[] buffer, int* x, int* y, int* channels_in_file, int desired_channels = 0) | |
| { | |
| float* res = loadf_from_memory(buffer.ptr, (int)buffer.len, x, y, channels_in_file, desired_channels); | |
| if (!res) return IMAGE_LOAD_FAILED?; | |
| return res; | |
| } | |
| // Get image info without loading, returning an optional that fails on error | |
| macro void? get_info(ZString filename, int* x, int* y, int* comp) | |
| { | |
| int result = info(filename, x, y, comp); | |
| if (result == 0) return IMAGE_INFO_FAILED?; | |
| } | |
| // Get image info from memory without loading, returning an optional that fails on error | |
| macro void? get_info_from_memory(char[] buffer, int* x, int* y, int* comp) | |
| { | |
| int result = info_from_memory(buffer.ptr, (int)buffer.len, x, y, comp); | |
| if (result == 0) return IMAGE_INFO_FAILED?; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Test program for stb_image C3 bindings | |
| // Compile with: c3c compile test_stb_image.c3 ../stb_image/stb_image.c3 stb_image_impl.o | |
| module test_stb_image; | |
| import std::io; | |
| import stb_image::stbi; | |
| fn int main() | |
| { | |
| io::printn("=== stb_image Bindings Test ===\n"); | |
| // Test constants | |
| io::printfn("STBI_VERSION = %d", stbi::STBI_VERSION); | |
| io::printfn("STBI_DEFAULT = %d", stbi::STBI_DEFAULT); | |
| io::printfn("STBI_GREY = %d", stbi::STBI_GREY); | |
| io::printfn("STBI_GREY_ALPHA = %d", stbi::STBI_GREY_ALPHA); | |
| io::printfn("STBI_RGB = %d", stbi::STBI_RGB); | |
| io::printfn("STBI_RGB_ALPHA = %d", stbi::STBI_RGB_ALPHA); | |
| // Test struct size (verify StbiIoCallbacks compiles correctly) | |
| io::printfn("\nStruct sizes:"); | |
| io::printfn(" StbiIoCallbacks size: %d bytes", (int)stbi::StbiIoCallbacks.sizeof); | |
| // Test basic types (aliases StbiUc and StbiUs were suppressed per C3 creator feedback) | |
| io::printfn("\nBasic type sizes:"); | |
| io::printfn(" char size: %d bytes", (int)char.sizeof); | |
| io::printfn(" ushort size: %d bytes", (int)ushort.sizeof); | |
| // Test calling a simple function - get failure reason (should be null/empty initially) | |
| io::printn("\nTesting function calls:"); | |
| ZString reason = stbi::failure_reason(); | |
| if (reason != null) | |
| { | |
| io::printfn(" Initial failure reason: %s", reason); | |
| } | |
| else | |
| { | |
| io::printn(" Initial failure reason: (none)"); | |
| } | |
| // ========================================= | |
| // Test idiomatic C3 wrapper macros | |
| // ========================================= | |
| io::printn("\n=== Testing Idiomatic C3 Wrappers ===\n"); | |
| // Test get_info with non-existent file using optional error handling | |
| io::printn("Testing stbi::get_info with non-existent file:"); | |
| int x, y, comp; | |
| if (catch err = stbi::get_info("nonexistent.png", &x, &y, &comp)) | |
| { | |
| io::printfn(" Got expected error: %s", err); | |
| io::printfn(" Failure reason: %s", stbi::failure_reason()); | |
| } | |
| else | |
| { | |
| io::printn(" ERROR: Should have failed!"); | |
| return 1; | |
| } | |
| // Test load_image with non-existent file using optional error handling | |
| io::printn("\nTesting stbi::load_image with non-existent file:"); | |
| int img_x, img_y, img_channels; | |
| if (catch err = stbi::load_image("nonexistent.jpg", &img_x, &img_y, &img_channels)) | |
| { | |
| io::printfn(" Got expected error: %s", err); | |
| io::printfn(" Failure reason: %s", stbi::failure_reason()); | |
| } | |
| else | |
| { | |
| io::printn(" ERROR: Should have failed!"); | |
| return 1; | |
| } | |
| // Test load_image with actual file - success case | |
| io::printn("\nTesting stbi::load_image with snoopy.jpg (idiomatic style):"); | |
| if (try image_data = stbi::load_image("snoopy.jpg", &img_x, &img_y, &img_channels)) | |
| { | |
| io::printfn(" Successfully loaded snoopy.jpg!"); | |
| io::printfn(" Width: %d pixels", img_x); | |
| io::printfn(" Height: %d pixels", img_y); | |
| io::printfn(" Channels: %d", img_channels); | |
| io::printfn(" Total pixels: %d", img_x * img_y); | |
| io::printfn(" Data size: %d bytes", img_x * img_y * img_channels); | |
| // Free the image data | |
| stbi::image_free(image_data); | |
| io::printn(" Image data freed successfully."); | |
| } | |
| else | |
| { | |
| io::printfn(" ERROR: Failed to load snoopy.jpg: %s", stbi::failure_reason()); | |
| return 1; | |
| } | |
| // Test get_info on the same image - success case | |
| io::printn("\nTesting stbi::get_info with snoopy.jpg (idiomatic style):"); | |
| int info_x, info_y, info_comp; | |
| if (catch err = stbi::get_info("snoopy.jpg", &info_x, &info_y, &info_comp)) | |
| { | |
| io::printfn(" ERROR: get_info failed: %s", stbi::failure_reason()); | |
| return 1; | |
| } | |
| io::printfn(" Info reports: %dx%d, %d channels", info_x, info_y, info_comp); | |
| // Verify info matches what we got from load | |
| if (info_x == img_x && info_y == img_y && info_comp == img_channels) | |
| { | |
| io::printn(" Info matches loaded image dimensions!"); | |
| } | |
| else | |
| { | |
| io::printn(" WARNING: Info doesn't match loaded dimensions"); | |
| } | |
| // ========================================= | |
| // Compare with raw bindings style | |
| // ========================================= | |
| io::printn("\n=== Comparison: Raw Bindings Style ===\n"); | |
| io::printn("Testing raw stbi::load (for comparison):"); | |
| int raw_x, raw_y, raw_channels; | |
| char* raw_data = stbi::load("snoopy.jpg", &raw_x, &raw_y, &raw_channels, 0); | |
| if (raw_data != null) | |
| { | |
| io::printfn(" Loaded: %dx%d, %d channels", raw_x, raw_y, raw_channels); | |
| stbi::image_free(raw_data); | |
| io::printn(" Freed successfully."); | |
| } | |
| else | |
| { | |
| io::printfn(" ERROR: %s", stbi::failure_reason()); | |
| return 1; | |
| } | |
| io::printn("\n=== All binding tests passed! ==="); | |
| return 0; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
=== stb_image Bindings Test ===
STBI_VERSION = 1
STBI_DEFAULT = 0
STBI_GREY = 1
STBI_GREY_ALPHA = 2
STBI_RGB = 3
STBI_RGB_ALPHA = 4
Struct sizes:
StbiIoCallbacks size: 24 bytes
Basic type sizes:
char size: 1 bytes
ushort size: 2 bytes
Testing function calls:
Initial failure reason: (none)
=== Testing Idiomatic C3 Wrappers ===
Testing stbi::get_info with non-existent file:
Got expected error: stbi::IMAGE_INFO_FAILED
Failure reason: can't fopen
Testing stbi::load_image with non-existent file:
Got expected error: stbi::IMAGE_LOAD_FAILED
Failure reason: can't fopen
Testing stbi::load_image with snoopy.jpg (idiomatic style):
Successfully loaded snoopy.jpg!
Width: 180 pixels
Height: 101 pixels
Channels: 3
Total pixels: 18180
Data size: 54540 bytes
Image data freed successfully.
Testing stbi::get_info with snoopy.jpg (idiomatic style):
Info reports: 180x101, 3 channels
Info matches loaded image dimensions!
=== Comparison: Raw Bindings Style ===
Testing raw stbi::load (for comparison):
Loaded: 180x101, 3 channels
Freed successfully.
=== All binding tests passed! ===