diff options
| author | raysan5 <raysan5@gmail.com> | 2015-07-05 18:21:01 +0200 |
|---|---|---|
| committer | raysan5 <raysan5@gmail.com> | 2015-07-05 18:21:01 +0200 |
| commit | c944d62374859707404ff3ac5f2c6b3babfafa9f (patch) | |
| tree | d4495f5f5b0bd0101aae8d46c17730cdc2ccc85f /src/textures.c | |
| parent | 84befaea2467879e9fd01b0728e328f7d2497405 (diff) | |
| download | raylib-c944d62374859707404ff3ac5f2c6b3babfafa9f.tar.gz raylib-c944d62374859707404ff3ac5f2c6b3babfafa9f.zip | |
Improved mipmaps support and image loading
Diffstat (limited to 'src/textures.c')
| -rw-r--r-- | src/textures.c | 348 |
1 files changed, 225 insertions, 123 deletions
diff --git a/src/textures.c b/src/textures.c index e6c6cccb..42c7810b 100644 --- a/src/textures.c +++ b/src/textures.c @@ -123,6 +123,32 @@ Image LoadImage(const char *fileName) return image; } +// Load image data from Color array data (RGBA - 32bit) +Image LoadImageEx(Color *pixels, int width, int height) +{ + Image image; + image.data = NULL; + image.width = width; + image.height = height; + image.mipmaps = 1; + image.format = UNCOMPRESSED_R8G8B8A8; + + int k = 0; + + image.data = (unsigned char *)malloc(image.width*image.height*4*sizeof(unsigned char)); + + for (int i = 0; i < image.width*image.height*4; i += 4) + { + ((unsigned char *)image.data)[i] = pixels[k].r; + ((unsigned char *)image.data)[i + 1] = pixels[k].g; + ((unsigned char *)image.data)[i + 2] = pixels[k].b; + ((unsigned char *)image.data)[i + 3] = pixels[k].a; + k++; + } + + return image; +} + // Load an image from rRES file (raylib Resource) // TODO: Review function to support multiple color modes Image LoadImageFromRES(const char *rresName, int resId) @@ -243,12 +269,12 @@ Texture2D LoadTexture(const char *fileName) Image image = LoadImage(fileName); #if defined(PLATFORM_RPI) || defined(PLATFORM_WEB) - ConvertToPOT(&image, BLANK); + ImageConvertToPOT(&image, BLANK); #endif if (image.data != NULL) { - texture = LoadTextureFromImage(image, false); + texture = LoadTextureFromImage(image); UnloadImage(image); } else @@ -261,7 +287,7 @@ Texture2D LoadTexture(const char *fileName) return texture; } -Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps) +Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount) { Texture2D texture; @@ -270,14 +296,14 @@ Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, in texture.mipmaps = mipmapCount; texture.format = textureFormat; - texture.id = rlglLoadTexture(data, width, height, textureFormat, mipmapCount, genMipmaps); + texture.id = rlglLoadTexture(data, width, height, textureFormat, mipmapCount); return texture; } // Load a texture from image data // NOTE: image is not unloaded, it must be done manually -Texture2D LoadTextureFromImage(Image image, bool genMipmaps) +Texture2D LoadTextureFromImage(Image image) { Texture2D texture; @@ -288,7 +314,7 @@ Texture2D LoadTextureFromImage(Image image, bool genMipmaps) texture.mipmaps = 0; texture.format = 0; - texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps, false); + texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps); texture.width = image.width; texture.height = image.height; @@ -304,7 +330,7 @@ Texture2D LoadTextureFromRES(const char *rresName, int resId) Texture2D texture; Image image = LoadImageFromRES(rresName, resId); - texture = LoadTextureFromImage(image, false); + texture = LoadTextureFromImage(image); UnloadImage(image); return texture; @@ -324,7 +350,7 @@ void UnloadTexture(Texture2D texture) // Convert image to POT (power-of-two) // NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5) -void ConvertToPOT(Image *image, Color fillColor) +void ImageConvertToPOT(Image *image, Color fillColor) { // TODO: Review for new image struct /* @@ -447,142 +473,172 @@ Color *GetPixelData(Image image) return pixels; } -// Fill image data with pixels Color data (RGBA - 32bit) -// NOTE: Data is transformed to desired format -Image LoadImageFromData(Color *pixels, int width, int height, int format) +// Get pixel data from GPU texture and return an Image +Image GetTextureData(Texture2D texture) { Image image; - image.data = NULL; - image.width = width; - image.height = height; - image.mipmaps = 1; - image.format = format; - - int k = 0; - switch (format) + image.data = rlglReadTexturePixels(texture.id, texture.format); + + if (image.data != NULL) { - case UNCOMPRESSED_GRAYSCALE: - { - image.data = (unsigned char *)malloc(image.width*image.height*sizeof(unsigned char)); - - for (int i = 0; i < image.width*image.height; i++) - { - ((unsigned char *)image.data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f); - k++; - } + image.width = texture.width; + image.height = texture.height; + image.format = texture.format; + image.mipmaps = 1; + } + else TraceLog(WARNING, "Texture pixel data could not be obtained"); - } break; - case UNCOMPRESSED_GRAY_ALPHA: + return image; +} + +// Convert image data to desired format +void ImageConvertFormat(Image *image, int newFormat) +{ + if ((image->format != newFormat) && (image->format < 8) && (newFormat < 8)) + { + Color *pixels = GetPixelData(*image); + + free(image->data); + + image->format = newFormat; + + int k = 0; + + switch (image->format) { - image.data = (unsigned char *)malloc(image.width*image.height*2*sizeof(unsigned char)); - - for (int i = 0; i < image.width*image.height*2; i += 2) + case UNCOMPRESSED_GRAYSCALE: { - ((unsigned char *)image.data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f); - ((unsigned char *)image.data)[i + 1] = pixels[k].a; - k++; - } + image->data = (unsigned char *)malloc(image->width*image->height*sizeof(unsigned char)); + + for (int i = 0; i < image->width*image->height; i++) + { + ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f); + k++; + } + + } break; + case UNCOMPRESSED_GRAY_ALPHA: + { + image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char)); + + for (int i = 0; i < image->width*image->height*2; i += 2) + { + ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f); + ((unsigned char *)image->data)[i + 1] = pixels[k].a; + k++; + } - } break; - case UNCOMPRESSED_R5G6B5: - { - image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short)); - - unsigned char r; - unsigned char g; - unsigned char b; - - for (int i = 0; i < image.width*image.height; i++) + } break; + case UNCOMPRESSED_R5G6B5: { - r = (unsigned char)(round((float)pixels[k].r*31/255)); - g = (unsigned char)(round((float)pixels[k].g*63/255)); - b = (unsigned char)(round((float)pixels[k].b*31/255)); + image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - ((unsigned short *)image.data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b; + unsigned char r; + unsigned char g; + unsigned char b; + + for (int i = 0; i < image->width*image->height; i++) + { + r = (unsigned char)(round((float)pixels[k].r*31/255)); + g = (unsigned char)(round((float)pixels[k].g*63/255)); + b = (unsigned char)(round((float)pixels[k].b*31/255)); + + ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b; - k++; - } + k++; + } - } break; - case UNCOMPRESSED_R8G8B8: - { - image.data = (unsigned char *)malloc(image.width*image.height*3*sizeof(unsigned char)); - - for (int i = 0; i < image.width*image.height*3; i += 3) + } break; + case UNCOMPRESSED_R8G8B8: { - ((unsigned char *)image.data)[i] = pixels[k].r; - ((unsigned char *)image.data)[i + 1] = pixels[k].g; - ((unsigned char *)image.data)[i + 2] = pixels[k].b; - k++; - } - } break; - case UNCOMPRESSED_R5G5B5A1: - { - image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short)); - - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char a = 1; - - for (int i = 0; i < image.width*image.height; i++) + image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char)); + + for (int i = 0; i < image->width*image->height*3; i += 3) + { + ((unsigned char *)image->data)[i] = pixels[k].r; + ((unsigned char *)image->data)[i + 1] = pixels[k].g; + ((unsigned char *)image->data)[i + 2] = pixels[k].b; + k++; + } + } break; + case UNCOMPRESSED_R5G5B5A1: { - r = (unsigned char)(round((float)pixels[k].r*31/255)); - g = (unsigned char)(round((float)pixels[k].g*31/255)); - b = (unsigned char)(round((float)pixels[k].b*31/255)); - a = (pixels[k].a > 50) ? 1 : 0; + image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - ((unsigned short *)image.data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a; - - k++; - } + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a = 1; + + for (int i = 0; i < image->width*image->height; i++) + { + r = (unsigned char)(round((float)pixels[k].r*31/255)); + g = (unsigned char)(round((float)pixels[k].g*31/255)); + b = (unsigned char)(round((float)pixels[k].b*31/255)); + a = (pixels[k].a > 50) ? 1 : 0; + + ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a; + + k++; + } - } break; - case UNCOMPRESSED_R4G4B4A4: - { - image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short)); - - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char a; - - for (int i = 0; i < image.width*image.height; i++) + } break; + case UNCOMPRESSED_R4G4B4A4: { - r = (unsigned char)(round((float)pixels[k].r*15/255)); - g = (unsigned char)(round((float)pixels[k].g*15/255)); - b = (unsigned char)(round((float)pixels[k].b*15/255)); - a = (unsigned char)(round((float)pixels[k].a*15/255)); + image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - ((unsigned short *)image.data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a; - - k++; - } - - } break; - case UNCOMPRESSED_R8G8B8A8: - { - image.data = (unsigned char *)malloc(image.width*image.height*4*sizeof(unsigned char)); - - for (int i = 0; i < image.width*image.height*4; i += 4) + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + + for (int i = 0; i < image->width*image->height; i++) + { + r = (unsigned char)(round((float)pixels[k].r*15/255)); + g = (unsigned char)(round((float)pixels[k].g*15/255)); + b = (unsigned char)(round((float)pixels[k].b*15/255)); + a = (unsigned char)(round((float)pixels[k].a*15/255)); + + ((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a; + + k++; + } + + } break; + case UNCOMPRESSED_R8G8B8A8: { - ((unsigned char *)image.data)[i] = pixels[k].r; - ((unsigned char *)image.data)[i + 1] = pixels[k].g; - ((unsigned char *)image.data)[i + 2] = pixels[k].b; - ((unsigned char *)image.data)[i + 3] = pixels[k].a; - k++; - } - } break; - default: - { - TraceLog(WARNING, "Format not recognized, image could not be loaded"); - - return image; - } break; + image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char)); + + for (int i = 0; i < image->width*image->height*4; i += 4) + { + ((unsigned char *)image->data)[i] = pixels[k].r; + ((unsigned char *)image->data)[i + 1] = pixels[k].g; + ((unsigned char *)image->data)[i + 2] = pixels[k].b; + ((unsigned char *)image->data)[i + 3] = pixels[k].a; + k++; + } + } break; + default: break; + } + + free(pixels); } + else TraceLog(WARNING, "Image data format is compressed, can not be converted"); +} - return image; +/* +Image ImageCopy(Image image); +void ImageCrop(Image *image, Rectangle crop); +void ImageResize(Image *image, int newWidth, int newHeight); +void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); +void ImageDrawText(Image *dst, const char *text, Vector2 position, int size, Color color); +*/ + +// Generate GPU mipmaps for a texture +void GenTextureMipmaps(Texture2D texture) +{ + rlglGenerateMipmaps(texture.id); } // Draw a Texture2D @@ -1224,6 +1280,8 @@ static Image LoadASTC(const char *fileName) // NOTE: Assuming Little Endian (could it be wrong?) image.width = 0x00000000 | ((int)header.width[2] << 16) | ((int)header.width[1] << 8) | ((int)header.width[0]); image.height = 0x00000000 | ((int)header.height[2] << 16) | ((int)header.height[1] << 8) | ((int)header.height[0]); + + // NOTE: ASTC format only contains one mipmap level image.mipmaps = 1; TraceLog(DEBUG, "ASTC image width: %i", image.width); @@ -1251,4 +1309,48 @@ static Image LoadASTC(const char *fileName) } return image; +} + +// Load RAW image file +static Image LoadRAW(const char *fileName, int width, int height, int format, int headerSize) +{ + Image image; + + image.data = NULL; + image.width = 0; + image.height = 0; + image.mipmaps = 0; + image.format = 0; + + FILE *rawFile = fopen(fileName, "rb"); + + if (rawFile == NULL) + { + TraceLog(WARNING, "[%s] RAW image file could not be opened", fileName); + } + else + { + if (headerSize > 0) fseek(rawFile, headerSize, SEEK_SET); + + int dataSize = 0; + + // TODO: Calculate data size and allocate memory + switch (format) + { + + } + + fread(image.data, dataSize, 1, rawFile); + + // TODO: Check if data have been read + + image.width = width; + image.height = height; + image.mipmaps = 0; + image.format = format; + + fclose(rawFile); + } + + return image; }
\ No newline at end of file |
