From f9963d4ed48db37bfeed53e26879078e1d8b9ca8 Mon Sep 17 00:00:00 2001 From: Jens Pitkanen Date: Thu, 14 Feb 2019 12:32:23 +0200 Subject: [PATCH 1/2] Fix config.h flags --- src/models.c | 4 ++++ src/raudio.c | 24 ++++++++++++++++++++++++ src/shapes.c | 2 +- src/text.c | 10 ++++++++++ src/textures.c | 24 +++++++++++++++++++++--- 5 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/models.c b/src/models.c index 925ede07..5feec0f6 100644 --- a/src/models.c +++ b/src/models.c @@ -655,12 +655,16 @@ Mesh LoadMesh(const char *fileName) TraceLog(LOG_WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); #endif +#if defined(SUPPORT_MESH_GENERATION) if (mesh.vertexCount == 0) { TraceLog(LOG_WARNING, "Mesh could not be loaded! Let's load a cube to replace it!"); mesh = GenMeshCube(1.0f, 1.0f, 1.0f); } else rlLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) +#else + rlLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) +#endif return mesh; } diff --git a/src/raudio.c b/src/raudio.c index af4bc3a4..b19c7d86 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -767,7 +767,11 @@ Wave LoadWave(const char *fileName) { Wave wave = { 0 }; +#if defined(SUPPORT_FILEFORMAT_WAV) if (IsFileExtension(fileName, ".wav")) wave = LoadWAV(fileName); +#else + if (false) {} +#endif #if defined(SUPPORT_FILEFORMAT_OGG) else if (IsFileExtension(fileName, ".ogg")) wave = LoadOGG(fileName); #endif @@ -887,7 +891,11 @@ void ExportWave(Wave wave, const char *fileName) { bool success = false; +#if defined(SUPPORT_FILEFORMAT_WAV) if (IsFileExtension(fileName, ".wav")) success = SaveWAV(wave, fileName); +#else + if (false) {} +#endif else if (IsFileExtension(fileName, ".raw")) { // Export raw sample data (without header) @@ -1087,6 +1095,7 @@ Music LoadMusicStream(const char *fileName) Music music = (MusicData *)malloc(sizeof(MusicData)); bool musicLoaded = true; +#if defined(SUPPORT_FILEFORMAT_OGG) if (IsFileExtension(fileName, ".ogg")) { // Open ogg audio stream @@ -1110,6 +1119,9 @@ Music LoadMusicStream(const char *fileName) TraceLog(LOG_DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); } } +#else + if (false) {} +#endif #if defined(SUPPORT_FILEFORMAT_FLAC) else if (IsFileExtension(fileName, ".flac")) { @@ -1202,7 +1214,11 @@ Music LoadMusicStream(const char *fileName) if (!musicLoaded) { + #if defined(SUPPORT_FILEFORMAT_OGG) if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close(music->ctxOgg); + #else + if (false) {} + #endif #if defined(SUPPORT_FILEFORMAT_FLAC) else if (music->ctxType == MUSIC_AUDIO_FLAC) drflac_free(music->ctxFlac); #endif @@ -1232,7 +1248,11 @@ void UnloadMusicStream(Music music) CloseAudioStream(music->stream); +#if defined(SUPPORT_FILEFORMAT_OGG) if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close(music->ctxOgg); +#else + if (false) {} +#endif #if defined(SUPPORT_FILEFORMAT_FLAC) else if (music->ctxType == MUSIC_AUDIO_FLAC) drflac_free(music->ctxFlac); #endif @@ -1297,7 +1317,9 @@ void StopMusicStream(Music music) // Restart music context switch (music->ctxType) { +#if defined(SUPPORT_FILEFORMAT_OGG) case MUSIC_AUDIO_OGG: stb_vorbis_seek_start(music->ctxOgg); break; +#endif #if defined(SUPPORT_FILEFORMAT_FLAC) case MUSIC_AUDIO_FLAC: /* TODO: Restart FLAC context */ break; #endif @@ -1339,12 +1361,14 @@ void UpdateMusicStream(Music music) // TODO: Really don't like ctxType thingy... switch (music->ctxType) { + #if defined(SUPPORT_FILEFORMAT_OGG) case MUSIC_AUDIO_OGG: { // NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!) stb_vorbis_get_samples_short_interleaved(music->ctxOgg, music->stream.channels, (short *)pcm, samplesCount); } break; + #endif #if defined(SUPPORT_FILEFORMAT_FLAC) case MUSIC_AUDIO_FLAC: { diff --git a/src/shapes.c b/src/shapes.c index 454e176a..8976c81c 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -742,7 +742,7 @@ static Texture2D GetShapesTexture(void) recTexShapes = (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }; #else texShapes = GetTextureDefault(); // Use default white texture - recTexShapes = { 0.0f, 0.0f, 1.0f, 1.0f }; + recTexShapes = (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }; #endif } diff --git a/src/text.c b/src/text.c index a6253ffd..17f6d9dd 100644 --- a/src/text.c +++ b/src/text.c @@ -309,6 +309,7 @@ Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCou font.charsCount = (charsCount > 0) ? charsCount : 95; font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT); +#if defined(SUPPORT_FILEFORMAT_TTF) if (font.chars != NULL) { Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 2, 0); @@ -316,6 +317,9 @@ Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCou UnloadImage(atlas); } else font = GetFontDefault(); +#else + font = GetFontDefault(); +#endif return font; } @@ -449,6 +453,7 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c CharInfo *chars = NULL; +#if defined(SUPPORT_FILEFORMAT_TTF) // Load font data (including pixel data) from TTF file // NOTE: Loaded information should be enough to generate font image atlas, // using any packaging method @@ -537,12 +542,16 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c if (genFontChars) free(fontChars); } else TraceLog(LOG_WARNING, "[%s] TTF file could not be opened", fileName); +#else + TraceLog(LOG_WARNING, "[%s] TTF support is disabled", fileName); +#endif return chars; } // Generate image font atlas using chars info // NOTE: Packing method: 0-Default, 1-Skyline +#if defined(SUPPORT_FILEFORMAT_TTF) Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int padding, int packMethod) { Image atlas = { 0 }; @@ -667,6 +676,7 @@ Image GenImageFontAtlas(CharInfo *chars, int charsCount, int fontSize, int paddi return atlas; } +#endif // Unload Font from GPU memory (VRAM) void UnloadFont(Font font) diff --git a/src/textures.c b/src/textures.c index bd47fc81..6684ea84 100644 --- a/src/textures.c +++ b/src/textures.c @@ -182,7 +182,11 @@ Image LoadImage(const char *fileName) { Image image = { 0 }; +#if defined(SUPPORT_FILEFORMAT_PNG) if ((IsFileExtension(fileName, ".png")) +#else + if ((false) +#endif #if defined(SUPPORT_FILEFORMAT_BMP) || (IsFileExtension(fileName, ".bmp")) #endif @@ -825,14 +829,27 @@ void ExportImage(Image image, const char *fileName) { int success = 0; +#if defined(SUPPORT_IMAGE_EXPORT) // NOTE: Getting Color array as RGBA unsigned char values unsigned char *imgData = (unsigned char *)GetImageData(image); +#if defined(SUPPORT_FILEFORMAT_PNG) if (IsFileExtension(fileName, ".png")) success = stbi_write_png(fileName, image.width, image.height, 4, imgData, image.width*4); +#else + if (false) {} +#endif +#if defined(SUPPORT_FILEFORMAT_BMP) else if (IsFileExtension(fileName, ".bmp")) success = stbi_write_bmp(fileName, image.width, image.height, 4, imgData); +#endif +#if defined(SUPPORT_FILEFORMAT_TGA) else if (IsFileExtension(fileName, ".tga")) success = stbi_write_tga(fileName, image.width, image.height, 4, imgData); +#endif +#if defined(SUPPORT_FILEFORMAT_JPG) else if (IsFileExtension(fileName, ".jpg")) success = stbi_write_jpg(fileName, image.width, image.height, 4, imgData, 80); // JPG quality: between 1 and 100 +#endif +#if defined(SUPPORT_FILEFORMAT_KTX) else if (IsFileExtension(fileName, ".ktx")) success = SaveKTX(image, fileName); +#endif else if (IsFileExtension(fileName, ".raw")) { // Export raw pixel data (without header) @@ -842,10 +859,11 @@ void ExportImage(Image image, const char *fileName) fclose(rawFile); } + free(imgData); +#endif + if (success != 0) TraceLog(LOG_INFO, "Image exported successfully: %s", fileName); else TraceLog(LOG_WARNING, "Image could not be exported."); - - free(imgData); } // Export image as code file (.h) defining an array of bytes @@ -2146,7 +2164,6 @@ void ImageColorReplace(Image *image, Color color, Color replace) } #endif // SUPPORT_IMAGE_MANIPULATION -#if defined(SUPPORT_IMAGE_GENERATION) // Generate image: plain color Image GenImageColor(int width, int height, Color color) { @@ -2161,6 +2178,7 @@ Image GenImageColor(int width, int height, Color color) return image; } +#if defined(SUPPORT_IMAGE_GENERATION) // Generate image: vertical gradient Image GenImageGradientV(int width, int height, Color top, Color bottom) { From eed69d41271a597c9753605da77281f93231d4f8 Mon Sep 17 00:00:00 2001 From: Jens Pitkanen Date: Fri, 15 Feb 2019 17:56:36 +0200 Subject: [PATCH 2/2] Fix the image manipulation config flag --- src/textures.c | 234 +++++++++++++++++++++++++------------------------ 1 file changed, 118 insertions(+), 116 deletions(-) diff --git a/src/textures.c b/src/textures.c index 6684ea84..5edd7201 100644 --- a/src/textures.c +++ b/src/textures.c @@ -402,90 +402,6 @@ Texture2D LoadTextureFromImage(Image image) return texture; } -// Load cubemap from image, multiple image cubemap layouts supported -TextureCubemap LoadTextureCubemap(Image image, int layoutType) -{ - TextureCubemap cubemap = { 0 }; - - if (layoutType == CUBEMAP_AUTO_DETECT) // Try to automatically guess layout type - { - // Check image width/height to determine the type of cubemap provided - if (image.width > image.height) - { - if ((image.width/6) == image.height) { layoutType = CUBEMAP_LINE_HORIZONTAL; cubemap.width = image.width/6; } - else if ((image.width/4) == (image.height/3)) { layoutType = CUBEMAP_CROSS_FOUR_BY_THREE; cubemap.width = image.width/4; } - else if (image.width >= (int)((float)image.height*1.85f)) { layoutType = CUBEMAP_PANORAMA; cubemap.width = image.width/4; } - } - else if (image.height > image.width) - { - if ((image.height/6) == image.width) { layoutType = CUBEMAP_LINE_VERTICAL; cubemap.width = image.height/6; } - else if ((image.width/3) == (image.height/4)) { layoutType = CUBEMAP_CROSS_THREE_BY_FOUR; cubemap.width = image.width/3; } - } - - cubemap.height = cubemap.width; - } - - int size = cubemap.width; - - if (layoutType != CUBEMAP_AUTO_DETECT) - { - //unsigned int dataSize = GetPixelDataSize(size, size, format); - //void *facesData = malloc(size*size*dataSize*6); // Get memory for 6 faces in a column - - Image faces = { 0 }; // Vertical column image - Rectangle faceRecs[6] = { 0 }; // Face source rectangles - for (int i = 0; i < 6; i++) faceRecs[i] = (Rectangle){ 0, 0, size, size }; - - if (layoutType == CUBEMAP_LINE_VERTICAL) - { - faces = image; - for (int i = 0; i < 6; i++) faceRecs[i].y = size*i; - } - else if (layoutType == CUBEMAP_PANORAMA) - { - // TODO: Convert panorama image to square faces... - } - else - { - if (layoutType == CUBEMAP_LINE_HORIZONTAL) for (int i = 0; i < 6; i++) faceRecs[i].x = size*i; - else if (layoutType == CUBEMAP_CROSS_THREE_BY_FOUR) - { - faceRecs[0].x = size; faceRecs[0].y = size; - faceRecs[1].x = size; faceRecs[1].y = 3*size; - faceRecs[2].x = size; faceRecs[2].y = 0; - faceRecs[3].x = size; faceRecs[3].y = 2*size; - faceRecs[4].x = 0; faceRecs[4].y = size; - faceRecs[5].x = 2*size; faceRecs[5].y = size; - } - else if (layoutType == CUBEMAP_CROSS_FOUR_BY_THREE) - { - faceRecs[0].x = 2*size; faceRecs[0].y = size; - faceRecs[1].x = 0; faceRecs[1].y = size; - faceRecs[2].x = size; faceRecs[2].y = 0; - faceRecs[3].x = size; faceRecs[3].y = 2*size; - faceRecs[4].x = size; faceRecs[4].y = size; - faceRecs[5].x = 3*size; faceRecs[5].y = size; - } - - // Convert image data to 6 faces in a vertical column, that's the optimum layout for loading - faces = GenImageColor(size, size*6, MAGENTA); - ImageFormat(&faces, image.format); - - // TODO: Image formating does not work with compressed textures! - } - - for (int i = 0; i < 6; i++) ImageDraw(&faces, image, faceRecs[i], (Rectangle){ 0, size*i, size, size }); - - cubemap.id = rlLoadTextureCubemap(faces.data, size, faces.format); - if (cubemap.id == 0) TraceLog(LOG_WARNING, "Cubemap image could not be loaded."); - - UnloadImage(faces); - } - else TraceLog(LOG_WARNING, "Cubemap image layout can not be detected."); - - return cubemap; -} - // Load texture for rendering (framebuffer) // NOTE: Render texture is loaded by default with RGBA color attachment and depth RenderBuffer RenderTexture2D LoadRenderTexture(int width, int height) @@ -1151,7 +1067,9 @@ void ImageFormat(Image *image, int newFormat) if (image->mipmaps > 1) { image->mipmaps = 1; + #if defined(SUPPORT_IMAGE_MANIPULATION) if (image->data != NULL) ImageMipmaps(image); + #endif } } else TraceLog(LOG_WARNING, "Image data format is compressed, can not be converted"); @@ -1220,38 +1138,6 @@ void ImageAlphaClear(Image *image, Color color, float threshold) ImageFormat(image, prevFormat); } -// Crop image depending on alpha value -void ImageAlphaCrop(Image *image, float threshold) -{ - Color *pixels = GetImageData(*image); - - int xMin = 65536; // Define a big enough number - int xMax = 0; - int yMin = 65536; - int yMax = 0; - - for (int y = 0; y < image->height; y++) - { - for (int x = 0; x < image->width; x++) - { - if (pixels[y*image->width + x].a > (unsigned char)(threshold*255.0f)) - { - if (x < xMin) xMin = x; - if (x > xMax) xMax = x; - if (y < yMin) yMin = y; - if (y > yMax) yMax = y; - } - } - } - - Rectangle crop = { xMin, yMin, (xMax + 1) - xMin, (yMax + 1) - yMin }; - - free(pixels); - - // Check for not empty image brefore cropping - if (!((xMax < xMin) || (yMax < yMin))) ImageCrop(image, crop); -} - // Premultiply alpha channel void ImageAlphaPremultiply(Image *image) { @@ -1277,6 +1163,90 @@ void ImageAlphaPremultiply(Image *image) #if defined(SUPPORT_IMAGE_MANIPULATION) +// Load cubemap from image, multiple image cubemap layouts supported +TextureCubemap LoadTextureCubemap(Image image, int layoutType) +{ + TextureCubemap cubemap = { 0 }; + + if (layoutType == CUBEMAP_AUTO_DETECT) // Try to automatically guess layout type + { + // Check image width/height to determine the type of cubemap provided + if (image.width > image.height) + { + if ((image.width/6) == image.height) { layoutType = CUBEMAP_LINE_HORIZONTAL; cubemap.width = image.width/6; } + else if ((image.width/4) == (image.height/3)) { layoutType = CUBEMAP_CROSS_FOUR_BY_THREE; cubemap.width = image.width/4; } + else if (image.width >= (int)((float)image.height*1.85f)) { layoutType = CUBEMAP_PANORAMA; cubemap.width = image.width/4; } + } + else if (image.height > image.width) + { + if ((image.height/6) == image.width) { layoutType = CUBEMAP_LINE_VERTICAL; cubemap.width = image.height/6; } + else if ((image.width/3) == (image.height/4)) { layoutType = CUBEMAP_CROSS_THREE_BY_FOUR; cubemap.width = image.width/3; } + } + + cubemap.height = cubemap.width; + } + + int size = cubemap.width; + + if (layoutType != CUBEMAP_AUTO_DETECT) + { + //unsigned int dataSize = GetPixelDataSize(size, size, format); + //void *facesData = malloc(size*size*dataSize*6); // Get memory for 6 faces in a column + + Image faces = { 0 }; // Vertical column image + Rectangle faceRecs[6] = { 0 }; // Face source rectangles + for (int i = 0; i < 6; i++) faceRecs[i] = (Rectangle){ 0, 0, size, size }; + + if (layoutType == CUBEMAP_LINE_VERTICAL) + { + faces = image; + for (int i = 0; i < 6; i++) faceRecs[i].y = size*i; + } + else if (layoutType == CUBEMAP_PANORAMA) + { + // TODO: Convert panorama image to square faces... + } + else + { + if (layoutType == CUBEMAP_LINE_HORIZONTAL) for (int i = 0; i < 6; i++) faceRecs[i].x = size*i; + else if (layoutType == CUBEMAP_CROSS_THREE_BY_FOUR) + { + faceRecs[0].x = size; faceRecs[0].y = size; + faceRecs[1].x = size; faceRecs[1].y = 3*size; + faceRecs[2].x = size; faceRecs[2].y = 0; + faceRecs[3].x = size; faceRecs[3].y = 2*size; + faceRecs[4].x = 0; faceRecs[4].y = size; + faceRecs[5].x = 2*size; faceRecs[5].y = size; + } + else if (layoutType == CUBEMAP_CROSS_FOUR_BY_THREE) + { + faceRecs[0].x = 2*size; faceRecs[0].y = size; + faceRecs[1].x = 0; faceRecs[1].y = size; + faceRecs[2].x = size; faceRecs[2].y = 0; + faceRecs[3].x = size; faceRecs[3].y = 2*size; + faceRecs[4].x = size; faceRecs[4].y = size; + faceRecs[5].x = 3*size; faceRecs[5].y = size; + } + + // Convert image data to 6 faces in a vertical column, that's the optimum layout for loading + faces = GenImageColor(size, size*6, MAGENTA); + ImageFormat(&faces, image.format); + + // TODO: Image formating does not work with compressed textures! + } + + for (int i = 0; i < 6; i++) ImageDraw(&faces, image, faceRecs[i], (Rectangle){ 0, size*i, size, size }); + + cubemap.id = rlLoadTextureCubemap(faces.data, size, faces.format); + if (cubemap.id == 0) TraceLog(LOG_WARNING, "Cubemap image could not be loaded."); + + UnloadImage(faces); + } + else TraceLog(LOG_WARNING, "Cubemap image layout can not be detected."); + + return cubemap; +} + // Crop an image to area defined by a rectangle // NOTE: Security checks are performed in case rectangle goes out of bounds void ImageCrop(Image *image, Rectangle crop) @@ -1327,6 +1297,38 @@ void ImageCrop(Image *image, Rectangle crop) } } +// Crop image depending on alpha value +void ImageAlphaCrop(Image *image, float threshold) +{ + Color *pixels = GetImageData(*image); + + int xMin = 65536; // Define a big enough number + int xMax = 0; + int yMin = 65536; + int yMax = 0; + + for (int y = 0; y < image->height; y++) + { + for (int x = 0; x < image->width; x++) + { + if (pixels[y*image->width + x].a > (unsigned char)(threshold*255.0f)) + { + if (x < xMin) xMin = x; + if (x > xMax) xMax = x; + if (y < yMin) yMin = y; + if (y > yMax) yMax = y; + } + } + } + + Rectangle crop = { xMin, yMin, (xMax + 1) - xMin, (yMax + 1) - yMin }; + + free(pixels); + + // Check for not empty image brefore cropping + if (!((xMax < xMin) || (yMax < yMin))) ImageCrop(image, crop); +} + // Resize and image to new size // NOTE: Uses stb default scaling filters (both bicubic): // STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM