mirror of
https://github.com/haya3218/SDfmL.git
synced 2024-08-14 23:57:09 +00:00
Can out SDL_image and replace with stb_image
Less dlls poyo https://github.com/DanielGibson/Snippets/blob/master/SDL_stbimage.h
This commit is contained in:
parent
b9702710b7
commit
0e100c06b8
8 changed files with 8573 additions and 12 deletions
|
@ -12,10 +12,10 @@ set(OUT3_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/src/toml/")
|
||||||
|
|
||||||
# Support both 32 and 64 bit builds
|
# Support both 32 and 64 bit builds
|
||||||
if (${CMAKE_SIZEOF_VOID_P} MATCHES 8)
|
if (${CMAKE_SIZEOF_VOID_P} MATCHES 8)
|
||||||
set(MAIN_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x64/soloud_static.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2main.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2_image.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2_ttf.lib")
|
set(MAIN_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x64/soloud_static.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2main.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2_ttf.lib")
|
||||||
set(MAIN_LIBRARIES_E "${CMAKE_CURRENT_LIST_DIR}/lib/x64/")
|
set(MAIN_LIBRARIES_E "${CMAKE_CURRENT_LIST_DIR}/lib/x64/")
|
||||||
else ()
|
else ()
|
||||||
set(MAIN_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x86/soloud_static.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2main.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2_image.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2_ttf.lib")
|
set(MAIN_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x86/soloud_static.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2main.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2_ttf.lib")
|
||||||
set(MAIN_LIBRARIES_E "${CMAKE_CURRENT_LIST_DIR}/lib/x86/")
|
set(MAIN_LIBRARIES_E "${CMAKE_CURRENT_LIST_DIR}/lib/x86/")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
@ -106,7 +106,6 @@ file(COPY ${MAIN_LIBRARIES_E} DESTINATION ${BUILD_DIRECTORY})
|
||||||
# remove lib files
|
# remove lib files
|
||||||
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/*.lib")
|
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/*.lib")
|
||||||
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/SDL2.lib")
|
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/SDL2.lib")
|
||||||
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/SDL2_image.lib")
|
|
||||||
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/SDL2_ttf.lib")
|
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/SDL2_ttf.lib")
|
||||||
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/SDL2main.lib")
|
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/SDL2main.lib")
|
||||||
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/SDL2test.lib")
|
file(REMOVE_RECURSE "${BUILD_DIRECTORY}/SDL2test.lib")
|
||||||
|
|
BIN
resources/dialog.res
Normal file
BIN
resources/dialog.res
Normal file
Binary file not shown.
27
resources/version.rc
Normal file
27
resources/version.rc
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
1 VERSIONINFO
|
||||||
|
FILEVERSION 0,1,2,1
|
||||||
|
PRODUCTVERSION 0,1,2,1
|
||||||
|
FILEOS 0x40004
|
||||||
|
FILETYPE 0x1
|
||||||
|
{
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
{
|
||||||
|
BLOCK "040904B0"
|
||||||
|
{
|
||||||
|
VALUE "FileDescription", "dumb"
|
||||||
|
VALUE "InternalName", "SDfmL.exe"
|
||||||
|
VALUE "OriginalFilename", "Skateboard.exe"
|
||||||
|
VALUE "CompanyName", "no one"
|
||||||
|
VALUE "LegalCopyright", "no one"
|
||||||
|
VALUE "ProductName", "SDfmL"
|
||||||
|
VALUE "FileVersion", "0.1.2.1"
|
||||||
|
VALUE "ProductVersion", "0.1.2.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
{
|
||||||
|
VALUE "Translation", 0x0409 0x04B0
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
#define SDL_MAIN_HANDLED // needs to be here or linker fucking dies
|
#define SDL_MAIN_HANDLED // needs to be here or linker fucking dies
|
||||||
|
#define SDL_STBIMAGE_IMPLEMENTATION
|
||||||
#undef _HAS_STD_BYTE
|
#undef _HAS_STD_BYTE
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "SDL2/SDL.h"
|
#include "SDL2/SDL.h"
|
||||||
|
@ -22,7 +23,7 @@ class MainState : public State {
|
||||||
// to override a function, just state back the name of it with a virtual keyword
|
// to override a function, just state back the name of it with a virtual keyword
|
||||||
// before it
|
// before it
|
||||||
virtual void Create() {
|
virtual void Create() {
|
||||||
SPEAK("Welcome, to es dee eff emm L. A stupid fucking wrapper for ess dee L 2. Get over it, bitch", 3000.0f, 6.5f);
|
// SPEAK("eyeyeyayeyayeyaeyaeyayeayeyaeyaeyayeyaeyayeyayeyayeyayeaye", 3000.0f, 5.0f);
|
||||||
playModPlug("data/canyon.mid");
|
playModPlug("data/canyon.mid");
|
||||||
// i know that this isnt the best idea to do this
|
// i know that this isnt the best idea to do this
|
||||||
// yeah, im just lazy
|
// yeah, im just lazy
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "SDL2/SDL.h"
|
#include "SDL2/SDL.h"
|
||||||
#include "SDL2/SDL_image.h"
|
|
||||||
#include "SDL2/SDL_ttf.h"
|
#include "SDL2/SDL_ttf.h"
|
||||||
#include "Render.hpp"
|
#include "Render.hpp"
|
||||||
#include "SDL2/SDL_syswm.h"
|
#include "SDL2/SDL_syswm.h"
|
||||||
|
@ -18,6 +17,8 @@
|
||||||
#include "SoLoud/soloud_openmpt.h"
|
#include "SoLoud/soloud_openmpt.h"
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include "SDL2/SDL_stbimage.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <winuser.h>
|
#include <winuser.h>
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ Render::State::~State() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render::Object::create(int x, int y, string path){
|
void Render::Object::create(int x, int y, string path){
|
||||||
this->_tex = IMG_LoadTexture(renderer, path.c_str());
|
this->_tex = STBIMG_LoadTexture(renderer, path.c_str());
|
||||||
SDL_SetTextureBlendMode(_tex, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(_tex, SDL_BLENDMODE_BLEND);
|
||||||
if (_tex == nullptr) {
|
if (_tex == nullptr) {
|
||||||
cout << "texture failed to lod" << endl;
|
cout << "texture failed to lod" << endl;
|
||||||
|
@ -231,11 +232,6 @@ bool Render::Init(string window_name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
log("SDL", " has been successfully initialized.", NORMAL, __FILENAME__, __LINE__);
|
log("SDL", " has been successfully initialized.", NORMAL, __FILENAME__, __LINE__);
|
||||||
if (IMG_Init(IMG_INIT_PNG) == 0) {
|
|
||||||
log("SDL_image", " has failed to load. Is your dll broken? " + string(SDL_GetError()), ERROR_, __FILENAME__, __LINE__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
log("SDL_image", " has been successfully initialized.", NORMAL, __FILENAME__, __LINE__);
|
|
||||||
if (TTF_Init() < 0) {
|
if (TTF_Init() < 0) {
|
||||||
log("SDL_ttf", " has failed to load. Is your dll broken? " + string(SDL_GetError()), ERROR_, __FILENAME__, __LINE__);
|
log("SDL_ttf", " has failed to load. Is your dll broken? " + string(SDL_GetError()), ERROR_, __FILENAME__, __LINE__);
|
||||||
return false;
|
return false;
|
||||||
|
@ -359,7 +355,6 @@ bool Render::Update() {
|
||||||
music.stopAll();
|
music.stopAll();
|
||||||
se.deinit();
|
se.deinit();
|
||||||
music.deinit();
|
music.deinit();
|
||||||
IMG_Quit();
|
|
||||||
TTF_Quit();
|
TTF_Quit();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "SoLoud/soloud_biquadresonantfilter.h"
|
#include "SoLoud/soloud_biquadresonantfilter.h"
|
||||||
#include "SoLoud/soloud_fftfilter.h"
|
#include "SoLoud/soloud_fftfilter.h"
|
||||||
|
|
||||||
|
#include "SDL2/SDL_stbimage.h"
|
||||||
|
|
||||||
#include "toml.hpp"
|
#include "toml.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
|
640
src/SDL2/SDL_stbimage.h
Normal file
640
src/SDL2/SDL_stbimage.h
Normal file
|
@ -0,0 +1,640 @@
|
||||||
|
/*
|
||||||
|
* A small header-only library to load an image into a RGB(A) SDL_Surface*,
|
||||||
|
* like a stripped down version of SDL_Image, but using stb_image.h to decode
|
||||||
|
* images and thus without any further external dependencies.
|
||||||
|
* Supports all filetypes supported by stb_image (JPEG, PNG, TGA, BMP, PSD, ...
|
||||||
|
* See stb_image.h for details).
|
||||||
|
*
|
||||||
|
* (C) 2015-2021 Daniel Gibson
|
||||||
|
*
|
||||||
|
* Homepage: https://github.com/DanielGibson/Snippets/
|
||||||
|
*
|
||||||
|
* Dependencies:
|
||||||
|
* libSDL2 http://www.libsdl.org
|
||||||
|
* stb_image.h https://github.com/nothings/stb
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* Put this file and stb_image.h somewhere in your project.
|
||||||
|
* In *one* of your .c/.cpp files, do
|
||||||
|
* #define SDL_STBIMAGE_IMPLEMENTATION
|
||||||
|
* #include "SDL_stbimage.h"
|
||||||
|
* to create the implementation of this library in that file.
|
||||||
|
* You can just #include "SDL_stbimage.h" (without the #define) in other source
|
||||||
|
* files to use it there. (See also below this comment for an usage example)
|
||||||
|
* This header implicitly #includes <SDL.h> and "stb_image.h".
|
||||||
|
*
|
||||||
|
* You can #define SDL_STBIMG_DEF before including this header if you want to
|
||||||
|
* prepend anything to the function signatures (like "static", "inline",
|
||||||
|
* "__declspec(dllexport)", ...)
|
||||||
|
* Example: #define SDL_STBIMG_DEF static inline
|
||||||
|
*
|
||||||
|
* By default, this deactivates stb_image's load from file functions via
|
||||||
|
* #define STBI_NO_STDIO, as they use stdio.h and that adds a dependency to the
|
||||||
|
* CRT on windows and with SDL you're better off using SDL_RWops, incl. SDL_RWFromFile()
|
||||||
|
* If you wanna use stbi_load(), stbi_info(), stbi_load_from_file() etc anyway, do
|
||||||
|
* #define SDL_STBIMG_ALLOW_STDIO
|
||||||
|
* before including this header.
|
||||||
|
* (Note that all the STBIMG_* functions of this lib will work without it)
|
||||||
|
*
|
||||||
|
* stb_image.h uses assert.h by default. You can #define STBI_ASSERT(x)
|
||||||
|
* before the implementation-#include of SDL_stbimage.h to avoid that.
|
||||||
|
* By default stb_image supports HDR images, for that it needs pow() from libm.
|
||||||
|
* If you don't need HDR (it can't be loaded into a SDL_Surface anyway),
|
||||||
|
* #define STBI_NO_LINEAR and #define STBI_NO_HDR before including this header.
|
||||||
|
*
|
||||||
|
* License:
|
||||||
|
* This software is dual-licensed to the public domain and under the following
|
||||||
|
* license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||||
|
* publish, and distribute this file as you see fit.
|
||||||
|
* No warranty implied; use at your own risk.
|
||||||
|
*
|
||||||
|
* So you can do whatever you want with this code, including copying it
|
||||||
|
* (or parts of it) into your own source.
|
||||||
|
* No need to mention me or this "license" in your code or docs, even though
|
||||||
|
* it would be appreciated, of course.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0 // Usage Example:
|
||||||
|
#define SDL_STBIMAGE_IMPLEMENTATION
|
||||||
|
#include "SDL_stbimage.h"
|
||||||
|
|
||||||
|
void yourFunction(const char* imageFilePath)
|
||||||
|
{
|
||||||
|
SDL_Surface* surf = STBIMG_Load(imageFilePath);
|
||||||
|
if(surf == NULL) {
|
||||||
|
printf("ERROR: Couldn't load %s, reason: %s\n", imageFilePath, SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... do something with surf ...
|
||||||
|
|
||||||
|
SDL_FreeSurface(surf);
|
||||||
|
}
|
||||||
|
#endif // 0 (usage example)
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SDL__STBIMAGE_H
|
||||||
|
#define SDL__STBIMAGE_H
|
||||||
|
|
||||||
|
// if you really think you need <SDL2/SDL.h> here instead.. feel free to change it,
|
||||||
|
// but the cool kids have path/to/include/SDL2/ in their compilers include path.
|
||||||
|
#include "SDL.h"
|
||||||
|
|
||||||
|
#ifndef SDL_STBIMG_ALLOW_STDIO
|
||||||
|
#define STBI_NO_STDIO // don't need STDIO, will use SDL_RWops to open files
|
||||||
|
#endif
|
||||||
|
#include "../stb_image.h"
|
||||||
|
|
||||||
|
// this allows you to prepend stuff to function signatures, e.g. "static"
|
||||||
|
#ifndef SDL_STBIMG_DEF
|
||||||
|
// by default it's empty
|
||||||
|
#define SDL_STBIMG_DEF
|
||||||
|
#endif // DG_MISC_DEF
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// loads the image file at the given path into a RGB(A) SDL_Surface
|
||||||
|
// Returns NULL on error, use SDL_GetError() to get more information.
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load(const char* file);
|
||||||
|
|
||||||
|
// loads the image file in the given memory buffer into a RGB(A) SDL_Surface
|
||||||
|
// Returns NULL on error, use SDL_GetError() to get more information.
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_LoadFromMemory(const unsigned char* buffer, int length);
|
||||||
|
|
||||||
|
// loads an image file into a RGB(A) SDL_Surface from a seekable SDL_RWops (src)
|
||||||
|
// if you set freesrc to non-zero, SDL_RWclose(src) will be executed after reading.
|
||||||
|
// Returns NULL on error, use SDL_GetError() to get more information.
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW(SDL_RWops* src, int freesrc);
|
||||||
|
|
||||||
|
|
||||||
|
// Creates an SDL_Surface* using the raw RGB(A) pixelData with given width/height
|
||||||
|
// (this doesn't use stb_image and is just a simple SDL_CreateSurfaceFrom()-wrapper)
|
||||||
|
// ! It must be byte-wise 24bit RGB ("888", bytesPerPixel=3) !
|
||||||
|
// ! or byte-wise 32bit RGBA ("8888", bytesPerPixel=4) data !
|
||||||
|
// If freeWithSurface is SDL_TRUE, SDL_FreeSurface() will free the pixelData
|
||||||
|
// you passed with SDL_free() - NOTE that you should only do that if pixelData
|
||||||
|
// was allocated with SDL_malloc(), SDL_calloc() or SDL_realloc()!
|
||||||
|
// Returns NULL on error (in that case pixelData won't be freed!),
|
||||||
|
// use SDL_GetError() to get more information.
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_CreateSurface(unsigned char* pixelData, int width, int height,
|
||||||
|
int bytesPerPixel, SDL_bool freeWithSurface);
|
||||||
|
|
||||||
|
|
||||||
|
#if SDL_MAJOR_VERSION > 1
|
||||||
|
// loads the image file at the given path into a RGB(A) SDL_Texture
|
||||||
|
// Returns NULL on error, use SDL_GetError() to get more information.
|
||||||
|
SDL_STBIMG_DEF SDL_Texture*
|
||||||
|
STBIMG_LoadTexture(SDL_Renderer* renderer, const char* file);
|
||||||
|
|
||||||
|
// loads the image file in the given memory buffer into a RGB(A) SDL_Texture
|
||||||
|
// Returns NULL on error, use SDL_GetError() to get more information.
|
||||||
|
SDL_STBIMG_DEF SDL_Texture*
|
||||||
|
STBIMG_LoadTextureFromMemory(SDL_Renderer* renderer, const unsigned char* buffer, int length);
|
||||||
|
|
||||||
|
// loads an image file into a RGB(A) SDL_Texture from a seekable SDL_RWops (src)
|
||||||
|
// if you set freesrc to non-zero, SDL_RWclose(src) will be executed after reading.
|
||||||
|
// Returns NULL on error, use SDL_GetError() to get more information.
|
||||||
|
SDL_STBIMG_DEF SDL_Texture*
|
||||||
|
STBIMG_LoadTexture_RW(SDL_Renderer* renderer, SDL_RWops* src, int freesrc);
|
||||||
|
|
||||||
|
// Creates an SDL_Texture* using the raw RGB(A) pixelData with given width/height
|
||||||
|
// (this doesn't use stb_image and is just a simple SDL_CreateSurfaceFrom()-wrapper)
|
||||||
|
// ! It must be byte-wise 24bit RGB ("888", bytesPerPixel=3) !
|
||||||
|
// ! or byte-wise 32bit RGBA ("8888", bytesPerPixel=4) data !
|
||||||
|
// Returns NULL on error, use SDL_GetError() to get more information.
|
||||||
|
SDL_STBIMG_DEF SDL_Texture*
|
||||||
|
STBIMG_CreateTexture(SDL_Renderer* renderer, const unsigned char* pixelData,
|
||||||
|
int width, int height, int bytesPerPixel);
|
||||||
|
#endif // SDL_MAJOR_VERSION > 1
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SDL_RWops* src;
|
||||||
|
stbi_io_callbacks stb_cbs;
|
||||||
|
int atEOF; // defaults to 0; 1: reached EOF or error on read, 2: error on seek
|
||||||
|
} STBIMG_stbio_RWops;
|
||||||
|
|
||||||
|
// creates stbi_io_callbacks and userdata to use stbi_*_from_callbacks() directly,
|
||||||
|
// especially useful to use SDL_RWops with stb_image, without using SDL_Surface
|
||||||
|
// src must be readable and seekable!
|
||||||
|
// Returns SDL_FALSE on error (SDL_GetError() will give you info), else SDL_TRUE
|
||||||
|
// NOTE: If you want to use src twice (e.g. for info and load), remember to rewind
|
||||||
|
// it by seeking back to its initial position and resetting out->atEOF to 0
|
||||||
|
// inbetween the uses!
|
||||||
|
SDL_STBIMG_DEF SDL_bool STBIMG_stbi_callback_from_RW(SDL_RWops* src, STBIMG_stbio_RWops* out);
|
||||||
|
|
||||||
|
#if 0 // Use STBIMG_stbi_callback_from_RW() like this:
|
||||||
|
SDL_RWops* src = ...; // wherever it's from
|
||||||
|
STBIMG_stbio_RWops io;
|
||||||
|
if(!STBIMG_stbi_callback_from_RW(src, &io)) {
|
||||||
|
printf("ERROR creating stbio callbacks: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
Sint64 origSrcPosition = SDL_RWtell(src);
|
||||||
|
int w, h, fmt;
|
||||||
|
if(!stbi_info_from_callbacks(&io.stb_cbs, &io, &w, &h, &fmt)) {
|
||||||
|
printf("stbi_info_from_callbacks() failed, reason: %s\n", stbi_failure_reason());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
printf("image is %d x %d pixels with %d bytes per pixel\n", w, h, fmt);
|
||||||
|
|
||||||
|
// rewind src before using it again in stbi_load_from_callbacks()
|
||||||
|
if(SDL_RWseek(src, origSrcPosition, RW_SEEK_SET) < 0)
|
||||||
|
{
|
||||||
|
printf("ERROR: src not be seekable!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
io.atEOF = 0; // remember to reset atEOF, too!
|
||||||
|
|
||||||
|
unsigned char* data;
|
||||||
|
data = stbi_load_from_callbacks(&io.stb_cbs, &io, &w, &h, &fmt, 0);
|
||||||
|
if(data == NULL) {
|
||||||
|
printf("stbi_load_from_callbacks() failed, reason: %s\n", stbi_failure_reason());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
// ... do something with data ...
|
||||||
|
stbi_image_free(data);
|
||||||
|
#endif // 0 (STBIMG_stbi_callback_from_RW() example)
|
||||||
|
|
||||||
|
|
||||||
|
#if SDL_MAJOR_VERSION > 1
|
||||||
|
// loads an image file into a RGB(A) SDL_Surface from a SDL_RWops (src)
|
||||||
|
// - without using SDL_RWseek(), for streams that don't support or are slow
|
||||||
|
// at seeking. It reads everything into a buffer and calls STBIMG_LoadFromMemory()
|
||||||
|
// You should probably only use this if you *really* have performance problems
|
||||||
|
// because of seeking or your src doesn't support SDL_RWseek(), but SDL_RWsize()
|
||||||
|
// src must at least support SDL_RWread() and SDL_RWsize()
|
||||||
|
// if you set freesrc to non-zero, SDL_RWclose(src) will be executed after reading.
|
||||||
|
// Returns NULL on error, use SDL_GetError() to get more information.
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW_noSeek(SDL_RWops* src, int freesrc);
|
||||||
|
|
||||||
|
// the same for textures (you should probably not use this one, either..)
|
||||||
|
SDL_STBIMG_DEF SDL_Texture* STBIMG_LoadTexture_RW_noSeek(SDL_Renderer* renderer, SDL_RWops* src, int freesrc);
|
||||||
|
#endif // SDL_MAJOR_VERSION > 1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SDL__STBIMAGE_H
|
||||||
|
|
||||||
|
|
||||||
|
// ############# Below: Implementation ###############
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SDL_STBIMAGE_IMPLEMENTATION
|
||||||
|
|
||||||
|
// make stb_image use SDL_malloc etc, so SDL_FreeSurface() can SDL_free()
|
||||||
|
// the data allocated by stb_image
|
||||||
|
#define STBI_MALLOC SDL_malloc
|
||||||
|
#define STBI_REALLOC SDL_realloc
|
||||||
|
#define STBI_FREE SDL_free
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#ifndef SDL_STBIMG_ALLOW_STDIO
|
||||||
|
#define STBI_NO_STDIO // don't need STDIO, will use SDL_RWops to open files
|
||||||
|
#endif
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char* data;
|
||||||
|
int w;
|
||||||
|
int h;
|
||||||
|
int format; // 3: RGB, 4: RGBA
|
||||||
|
} STBIMG__image;
|
||||||
|
|
||||||
|
static SDL_Surface* STBIMG__CreateSurfaceImpl(STBIMG__image img, int freeWithSurface)
|
||||||
|
{
|
||||||
|
SDL_Surface* surf = NULL;
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 5)
|
||||||
|
|
||||||
|
// SDL 2.0.5 introduced SDL_CreateRGBSurfaceWithFormatFrom() and SDL_PIXELFORMAT_RGBA32
|
||||||
|
// which makes this code much simpler.
|
||||||
|
|
||||||
|
Uint32 format = (img.format == STBI_rgb) ? SDL_PIXELFORMAT_RGB24 : SDL_PIXELFORMAT_RGBA32;
|
||||||
|
|
||||||
|
surf = SDL_CreateRGBSurfaceWithFormatFrom((void*)img.data, img.w, img.h,
|
||||||
|
img.format*8, img.format*img.w, format);
|
||||||
|
|
||||||
|
#else // older SDL2 version without SDL_CreateRGBSurfaceWithFormatFrom()
|
||||||
|
|
||||||
|
Uint32 rmask, gmask, bmask, amask;
|
||||||
|
// ok, the following is pretty stupid.. SDL_CreateRGBSurfaceFrom() pretends to use
|
||||||
|
// a void* for the data, but it's really treated as endian-specific Uint32*
|
||||||
|
// and there isn't even an SDL_PIXELFORMAT_* for 32bit byte-wise RGBA
|
||||||
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||||
|
int shift = (img.format == STBI_rgb) ? 8 : 0;
|
||||||
|
rmask = 0xff000000 >> shift;
|
||||||
|
gmask = 0x00ff0000 >> shift;
|
||||||
|
bmask = 0x0000ff00 >> shift;
|
||||||
|
amask = 0x000000ff >> shift;
|
||||||
|
#else // little endian, like x86
|
||||||
|
rmask = 0x000000ff;
|
||||||
|
gmask = 0x0000ff00;
|
||||||
|
bmask = 0x00ff0000;
|
||||||
|
amask = (img.format == STBI_rgb) ? 0 : 0xff000000;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
surf = SDL_CreateRGBSurfaceFrom((void*)img.data, img.w, img.h,
|
||||||
|
img.format*8, img.format*img.w,
|
||||||
|
rmask, gmask, bmask, amask);
|
||||||
|
#endif // SDL_VERSION_ATLEAST
|
||||||
|
|
||||||
|
if(surf == NULL)
|
||||||
|
{
|
||||||
|
// hopefully SDL_CreateRGBSurfaceFrom() has set an sdl error
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(freeWithSurface)
|
||||||
|
{
|
||||||
|
// SDL_Surface::flags is documented to be read-only.. but if the pixeldata
|
||||||
|
// has been allocated with SDL_malloc()/SDL_calloc()/SDL_realloc() this
|
||||||
|
// should work (and it currently does) + @icculus said it's reasonably safe:
|
||||||
|
// https://twitter.com/icculus/status/667036586610139137 :-)
|
||||||
|
// clear the SDL_PREALLOC flag, so SDL_FreeSurface() free()s the data passed from img.data
|
||||||
|
surf->flags &= ~SDL_PREALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return surf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_LoadFromMemory(const unsigned char* buffer, int length)
|
||||||
|
{
|
||||||
|
STBIMG__image img = {0};
|
||||||
|
int bppToUse = 0;
|
||||||
|
int inforet = 0;
|
||||||
|
SDL_Surface* ret = NULL;
|
||||||
|
|
||||||
|
if(buffer == NULL)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_LoadFromMemory(): passed buffer was NULL!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(length <= 0)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_LoadFromMemory(): passed invalid length: %d!", length);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inforet = stbi_info_from_memory(buffer, length, &img.w, &img.h, &img.format);
|
||||||
|
if(!inforet)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_LoadFromMemory(): Couldn't get image info: %s!\n", stbi_failure_reason());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no alpha => use RGB, else use RGBA
|
||||||
|
bppToUse = (img.format == STBI_grey || img.format == STBI_rgb) ? STBI_rgb : STBI_rgb_alpha;
|
||||||
|
|
||||||
|
img.data = stbi_load_from_memory(buffer, length, &img.w, &img.h, &img.format, bppToUse);
|
||||||
|
if(img.data == NULL)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_LoadFromMemory(): Couldn't load image: %s!\n", stbi_failure_reason());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
img.format = bppToUse;
|
||||||
|
|
||||||
|
ret = STBIMG__CreateSurfaceImpl(img, 1);
|
||||||
|
|
||||||
|
if(ret == NULL)
|
||||||
|
{
|
||||||
|
// no need to log an error here, it was an SDL error which should still be available through SDL_GetError()
|
||||||
|
SDL_free(img.data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// fill 'data' with 'size' bytes. return number of bytes actually read
|
||||||
|
static int STBIMG__io_read(void* user, char* data, int size)
|
||||||
|
{
|
||||||
|
STBIMG_stbio_RWops* io = (STBIMG_stbio_RWops*)user;
|
||||||
|
|
||||||
|
int ret = SDL_RWread(io->src, data, sizeof(char), size);
|
||||||
|
if(ret == 0)
|
||||||
|
{
|
||||||
|
// we're at EOF or some error happend
|
||||||
|
io->atEOF = 1;
|
||||||
|
}
|
||||||
|
return (int)ret*sizeof(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip the next 'n' bytes, or 'unget' the last -n bytes if negative
|
||||||
|
static void STBIMG__io_skip(void* user, int n)
|
||||||
|
{
|
||||||
|
STBIMG_stbio_RWops* io = (STBIMG_stbio_RWops*)user;
|
||||||
|
|
||||||
|
if(SDL_RWseek(io->src, n, RW_SEEK_CUR) == -1)
|
||||||
|
{
|
||||||
|
// an error happened during seeking, hopefully setting EOF will make stb_image abort
|
||||||
|
io->atEOF = 2; // set this to 2 for "aborting because seeking failed" (stb_image only cares about != 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns nonzero if we are at end of file/data
|
||||||
|
static int STBIMG__io_eof(void* user)
|
||||||
|
{
|
||||||
|
STBIMG_stbio_RWops* io = (STBIMG_stbio_RWops*)user;
|
||||||
|
return io->atEOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_bool STBIMG_stbi_callback_from_RW(SDL_RWops* src, STBIMG_stbio_RWops* out)
|
||||||
|
{
|
||||||
|
if(out == NULL)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_stbi_callback_from_RW(): out must not be NULL!");
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure out is at least initialized to something deterministic
|
||||||
|
memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
|
if(src == NULL)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_stbi_callback_from_RW(): src must not be NULL!");
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->src = src;
|
||||||
|
out->atEOF = 0;
|
||||||
|
out->stb_cbs.read = STBIMG__io_read;
|
||||||
|
out->stb_cbs.skip = STBIMG__io_skip;
|
||||||
|
out->stb_cbs.eof = STBIMG__io_eof;
|
||||||
|
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW(SDL_RWops* src, int freesrc)
|
||||||
|
{
|
||||||
|
STBIMG__image img = {0};
|
||||||
|
int bppToUse = 0;
|
||||||
|
int inforet = 0;
|
||||||
|
SDL_Surface* ret = NULL;
|
||||||
|
Sint64 srcOffset = 0;
|
||||||
|
|
||||||
|
STBIMG_stbio_RWops cbData;
|
||||||
|
|
||||||
|
if(src == NULL)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_Load_RW(): src was NULL!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
srcOffset = SDL_RWtell(src);
|
||||||
|
if(srcOffset < 0)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_Load_RW(): src must be seekable, maybe use STBIMG_Load_RW_noSeek() instead!");
|
||||||
|
// TODO: or do that automatically? but I think the user should be aware of what they're doing
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!STBIMG_stbi_callback_from_RW(src, &cbData))
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
inforet = stbi_info_from_callbacks(&cbData.stb_cbs, &cbData, &img.w, &img.h, &img.format);
|
||||||
|
if(!inforet)
|
||||||
|
{
|
||||||
|
if(cbData.atEOF == 2) SDL_SetError("STBIMG_Load_RW(): src must be seekable!");
|
||||||
|
else SDL_SetError("STBIMG_Load_RW(): Couldn't get image info: %s!\n", stbi_failure_reason());
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rewind src so stbi_load_from_callbacks() will start reading from the beginning again
|
||||||
|
if(SDL_RWseek(src, srcOffset, RW_SEEK_SET) < 0)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_Load_RW(): src must be seekable!");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbData.atEOF = 0; // we've rewinded (rewound?)
|
||||||
|
|
||||||
|
// no alpha => use RGB, else use RGBA
|
||||||
|
bppToUse = (img.format == STBI_grey || img.format == STBI_rgb) ? STBI_rgb : STBI_rgb_alpha;
|
||||||
|
|
||||||
|
img.data = stbi_load_from_callbacks(&cbData.stb_cbs, &cbData, &img.w, &img.h, &img.format, bppToUse);
|
||||||
|
if(img.data == NULL)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_Load_RW(): Couldn't load image: %s!\n", stbi_failure_reason());
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
img.format = bppToUse;
|
||||||
|
|
||||||
|
ret = STBIMG__CreateSurfaceImpl(img, 1);
|
||||||
|
|
||||||
|
if(ret == NULL)
|
||||||
|
{
|
||||||
|
// no need to log an error here, it was an SDL error which should still be available through SDL_GetError()
|
||||||
|
SDL_free(img.data);
|
||||||
|
img.data = NULL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
if(freesrc)
|
||||||
|
{
|
||||||
|
SDL_RWclose(src);
|
||||||
|
}
|
||||||
|
else if(img.data == NULL)
|
||||||
|
{
|
||||||
|
// if data is still NULL, there was an error and we should probably
|
||||||
|
// seek src back to where it was when this function was called
|
||||||
|
SDL_RWseek(src, srcOffset, RW_SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SDL_MAJOR_VERSION > 1
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load_RW_noSeek(SDL_RWops* src, int freesrc)
|
||||||
|
{
|
||||||
|
unsigned char* buf = NULL;
|
||||||
|
Sint64 fileSize = 0;
|
||||||
|
SDL_Surface* ret = NULL;
|
||||||
|
|
||||||
|
if(src == NULL)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_Load_RW_noSeek(): src was NULL!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileSize = SDL_RWsize(src);
|
||||||
|
if(fileSize < 0)
|
||||||
|
{
|
||||||
|
goto end; // SDL should have set an error already
|
||||||
|
}
|
||||||
|
else if(fileSize == 0)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_Load_RW_noSeek(): SDL_RWsize(src) returned 0 => empty file/stream?!");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
else if(fileSize > 0x7FFFFFFF)
|
||||||
|
{
|
||||||
|
// stb_image.h uses ints for all sizes, so we can't support more
|
||||||
|
// (but >2GB images are insane anyway)
|
||||||
|
SDL_SetError("STBIMG_Load_RW_noSeek(): SDL_RWsize(src) too big (> 2GB)!");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = (unsigned char*)SDL_malloc(fileSize);
|
||||||
|
if(buf == NULL)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_Load_RW_noSeek(): Couldn't allocate buffer to read src into!");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SDL_RWread(src, buf, fileSize, 1) > 0)
|
||||||
|
{
|
||||||
|
// if that fails, STBIMG_LoadFromMemory() has set an SDL error
|
||||||
|
// and ret is NULL, so nothing special to do for us
|
||||||
|
ret = STBIMG_LoadFromMemory(buf, fileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
if(freesrc)
|
||||||
|
{
|
||||||
|
SDL_RWclose(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif // SDL_MAJOR_VERSION > 1
|
||||||
|
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_Load(const char* file)
|
||||||
|
{
|
||||||
|
SDL_RWops* src = SDL_RWFromFile(file, "rb");
|
||||||
|
if(src == NULL) return NULL;
|
||||||
|
return STBIMG_Load_RW(src, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_Surface* STBIMG_CreateSurface(unsigned char* pixelData, int width, int height, int bytesPerPixel, SDL_bool freeWithSurface)
|
||||||
|
{
|
||||||
|
STBIMG__image img;
|
||||||
|
|
||||||
|
if(pixelData == NULL)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_CreateSurface(): passed pixelData was NULL!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(bytesPerPixel != 3 && bytesPerPixel != 4)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_CreateSurface(): passed bytesPerPixel = %d, only 3 (24bit RGB) and 4 (32bit RGBA) are allowed!", bytesPerPixel);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(width <= 0 || height <= 0)
|
||||||
|
{
|
||||||
|
SDL_SetError("STBIMG_CreateSurface(): width and height must be > 0!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.data = pixelData;
|
||||||
|
img.w = width;
|
||||||
|
img.h = height;
|
||||||
|
img.format = bytesPerPixel;
|
||||||
|
|
||||||
|
return STBIMG__CreateSurfaceImpl(img, freeWithSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SDL_MAJOR_VERSION > 1
|
||||||
|
static SDL_Texture* STBIMG__SurfToTex(SDL_Renderer* renderer, SDL_Surface* surf)
|
||||||
|
{
|
||||||
|
SDL_Texture* ret = NULL;
|
||||||
|
if(surf != NULL)
|
||||||
|
{
|
||||||
|
ret = SDL_CreateTextureFromSurface(renderer, surf);
|
||||||
|
SDL_FreeSurface(surf); // not needed anymore, it's copied into tex
|
||||||
|
}
|
||||||
|
// if surf is NULL, whatever tried to create it should have called SDL_SetError(),
|
||||||
|
// if SDL_CreateTextureFromSurface() returned NULL it should have set an error
|
||||||
|
// so whenever this returns NULL, the user should be able to get a useful
|
||||||
|
// error-message with SDL_GetError().
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_Texture*
|
||||||
|
STBIMG_LoadTexture(SDL_Renderer* renderer, const char* file)
|
||||||
|
{
|
||||||
|
return STBIMG__SurfToTex(renderer, STBIMG_Load(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_Texture*
|
||||||
|
STBIMG_LoadTextureFromMemory(SDL_Renderer *renderer, const unsigned char* buffer, int length)
|
||||||
|
{
|
||||||
|
return STBIMG__SurfToTex(renderer, STBIMG_LoadFromMemory(buffer, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_Texture*
|
||||||
|
STBIMG_LoadTexture_RW(SDL_Renderer* renderer, SDL_RWops* src, int freesrc)
|
||||||
|
{
|
||||||
|
return STBIMG__SurfToTex(renderer, STBIMG_Load_RW(src, freesrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_Texture*
|
||||||
|
STBIMG_CreateTexture(SDL_Renderer* renderer, const unsigned char* pixelData,
|
||||||
|
int width, int height, int bytesPerPixel)
|
||||||
|
{
|
||||||
|
SDL_Surface* surf = STBIMG_CreateSurface((unsigned char*)pixelData, width, height, bytesPerPixel, SDL_FALSE);
|
||||||
|
return STBIMG__SurfToTex(renderer, surf);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_STBIMG_DEF SDL_Texture*
|
||||||
|
STBIMG_LoadTexture_RW_noSeek(SDL_Renderer* renderer, SDL_RWops* src, int freesrc)
|
||||||
|
{
|
||||||
|
return STBIMG__SurfToTex(renderer, STBIMG_Load_RW_noSeek(src, freesrc));
|
||||||
|
}
|
||||||
|
#endif // SDL_MAJOR_VERSION > 1
|
||||||
|
|
||||||
|
#endif // SDL_STBIMAGE_IMPLEMENTATION
|
7897
src/stb_image.h
Normal file
7897
src/stb_image.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue