summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorRay <[email protected]>2017-03-25 12:01:01 +0100
committerRay <[email protected]>2017-03-25 12:01:01 +0100
commit5387b4543175bee9d195b24e250a0ef863a63555 (patch)
treec0fc5326cf48070969af59163dcc0efa4688e19e /src
parent3f0c29642225f4da40e29e83117a4589f95be538 (diff)
downloadraylib-5387b4543175bee9d195b24e250a0ef863a63555.tar.gz
raylib-5387b4543175bee9d195b24e250a0ef863a63555.zip
Working on configuration flags
Diffstat (limited to 'src')
-rw-r--r--src/core.c6
-rw-r--r--src/raylib.h2
-rw-r--r--src/rlgl.c21
-rw-r--r--src/textures.c345
-rw-r--r--src/utils.c2
5 files changed, 228 insertions, 148 deletions
diff --git a/src/core.c b/src/core.c
index 1a0e5a66..5a1ab77f 100644
--- a/src/core.c
+++ b/src/core.c
@@ -70,13 +70,13 @@
*
**********************************************************************************************/
-// Default supported features
-//-------------------------------------
+// Default configuration flags (supported features)
+//-------------------------------------------------
#define SUPPORT_DEFAULT_FONT
#define SUPPORT_MOUSE_GESTURES
#define SUPPORT_CAMERA_SYSTEM
#define SUPPORT_GESTURES_SYSTEM
-//-------------------------------------
+//-------------------------------------------------
#include "raylib.h"
diff --git a/src/raylib.h b/src/raylib.h
index cdefceb2..24d6e1fd 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -13,7 +13,7 @@
* - Multiple textures support, including compressed formats and mipmaps generation
* - Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps
* - Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
-* - Audio loading and playing with streaming support and mixing channels [audio]
+* - Audio loading and playing with streaming support and mixing channels: [audio]
* - VR stereo rendering support with configurable HMD device parameters
* - Multiple platforms support: Windows, Linux, Mac, Android, Raspberry Pi, HTML5 and Oculus Rift CV1
* - Custom color palette for fancy visuals on raywhite background
diff --git a/src/rlgl.c b/src/rlgl.c
index a937bdec..546fbe6e 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -25,7 +25,7 @@
* #define SUPPORT_VR_SIMULATION / SUPPORT_STEREO_RENDERING
* Support VR simulation functionality (stereo rendering)
*
-* #define SUPPORT_SHADER_DISTORTION
+* #define SUPPORT_DISTORTION_SHADER
* Include stereo rendering distortion shader (shader_distortion.h)
*
* DEPENDENCIES:
@@ -54,6 +54,11 @@
*
**********************************************************************************************/
+// Default configuration flags (supported features)
+//-------------------------------------------------
+#define SUPPORT_VR_SIMULATION
+//-------------------------------------------------
+
#include "rlgl.h"
#include <stdio.h> // Required for: fopen(), fclose(), fread()... [Used only on LoadText()]
@@ -100,7 +105,7 @@
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()]
#endif
-#if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_DISTORTION_SHADER)
+#if !defined(GRAPHICS_API_OPENGL_11) && defined(SUPPORT_DISTORTION_SHADER)
#include "shader_distortion.h" // Distortion shader to be embedded
#endif
@@ -2591,10 +2596,12 @@ void InitVrSimulator(int vrDevice)
// Initialize framebuffer and textures for stereo rendering
// NOTE: screen size should match HMD aspect ratio
vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight);
-
+
+#if defined(SUPPORT_DISTORTION_SHADER)
// Load distortion shader (initialized by default with Oculus Rift CV1 parameters)
vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr);
if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader);
+#endif
SetStereoConfig(hmd);
@@ -2613,7 +2620,9 @@ void CloseVrSimulator(void)
if (vrSimulatorReady)
{
rlDeleteRenderTextures(vrConfig.stereoFbo); // Unload stereo framebuffer and texture
+ #if defined(SUPPORT_DISTORTION_SHADER)
UnloadShader(vrConfig.distortionShader); // Unload distortion shader
+ #endif
}
#endif
}
@@ -2700,8 +2709,12 @@ void EndVrDrawing(void)
rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix
rlLoadIdentity(); // Reset internal modelview matrix
+#if defined(SUPPORT_DISTORTION_SHADER)
// Draw RenderTexture (stereoFbo) using distortion shader
currentShader = vrConfig.distortionShader;
+#else
+ currentShader = GetDefaultShader();
+#endif
rlEnableTexture(vrConfig.stereoFbo.texture.id);
@@ -3536,6 +3549,7 @@ static void SetStereoConfig(VrDeviceInfo hmd)
TraceLog(DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]);
TraceLog(DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]);
+#if defined(SUPPORT_DISTORTION_SHADER)
// Update distortion shader with lens and distortion-scale parameters
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, 2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, 2);
@@ -3546,6 +3560,7 @@ static void SetStereoConfig(VrDeviceInfo hmd)
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scaleIn"), scaleIn, 2);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "hmdWarpParam"), hmd.distortionK, 4);
SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4);
+#endif
// Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG
// ...but with lens distortion it is increased (see Oculus SDK Documentation)
diff --git a/src/textures.c b/src/textures.c
index f323f352..6fff8e75 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -4,24 +4,24 @@
*
* CONFIGURATION:
*
-* #define SUPPORT_STB_IMAGE / INCLUDE_STB_IMAGE
-*
-* #define SUPPORT_FILEFORMAT_BMP / SUPPORT_LOAD_BMP
-* #define SUPPORT_FILEFORMAT_PNG / SUPPORT_LOAD_PNG
+* #define SUPPORT_FILEFORMAT_BMP
+* #define SUPPORT_FILEFORMAT_PNG
* #define SUPPORT_FILEFORMAT_TGA
-* #define SUPPORT_FILEFORMAT_JPG / ENABLE_LOAD_JPG
+* #define SUPPORT_FILEFORMAT_JPG
* #define SUPPORT_FILEFORMAT_GIF
+* #define SUPPORT_FILEFORMAT_PSD
* #define SUPPORT_FILEFORMAT_HDR
-* #define SUPPORT_FILEFORMAT_DDS / ENABLE_LOAD_DDS
+* #define SUPPORT_FILEFORMAT_DDS
* #define SUPPORT_FILEFORMAT_PKM
* #define SUPPORT_FILEFORMAT_KTX
* #define SUPPORT_FILEFORMAT_PVR
* #define SUPPORT_FILEFORMAT_ASTC
-* Selected desired fileformats to be supported for loading. Some of those formats are
+* Selecte desired fileformats to be supported for image data loading. Some of those formats are
* supported by default, to remove support, just comment unrequired #define in this module
*
-* #define SUPPORT_IMAGE_RESIZE / INCLUDE_STB_IMAGE_RESIZE
* #define SUPPORT_IMAGE_MANIPULATION
+* Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
+* If not defined only three image editing functions supported: ImageFormat(), ImageAlphaMask(), ImageToPOT()
*
* DEPENDENCIES:
* stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
@@ -50,6 +50,12 @@
*
**********************************************************************************************/
+// Default configuration flags (supported features)
+//-------------------------------------------------
+#define SUPPORT_FILEFORMAT_PNG
+#define SUPPORT_IMAGE_MANIPULATION
+//-------------------------------------------------
+
#include "raylib.h"
#include <stdlib.h> // Required for: malloc(), free()
@@ -61,23 +67,46 @@
#include "utils.h" // Required for: fopen() Android mapping, TraceLog()
-// Support only desired texture formats, by default: JPEG, PNG, BMP, TGA
-//#define STBI_NO_JPEG // Image format .jpg and .jpeg
-//#define STBI_NO_PNG
-//#define STBI_NO_BMP
-//#define STBI_NO_TGA
-#define STBI_NO_PSD
-#define STBI_NO_GIF
-#define STBI_NO_HDR
+// Support only desired texture formats on stb_image
+#if !defined(SUPPORT_FILEFORMAT_BMP)
+ #define STBI_NO_BMP
+#endif
+#if !defined(SUPPORT_FILEFORMAT_PNG)
+ #define STBI_NO_PNG
+#endif
+#if !defined(SUPPORT_FILEFORMAT_TGA)
+ #define STBI_NO_TGA
+#endif
+#if !defined(SUPPORT_FILEFORMAT_JPG)
+ #define STBI_NO_JPEG // Image format .jpg and .jpeg
+#endif
+#if !defined(SUPPORT_FILEFORMAT_PSD)
+ #define STBI_NO_PSD
+#endif
+#if !defined(SUPPORT_FILEFORMAT_GIF)
+ #define STBI_NO_GIF
+#endif
+#if !defined(SUPPORT_FILEFORMAT_HDR)
+ #define STBI_NO_HDR
+#endif
+
+// Image fileformats not supported by default
#define STBI_NO_PIC
#define STBI_NO_PNM // Image format .ppm and .pgm
-#define STB_IMAGE_IMPLEMENTATION
-#include "external/stb_image.h" // Required for: stbi_load()
- // NOTE: Used to read image data (multiple formats support)
-#define STB_IMAGE_RESIZE_IMPLEMENTATION
-#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8()
- // NOTE: Used for image scaling on ImageResize()
+#if (defined(SUPPORT_FILEFORMAT_BMP) || defined(SUPPORT_FILEFORMAT_PNG) || defined(SUPPORT_FILEFORMAT_TGA) || \
+ defined(SUPPORT_FILEFORMAT_JPG) || defined(SUPPORT_FILEFORMAT_PSD) || defined(SUPPORT_FILEFORMAT_GIF) || \
+ defined(SUPPORT_FILEFORMAT_HDR))
+ #define STB_IMAGE_IMPLEMENTATION
+ #include "external/stb_image.h" // Required for: stbi_load()
+ // NOTE: Used to read image data (multiple formats support)
+#endif
+
+#if defined(SUPPORT_IMAGE_MANIPULATION)
+ #define STB_IMAGE_RESIZE_IMPLEMENTATION
+ #include "external/stb_image_resize.h" // Required for: stbir_resize_uint8()
+ // NOTE: Used for image scaling on ImageResize()
+#endif
//----------------------------------------------------------------------------------
// Defines and Macros
@@ -102,11 +131,21 @@
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
+#if defined(SUPPORT_FILEFORMAT_DDS)
static Image LoadDDS(const char *fileName); // Load DDS file
+#endif
+#if defined(SUPPORT_FILEFORMAT_PKM)
static Image LoadPKM(const char *fileName); // Load PKM file
+#endif
+#if defined(SUPPORT_FILEFORMAT_KTX)
static Image LoadKTX(const char *fileName); // Load KTX file
+#endif
+#if defined(SUPPORT_FILEFORMAT_PVR)
static Image LoadPVR(const char *fileName); // Load PVR file
+#endif
+#if defined(SUPPORT_FILEFORMAT_ASTC)
static Image LoadASTC(const char *fileName); // Load ASTC file
+#endif
//----------------------------------------------------------------------------------
// Module Functions Definition
@@ -124,19 +163,22 @@ Image LoadImage(const char *fileName)
image.mipmaps = 0;
image.format = 0;
- if ((strcmp(GetExtension(fileName),"png") == 0) ||
- (strcmp(GetExtension(fileName),"bmp") == 0) ||
- (strcmp(GetExtension(fileName),"tga") == 0) ||
- (strcmp(GetExtension(fileName),"jpg") == 0)
-#ifndef STBI_NO_GIF
+ if ((strcmp(GetExtension(fileName),"png") == 0)
+#if defined(SUPPORT_FILEFORMAT_BMP)
+ || (strcmp(GetExtension(fileName),"bmp") == 0)
+#endif
+#if defined(SUPPORT_FILEFORMAT_TGA)
+ || (strcmp(GetExtension(fileName),"tga") == 0)
+#endif
+#if defined(SUPPORT_FILEFORMAT_JPG)
+ || (strcmp(GetExtension(fileName),"jpg") == 0)
+#endif
+#if defined(SUPPORT_FILEFORMAT_DDS)
|| (strcmp(GetExtension(fileName),"gif") == 0)
#endif
-#ifndef STBI_NO_PSD
+#if defined(SUPPORT_FILEFORMAT_PSD)
|| (strcmp(GetExtension(fileName),"psd") == 0)
#endif
-#ifndef STBI_NO_PIC
- || (strcmp(GetExtension(fileName),"pic") == 0)
-#endif
)
{
int imgWidth = 0;
@@ -155,11 +197,21 @@ Image LoadImage(const char *fileName)
else if (imgBpp == 3) image.format = UNCOMPRESSED_R8G8B8;
else if (imgBpp == 4) image.format = UNCOMPRESSED_R8G8B8A8;
}
+#if defined(SUPPORT_FILEFORMAT_DDS)
else if (strcmp(GetExtension(fileName),"dds") == 0) image = LoadDDS(fileName);
+#endif
+#if defined(SUPPORT_FILEFORMAT_PKM)
else if (strcmp(GetExtension(fileName),"pkm") == 0) image = LoadPKM(fileName);
+#endif
+#if defined(SUPPORT_FILEFORMAT_KTX)
else if (strcmp(GetExtension(fileName),"ktx") == 0) image = LoadKTX(fileName);
+#endif
+#if defined(SUPPORT_FILEFORMAT_PVR)
else if (strcmp(GetExtension(fileName),"pvr") == 0) image = LoadPVR(fileName);
+#endif
+#if defined(SUPPORT_FILEFORMAT_ASTC)
else if (strcmp(GetExtension(fileName),"astc") == 0) image = LoadASTC(fileName);
+#endif
else if (strcmp(GetExtension(fileName),"rres") == 0)
{
RRES rres = LoadResource(fileName, 0);
@@ -171,6 +223,7 @@ Image LoadImage(const char *fileName)
UnloadResource(rres);
}
+ else TraceLog("[%s] Image fileformat not supported", fileName);
if (image.data != NULL) TraceLog(INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height);
else TraceLog(WARNING, "[%s] Image could not be loaded", fileName);
@@ -664,115 +717,6 @@ void ImageAlphaMask(Image *image, Image alphaMask)
}
}
-// Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
-// NOTE: In case selected bpp do not represent an known 16bit format,
-// dithered data is stored in the LSB part of the unsigned short
-void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp)
-{
- if (image->format >= COMPRESSED_DXT1_RGB)
- {
- TraceLog(WARNING, "Compressed data formats can not be dithered");
- return;
- }
-
- if ((rBpp+gBpp+bBpp+aBpp) > 16)
- {
- TraceLog(WARNING, "Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp));
- }
- else
- {
- Color *pixels = GetImageData(*image);
-
- free(image->data); // free old image data
-
- if ((image->format != UNCOMPRESSED_R8G8B8) && (image->format != UNCOMPRESSED_R8G8B8A8))
- {
- TraceLog(WARNING, "Image format is already 16bpp or lower, dithering could have no effect");
- }
-
- // Define new image format, check if desired bpp match internal known format
- if ((rBpp == 5) && (gBpp == 6) && (bBpp == 5) && (aBpp == 0)) image->format = UNCOMPRESSED_R5G6B5;
- else if ((rBpp == 5) && (gBpp == 5) && (bBpp == 5) && (aBpp == 1)) image->format = UNCOMPRESSED_R5G5B5A1;
- else if ((rBpp == 4) && (gBpp == 4) && (bBpp == 4) && (aBpp == 4)) image->format = UNCOMPRESSED_R4G4B4A4;
- else
- {
- image->format = 0;
- TraceLog(WARNING, "Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp);
- }
-
- // NOTE: We will store the dithered data as unsigned short (16bpp)
- image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
-
- Color oldPixel = WHITE;
- Color newPixel = WHITE;
-
- int rError, gError, bError;
- unsigned short rPixel, gPixel, bPixel, aPixel; // Used for 16bit pixel composition
-
- #define MIN(a,b) (((a)<(b))?(a):(b))
-
- for (int y = 0; y < image->height; y++)
- {
- for (int x = 0; x < image->width; x++)
- {
- oldPixel = pixels[y*image->width + x];
-
- // NOTE: New pixel obtained by bits truncate, it would be better to round values (check ImageFormat())
- newPixel.r = oldPixel.r >> (8 - rBpp); // R bits
- newPixel.g = oldPixel.g >> (8 - gBpp); // G bits
- newPixel.b = oldPixel.b >> (8 - bBpp); // B bits
- newPixel.a = oldPixel.a >> (8 - aBpp); // A bits (not used on dithering)
-
- // NOTE: Error must be computed between new and old pixel but using same number of bits!
- // We want to know how much color precision we have lost...
- rError = (int)oldPixel.r - (int)(newPixel.r << (8 - rBpp));
- gError = (int)oldPixel.g - (int)(newPixel.g << (8 - gBpp));
- bError = (int)oldPixel.b - (int)(newPixel.b << (8 - bBpp));
-
- pixels[y*image->width + x] = newPixel;
-
- // NOTE: Some cases are out of the array and should be ignored
- if (x < (image->width - 1))
- {
- pixels[y*image->width + x+1].r = MIN((int)pixels[y*image->width + x+1].r + (int)((float)rError*7.0f/16), 0xff);
- pixels[y*image->width + x+1].g = MIN((int)pixels[y*image->width + x+1].g + (int)((float)gError*7.0f/16), 0xff);
- pixels[y*image->width + x+1].b = MIN((int)pixels[y*image->width + x+1].b + (int)((float)bError*7.0f/16), 0xff);
- }
-
- if ((x > 0) && (y < (image->height - 1)))
- {
- pixels[(y+1)*image->width + x-1].r = MIN((int)pixels[(y+1)*image->width + x-1].r + (int)((float)rError*3.0f/16), 0xff);
- pixels[(y+1)*image->width + x-1].g = MIN((int)pixels[(y+1)*image->width + x-1].g + (int)((float)gError*3.0f/16), 0xff);
- pixels[(y+1)*image->width + x-1].b = MIN((int)pixels[(y+1)*image->width + x-1].b + (int)((float)bError*3.0f/16), 0xff);
- }
-
- if (y < (image->height - 1))
- {
- pixels[(y+1)*image->width + x].r = MIN((int)pixels[(y+1)*image->width + x].r + (int)((float)rError*5.0f/16), 0xff);
- pixels[(y+1)*image->width + x].g = MIN((int)pixels[(y+1)*image->width + x].g + (int)((float)gError*5.0f/16), 0xff);
- pixels[(y+1)*image->width + x].b = MIN((int)pixels[(y+1)*image->width + x].b + (int)((float)bError*5.0f/16), 0xff);
- }
-
- if ((x < (image->width - 1)) && (y < (image->height - 1)))
- {
- pixels[(y+1)*image->width + x+1].r = MIN((int)pixels[(y+1)*image->width + x+1].r + (int)((float)rError*1.0f/16), 0xff);
- pixels[(y+1)*image->width + x+1].g = MIN((int)pixels[(y+1)*image->width + x+1].g + (int)((float)gError*1.0f/16), 0xff);
- pixels[(y+1)*image->width + x+1].b = MIN((int)pixels[(y+1)*image->width + x+1].b + (int)((float)bError*1.0f/16), 0xff);
- }
-
- rPixel = (unsigned short)newPixel.r;
- gPixel = (unsigned short)newPixel.g;
- bPixel = (unsigned short)newPixel.b;
- aPixel = (unsigned short)newPixel.a;
-
- ((unsigned short *)image->data)[y*image->width + x] = (rPixel << (gBpp + bBpp + aBpp)) | (gPixel << (bBpp + aBpp)) | (bPixel << aBpp) | aPixel;
- }
- }
-
- free(pixels);
- }
-}
-
// Convert image to POT (power-of-two)
// NOTE: It could be useful on OpenGL ES 2.0 (RPI, HTML5)
void ImageToPOT(Image *image, Color fillColor)
@@ -818,6 +762,7 @@ void ImageToPOT(Image *image, Color fillColor)
}
}
+#if defined(SUPPORT_IMAGE_MANIPULATION)
// Copy an image to a new image
Image ImageCopy(Image image)
{
@@ -1203,6 +1148,115 @@ void ImageFlipHorizontal(Image *image)
image->data = processed.data;
}
+// Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
+// NOTE: In case selected bpp do not represent an known 16bit format,
+// dithered data is stored in the LSB part of the unsigned short
+void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp)
+{
+ if (image->format >= COMPRESSED_DXT1_RGB)
+ {
+ TraceLog(WARNING, "Compressed data formats can not be dithered");
+ return;
+ }
+
+ if ((rBpp+gBpp+bBpp+aBpp) > 16)
+ {
+ TraceLog(WARNING, "Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp));
+ }
+ else
+ {
+ Color *pixels = GetImageData(*image);
+
+ free(image->data); // free old image data
+
+ if ((image->format != UNCOMPRESSED_R8G8B8) && (image->format != UNCOMPRESSED_R8G8B8A8))
+ {
+ TraceLog(WARNING, "Image format is already 16bpp or lower, dithering could have no effect");
+ }
+
+ // Define new image format, check if desired bpp match internal known format
+ if ((rBpp == 5) && (gBpp == 6) && (bBpp == 5) && (aBpp == 0)) image->format = UNCOMPRESSED_R5G6B5;
+ else if ((rBpp == 5) && (gBpp == 5) && (bBpp == 5) && (aBpp == 1)) image->format = UNCOMPRESSED_R5G5B5A1;
+ else if ((rBpp == 4) && (gBpp == 4) && (bBpp == 4) && (aBpp == 4)) image->format = UNCOMPRESSED_R4G4B4A4;
+ else
+ {
+ image->format = 0;
+ TraceLog(WARNING, "Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp);
+ }
+
+ // NOTE: We will store the dithered data as unsigned short (16bpp)
+ image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
+
+ Color oldPixel = WHITE;
+ Color newPixel = WHITE;
+
+ int rError, gError, bError;
+ unsigned short rPixel, gPixel, bPixel, aPixel; // Used for 16bit pixel composition
+
+ #define MIN(a,b) (((a)<(b))?(a):(b))
+
+ for (int y = 0; y < image->height; y++)
+ {
+ for (int x = 0; x < image->width; x++)
+ {
+ oldPixel = pixels[y*image->width + x];
+
+ // NOTE: New pixel obtained by bits truncate, it would be better to round values (check ImageFormat())
+ newPixel.r = oldPixel.r >> (8 - rBpp); // R bits
+ newPixel.g = oldPixel.g >> (8 - gBpp); // G bits
+ newPixel.b = oldPixel.b >> (8 - bBpp); // B bits
+ newPixel.a = oldPixel.a >> (8 - aBpp); // A bits (not used on dithering)
+
+ // NOTE: Error must be computed between new and old pixel but using same number of bits!
+ // We want to know how much color precision we have lost...
+ rError = (int)oldPixel.r - (int)(newPixel.r << (8 - rBpp));
+ gError = (int)oldPixel.g - (int)(newPixel.g << (8 - gBpp));
+ bError = (int)oldPixel.b - (int)(newPixel.b << (8 - bBpp));
+
+ pixels[y*image->width + x] = newPixel;
+
+ // NOTE: Some cases are out of the array and should be ignored
+ if (x < (image->width - 1))
+ {
+ pixels[y*image->width + x+1].r = MIN((int)pixels[y*image->width + x+1].r + (int)((float)rError*7.0f/16), 0xff);
+ pixels[y*image->width + x+1].g = MIN((int)pixels[y*image->width + x+1].g + (int)((float)gError*7.0f/16), 0xff);
+ pixels[y*image->width + x+1].b = MIN((int)pixels[y*image->width + x+1].b + (int)((float)bError*7.0f/16), 0xff);
+ }
+
+ if ((x > 0) && (y < (image->height - 1)))
+ {
+ pixels[(y+1)*image->width + x-1].r = MIN((int)pixels[(y+1)*image->width + x-1].r + (int)((float)rError*3.0f/16), 0xff);
+ pixels[(y+1)*image->width + x-1].g = MIN((int)pixels[(y+1)*image->width + x-1].g + (int)((float)gError*3.0f/16), 0xff);
+ pixels[(y+1)*image->width + x-1].b = MIN((int)pixels[(y+1)*image->width + x-1].b + (int)((float)bError*3.0f/16), 0xff);
+ }
+
+ if (y < (image->height - 1))
+ {
+ pixels[(y+1)*image->width + x].r = MIN((int)pixels[(y+1)*image->width + x].r + (int)((float)rError*5.0f/16), 0xff);
+ pixels[(y+1)*image->width + x].g = MIN((int)pixels[(y+1)*image->width + x].g + (int)((float)gError*5.0f/16), 0xff);
+ pixels[(y+1)*image->width + x].b = MIN((int)pixels[(y+1)*image->width + x].b + (int)((float)bError*5.0f/16), 0xff);
+ }
+
+ if ((x < (image->width - 1)) && (y < (image->height - 1)))
+ {
+ pixels[(y+1)*image->width + x+1].r = MIN((int)pixels[(y+1)*image->width + x+1].r + (int)((float)rError*1.0f/16), 0xff);
+ pixels[(y+1)*image->width + x+1].g = MIN((int)pixels[(y+1)*image->width + x+1].g + (int)((float)gError*1.0f/16), 0xff);
+ pixels[(y+1)*image->width + x+1].b = MIN((int)pixels[(y+1)*image->width + x+1].b + (int)((float)bError*1.0f/16), 0xff);
+ }
+
+ rPixel = (unsigned short)newPixel.r;
+ gPixel = (unsigned short)newPixel.g;
+ bPixel = (unsigned short)newPixel.b;
+ aPixel = (unsigned short)newPixel.a;
+
+ ((unsigned short *)image->data)[y*image->width + x] = (rPixel << (gBpp + bBpp + aBpp)) | (gPixel << (bBpp + aBpp)) | (bPixel << aBpp) | aPixel;
+ }
+ }
+
+ free(pixels);
+ }
+}
+
// Modify image color: tint
void ImageColorTint(Image *image, Color color)
{
@@ -1359,6 +1413,7 @@ void ImageColorBrightness(Image *image, int brightness)
image->data = processed.data;
}
+#endif // SUPPORT_IMAGE_MANIPULATION
// Generate GPU mipmaps for a texture
void GenTextureMipmaps(Texture2D *texture)
@@ -1547,6 +1602,7 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V
// Module specific Functions Definition
//----------------------------------------------------------------------------------
+#if defined(SUPPORT_FILEFORMAT_DDS)
// Loading DDS image data (compressed or uncompressed)
static Image LoadDDS(const char *fileName)
{
@@ -1744,7 +1800,9 @@ static Image LoadDDS(const char *fileName)
return image;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_PKM)
// Loading PKM image data (ETC1/ETC2 compression)
// NOTE: KTX is the standard Khronos Group compression format (ETC1/ETC2, mipmaps)
// PKM is a much simpler file format used mainly to contain a single ETC1/ETC2 compressed image (no mipmaps)
@@ -1836,7 +1894,9 @@ static Image LoadPKM(const char *fileName)
return image;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_KTX)
// Load KTX compressed image data (ETC1/ETC2 compression)
static Image LoadKTX(const char *fileName)
{
@@ -1929,7 +1989,9 @@ static Image LoadKTX(const char *fileName)
return image;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_PVR)
// Loading PVR image data (uncompressed or PVRT compression)
// NOTE: PVR v2 not supported, use PVR v3 instead
static Image LoadPVR(const char *fileName)
@@ -2087,7 +2149,9 @@ static Image LoadPVR(const char *fileName)
return image;
}
+#endif
+#if defined(SUPPORT_FILEFORMAT_ASTC)
// Load ASTC compressed image data (ASTC compression)
static Image LoadASTC(const char *fileName)
{
@@ -2170,3 +2234,4 @@ static Image LoadASTC(const char *fileName)
return image;
}
+#endif \ No newline at end of file
diff --git a/src/utils.c b/src/utils.c
index 4d30cbc7..b6b309cc 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -20,7 +20,7 @@
* Show TraceLog() DEBUG messages
*
* DEPENDENCIES:
-* stb_image_write - PNG writting functions
+* stb_image_write - BMP/PNG writting functions
*
*
* LICENSE: zlib/libpng