2
0
Эх сурвалжийг харах

ADDED: Some functions...

text:     IsEqualText() -WIP-
audio:  SaveWAV()
audio:  ExportWaveAsCode()
textures:  ExportImageAsCode()
Ray 6 жил өмнө
parent
commit
298203a41a
5 өөрчлөгдсөн 204 нэмэгдсэн , 97 устгасан
  1. 128 72
      src/audio.c
  2. 3 3
      src/core.c
  3. 6 3
      src/raylib.h
  4. 10 4
      src/text.c
  5. 57 15
      src/textures.c

+ 128 - 72
src/audio.c

@@ -185,7 +185,8 @@ typedef enum {
 // Module specific Functions Declaration
 // Module specific Functions Declaration
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 #if defined(SUPPORT_FILEFORMAT_WAV)
 #if defined(SUPPORT_FILEFORMAT_WAV)
-static Wave LoadWAV(const char *fileName);          // Load WAV file
+static Wave LoadWAV(const char *fileName);              // Load WAV file
+static int SaveWAV(Wave wave, const char *fileName);    // Save wave data as WAV file
 #endif
 #endif
 #if defined(SUPPORT_FILEFORMAT_OGG)
 #if defined(SUPPORT_FILEFORMAT_OGG)
 static Wave LoadOGG(const char *fileName);          // Load OGG file
 static Wave LoadOGG(const char *fileName);          // Load OGG file
@@ -878,82 +879,57 @@ void ExportWave(Wave wave, const char *fileName)
 {
 {
     bool success = false;
     bool success = false;
     
     
-    if (IsFileExtension(fileName, ".wav"))
+    if (IsFileExtension(fileName, ".wav")) success = SaveWAV(wave, fileName);
+    else if (IsFileExtension(fileName, ".raw")) 
     {
     {
-        // Basic WAV headers structs
-        typedef struct {
-            char chunkID[4];
-            int chunkSize;
-            char format[4];
-        } RiffHeader;
-
-        typedef struct {
-            char subChunkID[4];
-            int subChunkSize;
-            short audioFormat;
-            short numChannels;
-            int sampleRate;
-            int byteRate;
-            short blockAlign;
-            short bitsPerSample;
-        } WaveFormat;
-
-        typedef struct {
-            char subChunkID[4];
-            int subChunkSize;
-        } WaveData;
+        // Export raw sample data (without header)
+        // NOTE: It's up to the user to track wave parameters
+        FILE *rawFile = fopen(fileName, "wb");
+        success = fwrite(wave.data, wave.sampleCount*wave.channels*wave.sampleSize/8, 1, rawFile);
+        fclose(rawFile);
+    }
     
     
-        RiffHeader riffHeader;
-        WaveFormat waveFormat;
-        WaveData waveData;
-
-        // Fill structs with data
-        riffHeader.chunkID[0] = 'R';
-        riffHeader.chunkID[1] = 'I';
-        riffHeader.chunkID[2] = 'F';
-        riffHeader.chunkID[3] = 'F';
-        riffHeader.chunkSize = 44 - 4 + wave.sampleCount*wave.sampleSize/8;
-        riffHeader.format[0] = 'W';
-        riffHeader.format[1] = 'A';
-        riffHeader.format[2] = 'V';
-        riffHeader.format[3] = 'E';
-
-        waveFormat.subChunkID[0] = 'f';
-        waveFormat.subChunkID[1] = 'm';
-        waveFormat.subChunkID[2] = 't';
-        waveFormat.subChunkID[3] = ' ';
-        waveFormat.subChunkSize = 16;
-        waveFormat.audioFormat = 1;
-        waveFormat.numChannels = wave.channels;
-        waveFormat.sampleRate = wave.sampleRate;
-        waveFormat.byteRate = wave.sampleRate*wave.sampleSize/8;
-        waveFormat.blockAlign = wave.sampleSize/8;
-        waveFormat.bitsPerSample = wave.sampleSize;
-
-        waveData.subChunkID[0] = 'd';
-        waveData.subChunkID[1] = 'a';
-        waveData.subChunkID[2] = 't';
-        waveData.subChunkID[3] = 'a';
-        waveData.subChunkSize = wave.sampleCount*wave.channels*wave.sampleSize/8;
-
-        FILE *wavFile = fopen(fileName, "wb");
-        
-        if (wavFile == NULL) return;
-
-        fwrite(&riffHeader, 1, sizeof(RiffHeader), wavFile);
-        fwrite(&waveFormat, 1, sizeof(WaveFormat), wavFile);
-        fwrite(&waveData, 1, sizeof(WaveData), wavFile);
+    if (success) TraceLog(LOG_INFO, "Wave exported successfully: %s", fileName);
+    else TraceLog(LOG_WARNING, "Wave could not be exported.");
+}
 
 
-        fwrite(wave.data, 1, wave.sampleCount*wave.channels*wave.sampleSize/8, wavFile);
+// Export wave sample data to code (.h)
+void ExportWaveAsCode(Wave wave, const char *fileName)
+{
+    #define BYTES_TEXT_PER_LINE     20
+    
+    char varFileName[256] = { 0 };
+    int dataSize = wave.sampleCount*wave.channels*wave.sampleSize/8;
+    
+    FILE *txtFile = fopen(fileName, "wt");
+    
+    fprintf(txtFile, "\n//////////////////////////////////////////////////////////////////////////////////\n");
+    fprintf(txtFile, "//                                                                              //\n");
+    fprintf(txtFile, "// WaveAsCode exporter v1.0 - Wave data exported as an array of bytes           //\n");
+    fprintf(txtFile, "//                                                                              //\n");
+    fprintf(txtFile, "// more info and bugs-report:  github.com/raysan5/raylib                        //\n");
+    fprintf(txtFile, "// feedback and support:       ray[at]raylib.com                                //\n");
+    fprintf(txtFile, "//                                                                              //\n");
+    fprintf(txtFile, "// Copyright (c) 2018 Ramon Santamaria (@raysan5)                               //\n");
+    fprintf(txtFile, "//                                                                              //\n");
+    fprintf(txtFile, "//////////////////////////////////////////////////////////////////////////////////\n\n");
+
+    // Get file name from path and convert variable name to uppercase
+    strcpy(varFileName, GetFileNameWithoutExt(fileName));
+    for (int i = 0; varFileName[i] != '\0'; i++) if (varFileName[i] >= 'a' && varFileName[i] <= 'z') { varFileName[i] = varFileName[i] - 32; }
+ 
+    fprintf(txtFile, "// Wave data information\n");
+    fprintf(txtFile, "#define %s_SAMPLE_COUNT     %i\n", varFileName, wave.sampleCount);
+    fprintf(txtFile, "#define %s_SAMPLE_RATE      %i\n", varFileName, wave.sampleRate);
+    fprintf(txtFile, "#define %s_SAMPLE_SIZE      %i\n", varFileName, wave.sampleSize);
+    fprintf(txtFile, "#define %s_CHANNELS         %i\n\n", varFileName, wave.channels);
 
 
-        fclose(wavFile);
-        
-        success = true;
-    }
-    else if (IsFileExtension(fileName, ".raw")) { }   // TODO: Support additional file formats to export wave sample data
+    // Write byte data as hexadecimal text
+    fprintf(txtFile, "static unsigned char %s_DATA[%i] = { ", varFileName, dataSize);
+    for (int i = 0; i < dataSize - 1; i++) fprintf(txtFile, ((i%BYTES_TEXT_PER_LINE == 0) ? "0x%x,\n" : "0x%x, "), ((unsigned char *)wave.data)[i]);
+    fprintf(txtFile, "0x%x };\n", ((unsigned char *)wave.data)[dataSize - 1]);
 
 
-    if (success) TraceLog(LOG_INFO, "Wave exported successfully: %s", fileName);
-    else TraceLog(LOG_WARNING, "Wave could not be exported.");
+    fclose(txtFile);
 }
 }
 
 
 // Play a sound
 // Play a sound
@@ -1739,6 +1715,86 @@ static Wave LoadWAV(const char *fileName)
 
 
     return wave;
     return wave;
 }
 }
+
+// Save wave data as WAV file
+static int SaveWAV(Wave wave, const char *fileName)
+{
+    int success = 0;
+    int dataSize = wave.sampleCount*wave.channels*wave.sampleSize/8;
+    
+    // Basic WAV headers structs
+    typedef struct {
+        char chunkID[4];
+        int chunkSize;
+        char format[4];
+    } RiffHeader;
+
+    typedef struct {
+        char subChunkID[4];
+        int subChunkSize;
+        short audioFormat;
+        short numChannels;
+        int sampleRate;
+        int byteRate;
+        short blockAlign;
+        short bitsPerSample;
+    } WaveFormat;
+
+    typedef struct {
+        char subChunkID[4];
+        int subChunkSize;
+    } WaveData;
+
+    FILE *wavFile = fopen(fileName, "wb");
+    
+    if (wavFile == NULL) TraceLog(LOG_WARNING, "[%s] WAV audio file could not be created", fileName);
+    else
+    {
+        RiffHeader riffHeader;
+        WaveFormat waveFormat;
+        WaveData waveData;
+
+        // Fill structs with data
+        riffHeader.chunkID[0] = 'R';
+        riffHeader.chunkID[1] = 'I';
+        riffHeader.chunkID[2] = 'F';
+        riffHeader.chunkID[3] = 'F';
+        riffHeader.chunkSize = 44 - 4 + wave.sampleCount*wave.sampleSize/8;
+        riffHeader.format[0] = 'W';
+        riffHeader.format[1] = 'A';
+        riffHeader.format[2] = 'V';
+        riffHeader.format[3] = 'E';
+
+        waveFormat.subChunkID[0] = 'f';
+        waveFormat.subChunkID[1] = 'm';
+        waveFormat.subChunkID[2] = 't';
+        waveFormat.subChunkID[3] = ' ';
+        waveFormat.subChunkSize = 16;
+        waveFormat.audioFormat = 1;
+        waveFormat.numChannels = wave.channels;
+        waveFormat.sampleRate = wave.sampleRate;
+        waveFormat.byteRate = wave.sampleRate*wave.sampleSize/8;
+        waveFormat.blockAlign = wave.sampleSize/8;
+        waveFormat.bitsPerSample = wave.sampleSize;
+
+        waveData.subChunkID[0] = 'd';
+        waveData.subChunkID[1] = 'a';
+        waveData.subChunkID[2] = 't';
+        waveData.subChunkID[3] = 'a';
+        waveData.subChunkSize = dataSize;
+    
+        success = fwrite(&riffHeader, sizeof(RiffHeader), 1, wavFile);
+        success = fwrite(&waveFormat, sizeof(WaveFormat), 1, wavFile);
+        success = fwrite(&waveData, sizeof(WaveData), 1, wavFile);
+
+        success = fwrite(wave.data, dataSize, 1, wavFile);
+
+        fclose(wavFile);
+    }
+    
+    // If all data has been written correctly to file, success = 1
+    return success;
+}
 #endif
 #endif
 
 
 #if defined(SUPPORT_FILEFORMAT_OGG)
 #if defined(SUPPORT_FILEFORMAT_OGG)

+ 3 - 3
src/core.c

@@ -1766,11 +1766,11 @@ void StorageSaveValue(int position, int value)
         int fileSize = ftell(storageFile);  // Size in bytes
         int fileSize = ftell(storageFile);  // Size in bytes
         fseek(storageFile, 0, SEEK_SET);
         fseek(storageFile, 0, SEEK_SET);
 
 
-        if (fileSize < (position*4)) TraceLog(LOG_WARNING, "Storage position could not be found");
+        if (fileSize < (position*sizeof(int))) TraceLog(LOG_WARNING, "Storage position could not be found");
         else
         else
         {
         {
-            fseek(storageFile, (position*4), SEEK_SET);
-            fwrite(&value, 1, 4, storageFile);
+            fseek(storageFile, (position*sizeof(int)), SEEK_SET);
+            fwrite(&value, 1, sizeof(int), storageFile);
         }
         }
 
 
         fclose(storageFile);
         fclose(storageFile);

+ 6 - 3
src/raylib.h

@@ -1001,6 +1001,7 @@ RLAPI Image LoadImageEx(Color *pixels, int width, int height);
 RLAPI Image LoadImagePro(void *data, int width, int height, int format);                                 // Load image from raw data with parameters
 RLAPI Image LoadImagePro(void *data, int width, int height, int format);                                 // Load image from raw data with parameters
 RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize);       // Load image from RAW file data
 RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize);       // Load image from RAW file data
 RLAPI void ExportImage(Image image, const char *fileName);                                               // Export image data to file
 RLAPI void ExportImage(Image image, const char *fileName);                                               // Export image data to file
+RLAPI void ExportImageAsCode(Image image, const char *fileName);                                         // Export image as code file defining an array of bytes
 RLAPI Texture2D LoadTexture(const char *fileName);                                                       // Load texture from file into GPU memory (VRAM)
 RLAPI Texture2D LoadTexture(const char *fileName);                                                       // Load texture from file into GPU memory (VRAM)
 RLAPI Texture2D LoadTextureFromImage(Image image);                                                       // Load texture from image data
 RLAPI Texture2D LoadTextureFromImage(Image image);                                                       // Load texture from image data
 RLAPI RenderTexture2D LoadRenderTexture(int width, int height);                                          // Load texture for rendering (framebuffer)
 RLAPI RenderTexture2D LoadRenderTexture(int width, int height);                                          // Load texture for rendering (framebuffer)
@@ -1091,9 +1092,10 @@ RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float s
 RLAPI int GetGlyphIndex(Font font, int character);                                          // Get index position for a unicode character on font
 RLAPI int GetGlyphIndex(Font font, int character);                                          // Get index position for a unicode character on font
 
 
 // Text string edition functions
 // Text string edition functions
-RLAPI const char *FormatText(const char *text, ...);                    // Formatting of text with variables to 'embed'
-RLAPI const char *SubText(const char *text, int position, int length);  // Get a piece of a text string
-RLAPI char **SplitText(char *text, char delimiter, int *strCount);      // Split text string into multiple strings (memory should be freed manually!)
+RLAPI const char *FormatText(const char *text, ...);                        // Formatting of text with variables to 'embed'
+RLAPI const char *SubText(const char *text, int position, int length);      // Get a piece of a text string
+RLAPI char **SplitText(char *text, char delimiter, int *strCount);          // Split text string into multiple strings (memory should be freed manually!)
+RLAPI bool IsEqualText(const char *text1, const char *text2);               // Check if two text string are equal
 
 
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
 // Basic 3d Shapes Drawing Functions (Module: models)
 // Basic 3d Shapes Drawing Functions (Module: models)
@@ -1238,6 +1240,7 @@ RLAPI void UpdateSound(Sound sound, const void *data, int samplesCount);// Updat
 RLAPI void UnloadWave(Wave wave);                                     // Unload wave data
 RLAPI void UnloadWave(Wave wave);                                     // Unload wave data
 RLAPI void UnloadSound(Sound sound);                                  // Unload sound
 RLAPI void UnloadSound(Sound sound);                                  // Unload sound
 RLAPI void ExportWave(Wave wave, const char *fileName);               // Export wave data to file
 RLAPI void ExportWave(Wave wave, const char *fileName);               // Export wave data to file
+RLAPI void ExportWaveAsCode(Wave wave, const char *fileName);         // Export wave sample data to code (.h)
 
 
 // Wave/Sound management functions
 // Wave/Sound management functions
 RLAPI void PlaySound(Sound sound);                                    // Play a sound
 RLAPI void PlaySound(Sound sound);                                    // Play a sound

+ 10 - 4
src/text.c

@@ -190,10 +190,6 @@ extern void LoadDefaultFont(void)
         if (counter > 512) counter = 0;         // Security check...
         if (counter > 512) counter = 0;         // Security check...
     }
     }
 
 
-    //FILE *myimage = fopen("default_font.raw", "wb");
-    //fwrite(image.pixels, 1, 128*128*4, myimage);
-    //fclose(myimage);
-
     Image image = LoadImageEx(imagePixels, imWidth, imHeight);
     Image image = LoadImageEx(imagePixels, imWidth, imHeight);
     ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
     ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
 
 
@@ -823,6 +819,16 @@ char **SplitText(char *text, char delimiter, int *strCount)
     return strings;
     return strings;
 }
 }
 
 
+// Check if two text string are equal
+bool IsEqualText(const char *text1, const char *text2)
+{
+    bool result = false;
+    
+    if (strcmp(text1, text2) == 0) result = true;
+    
+    return result;
+}
+
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module specific Functions Definition
 // Module specific Functions Definition
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------

+ 57 - 15
src/textures.c

@@ -60,7 +60,7 @@
 #include "raylib.h"             // Declares module functions
 #include "raylib.h"             // Declares module functions
 
 
 #include <stdlib.h>             // Required for: malloc(), free()
 #include <stdlib.h>             // Required for: malloc(), free()
-#include <string.h>             // Required for: strcmp(), strrchr(), strncmp()
+#include <string.h>             // Required for: strlen()
 
 
 #include "rlgl.h"               // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2
 #include "rlgl.h"               // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2
                                 // Required for: rlLoadTexture() rlDeleteTextures(),
                                 // Required for: rlLoadTexture() rlDeleteTextures(),
@@ -147,8 +147,8 @@ static Image LoadDDS(const char *fileName);   // Load DDS file
 static Image LoadPKM(const char *fileName);   // Load PKM file
 static Image LoadPKM(const char *fileName);   // Load PKM file
 #endif
 #endif
 #if defined(SUPPORT_FILEFORMAT_KTX)
 #if defined(SUPPORT_FILEFORMAT_KTX)
-static Image LoadKTX(const char *fileName);   // Load KTX file
-static void SaveKTX(Image image, const char *fileName); // Save image data as KTX file
+static Image LoadKTX(const char *fileName);             // Load KTX file
+static int SaveKTX(Image image, const char *fileName);  // Save image data as KTX file
 #endif
 #endif
 #if defined(SUPPORT_FILEFORMAT_PVR)
 #if defined(SUPPORT_FILEFORMAT_PVR)
 static Image LoadPVR(const char *fileName);   // Load PVR file
 static Image LoadPVR(const char *fileName);   // Load PVR file
@@ -728,23 +728,60 @@ void ExportImage(Image image, const char *fileName)
     else if (IsFileExtension(fileName, ".bmp")) success = stbi_write_bmp(fileName, image.width, image.height, 4, imgData);
     else if (IsFileExtension(fileName, ".bmp")) success = stbi_write_bmp(fileName, image.width, image.height, 4, imgData);
     else if (IsFileExtension(fileName, ".tga")) success = stbi_write_tga(fileName, image.width, image.height, 4, imgData);
     else if (IsFileExtension(fileName, ".tga")) success = stbi_write_tga(fileName, image.width, image.height, 4, imgData);
     else if (IsFileExtension(fileName, ".jpg")) success = stbi_write_jpg(fileName, image.width, image.height, 4, imgData, 80);  // JPG quality: between 1 and 100
     else if (IsFileExtension(fileName, ".jpg")) success = stbi_write_jpg(fileName, image.width, image.height, 4, imgData, 80);  // JPG quality: between 1 and 100
-    else if (IsFileExtension(fileName, ".ktx")) SaveKTX(image, fileName);
+    else if (IsFileExtension(fileName, ".ktx")) success = SaveKTX(image, fileName);
     else if (IsFileExtension(fileName, ".raw")) 
     else if (IsFileExtension(fileName, ".raw")) 
     {
     {
         // Export raw pixel data (without header)
         // Export raw pixel data (without header)
         // NOTE: It's up to the user to track image parameters
         // NOTE: It's up to the user to track image parameters
         FILE *rawFile = fopen(fileName, "wb");
         FILE *rawFile = fopen(fileName, "wb");
-        fwrite(image.data, GetPixelDataSize(image.width, image.height, image.format), 1, rawFile);
+        success = fwrite(image.data, GetPixelDataSize(image.width, image.height, image.format), 1, rawFile);
         fclose(rawFile);
         fclose(rawFile);
     }
     }
-    else if (IsFileExtension(fileName, ".h")) { }    // TODO: Export pixel data as an array of bytes
-    
+
     if (success != 0) TraceLog(LOG_INFO, "Image exported successfully: %s", fileName);
     if (success != 0) TraceLog(LOG_INFO, "Image exported successfully: %s", fileName);
     else TraceLog(LOG_WARNING, "Image could not be exported.");
     else TraceLog(LOG_WARNING, "Image could not be exported.");
     
     
     free(imgData);
     free(imgData);
 }
 }
 
 
+// Export image as code file (.h) defining an array of bytes
+void ExportImageAsCode(Image image, const char *fileName)
+{
+    #define BYTES_TEXT_PER_LINE     20
+    
+    char varFileName[256] = { 0 };
+    int dataSize = GetPixelDataSize(image.width, image.height, image.format);
+    
+    FILE *txtFile = fopen(fileName, "wt");
+
+    fprintf(txtFile, "\n//////////////////////////////////////////////////////////////////////////////////////\n");
+    fprintf(txtFile, "//                                                                                    //\n");
+    fprintf(txtFile, "// ImageAsCode exporter v1.0 - Image pixel data exported as an array of bytes         //\n");
+    fprintf(txtFile, "//                                                                                    //\n");
+    fprintf(txtFile, "// more info and bugs-report:  github.com/raysan5/raylib                              //\n");
+    fprintf(txtFile, "// feedback and support:       ray[at]raylib.com                                      //\n");
+    fprintf(txtFile, "//                                                                                    //\n");
+    fprintf(txtFile, "// Copyright (c) 2018 Ramon Santamaria (@raysan5)                                     //\n");
+    fprintf(txtFile, "//                                                                                    //\n");
+    fprintf(txtFile, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
+    
+    // Get file name from path and convert variable name to uppercase
+    strcpy(varFileName, GetFileNameWithoutExt(fileName));
+    for (int i = 0; varFileName[i] != '\0'; i++) if (varFileName[i] >= 'a' && varFileName[i] <= 'z') { varFileName[i] = varFileName[i] - 32; }
+ 
+    // Add image information
+    fprintf(txtFile, "// Image data information\n");
+    fprintf(txtFile, "#define %s_WIDTH    %i\n", varFileName, image.width);
+    fprintf(txtFile, "#define %s_HEIGHT   %i\n", varFileName, image.height);
+    fprintf(txtFile, "#define %s_FORMAT   %i          // raylib internal pixel format\n\n", varFileName, image.format);
+
+    fprintf(txtFile, "static unsigned char %s_DATA[%i] = { ", varFileName, dataSize);
+    for (int i = 0; i < dataSize - 1; i++) fprintf(txtFile, ((i%BYTES_TEXT_PER_LINE == 0) ? "0x%x,\n" : "0x%x, "), ((unsigned char *)image.data)[i]);
+    fprintf(txtFile, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
+
+    fclose(txtFile);
+}
+
 // Copy an image to a new image
 // Copy an image to a new image
 Image ImageCopy(Image image)
 Image ImageCopy(Image image)
 {
 {
@@ -2669,11 +2706,11 @@ static Image LoadDDS(const char *fileName)
     else
     else
     {
     {
         // Verify the type of file
         // Verify the type of file
-        char filecode[4];
+        char ddsHeaderId[4];
 
 
-        fread(filecode, 4, 1, ddsFile);
+        fread(ddsHeaderId, 4, 1, ddsFile);
 
 
-        if (strncmp(filecode, "DDS ", 4) != 0)
+        if ((ddsHeaderId[0] != 'D') || (ddsHeaderId[1] != 'D') || (ddsHeaderId[2] != 'S') || (ddsHeaderId[3] != ' '))
         {
         {
             TraceLog(LOG_WARNING, "[%s] DDS file does not seem to be a valid image", fileName);
             TraceLog(LOG_WARNING, "[%s] DDS file does not seem to be a valid image", fileName);
         }
         }
@@ -2853,7 +2890,7 @@ static Image LoadPKM(const char *fileName)
         // Get the image header
         // Get the image header
         fread(&pkmHeader, sizeof(PKMHeader), 1, pkmFile);
         fread(&pkmHeader, sizeof(PKMHeader), 1, pkmFile);
 
 
-        if (strncmp(pkmHeader.id, "PKM ", 4) != 0)
+        if ((pkmHeader.id[0] != 'P') || (pkmHeader.id[1] != 'K') || (pkmHeader.id[2] != 'M') || (ddsHeaderId[3] != ' '))
         {
         {
             TraceLog(LOG_WARNING, "[%s] PKM file does not seem to be a valid image", fileName);
             TraceLog(LOG_WARNING, "[%s] PKM file does not seem to be a valid image", fileName);
         }
         }
@@ -2988,8 +3025,10 @@ static Image LoadKTX(const char *fileName)
 
 
 // Save image data as KTX file
 // Save image data as KTX file
 // NOTE: By default KTX 1.1 spec is used, 2.0 is still on draft (01Oct2018)
 // NOTE: By default KTX 1.1 spec is used, 2.0 is still on draft (01Oct2018)
-static void SaveKTX(Image image, const char *fileName)
+static int SaveKTX(Image image, const char *fileName)
 {
 {
+    int success = 0;
+    
     // KTX file Header (64 bytes)
     // KTX file Header (64 bytes)
     // v1.1 - https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
     // v1.1 - https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
     // v2.0 - http://github.khronos.org/KTX-Specification/ - still on draft, not ready for implementation
     // v2.0 - http://github.khronos.org/KTX-Specification/ - still on draft, not ready for implementation
@@ -3050,7 +3089,7 @@ static void SaveKTX(Image image, const char *fileName)
         if (ktxHeader.glFormat == -1) TraceLog(LOG_WARNING, "Image format not supported for KTX export.");
         if (ktxHeader.glFormat == -1) TraceLog(LOG_WARNING, "Image format not supported for KTX export.");
         else
         else
         {
         {
-            fwrite(&ktxHeader, 1, sizeof(KTXHeader), ktxFile);
+            success = fwrite(&ktxHeader, sizeof(KTXHeader), 1, ktxFile);
             
             
             int width = image.width;
             int width = image.width;
             int height = image.height;
             int height = image.height;
@@ -3060,8 +3099,8 @@ static void SaveKTX(Image image, const char *fileName)
             for (int i = 0; i < image.mipmaps; i++)
             for (int i = 0; i < image.mipmaps; i++)
             {
             {
                 unsigned int dataSize = GetPixelDataSize(width, height, image.format);
                 unsigned int dataSize = GetPixelDataSize(width, height, image.format);
-                fwrite(&dataSize, 1, sizeof(unsigned int), ktxFile);
-                fwrite((unsigned char *)image.data + dataOffset, 1, dataSize, ktxFile);
+                success = fwrite(&dataSize, sizeof(unsigned int), 1, ktxFile);
+                success = fwrite((unsigned char *)image.data + dataOffset, dataSize, 1, ktxFile);
                 
                 
                 width /= 2;
                 width /= 2;
                 height /= 2;
                 height /= 2;
@@ -3071,6 +3110,9 @@ static void SaveKTX(Image image, const char *fileName)
 
 
         fclose(ktxFile);    // Close file pointer
         fclose(ktxFile);    // Close file pointer
     }
     }
+    
+    // If all data has been written correctly to file, success = 1
+    return success;
 }
 }
 #endif
 #endif