created ImageMaskFromImage and LoadTextureMaskFromImage

These functions adds the possibility to retrieve a mask from the alpha
channel of an image.
This commit is contained in:
Bruno Cabral 2024-06-24 08:50:51 -07:00
parent c7bda3d10f
commit 1fc3072275
3 changed files with 130 additions and 15 deletions

View File

@ -0,0 +1,68 @@
/*******************************************************************************************
*
* raylib [textures] example - Retrive image mask from alpha values
*
* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM)
*
* Example originally created with raylib 5.1-dev, last time updated with raylib 5.1-dev
*
* Example contributed by Bruno Cabral (github.com/brccabral) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2024-2024 Bruno Cabral (github.com/brccabral) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include <raylib.h>
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 612;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - draw rectangle rounded");
Image fudesumi_image = LoadImage("resources/fudesumi.png");
Texture2D fudesumi_texture = LoadTextureFromImage(fudesumi_image);
Texture2D fudesumi_mask = LoadTextureMaskFromImage(fudesumi_image, RED, 0.0f);
Image background_image = GenImageChecked(screenWidth, screenHeight, screenWidth/20, screenHeight/20, BLUE, SKYBLUE);
Texture2D background_texture = LoadTextureFromImage(background_image);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
DrawTexture(background_texture, 0, 0, WHITE);
DrawTexture(fudesumi_texture, 50, 50, WHITE);
DrawTexture(fudesumi_mask, 410, 50, WHITE);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadImage(fudesumi_image);
UnloadImage(background_image);
UnloadTexture(fudesumi_texture);
UnloadTexture(fudesumi_mask);
UnloadTexture(background_texture);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1334,6 +1334,7 @@ RLAPI Image ImageCopy(Image image);
RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece
RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font)
RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font) RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font)
RLAPI Image ImageMaskFromImage(Image image, Color color, float threshold); // Create an image mask from an image (alpha channel)
RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
RLAPI void ImageToPOT(Image *image, Color fill); // Convert image to POT (power-of-two) RLAPI void ImageToPOT(Image *image, Color fill); // Convert image to POT (power-of-two)
RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle
@ -1394,6 +1395,7 @@ RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 posi
// NOTE: These functions require GPU access // NOTE: These functions require GPU access
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 Texture2D LoadTextureMaskFromImage(Image image, Color color, float threshold); // Load texture mask from image data (alpha channel)
RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported
RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer) RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
RLAPI bool IsTextureReady(Texture2D texture); // Check if a texture is ready RLAPI bool IsTextureReady(Texture2D texture); // Check if a texture is ready

View File

@ -1630,6 +1630,44 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
return imText; return imText;
} }
Image ImageMaskFromImage(const Image image, const Color color, float threshold)
{
Image mask = { 0 };
// Security check to avoid program crash
if ((image.data == NULL) || (image.width == 0) || (image.height == 0))
return mask;
// Set threshold to at least 0.0f
if (threshold < 0.0f) {
threshold = 0.0f;
}
Vector4 *pixels = LoadImageDataNormalized(image);
mask.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
mask.height = image.height;
mask.width = image.width;
mask.mipmaps = 1;
Color *new_pixels = (Color *) RL_CALLOC(image.width * image.height, sizeof(Color));
for (int i = 0; i < mask.width * mask.height; i++)
{
if (pixels[i].w > threshold)
new_pixels[i] = color;
else
new_pixels[i] = (Color) { 0 };
}
mask.data = new_pixels;
RL_FREE(pixels);
pixels = NULL;
return mask;
}
// Resize and image to new size using Nearest-Neighbor scaling algorithm // Resize and image to new size using Nearest-Neighbor scaling algorithm
void ImageResizeNN(Image *image,int newWidth,int newHeight) void ImageResizeNN(Image *image,int newWidth,int newHeight)
{ {
@ -3979,15 +4017,14 @@ Texture2D LoadTexture(const char *fileName)
// Load a texture from image data // Load a texture from image data
// NOTE: image is not unloaded, it must be done manually // NOTE: image is not unloaded, it must be done manually
Texture2D LoadTextureFromImage(Image image) Texture2D LoadTextureFromImage(Image image) {
{ Texture2D texture = {0};
Texture2D texture = { 0 };
if ((image.width != 0) && (image.height != 0)) if ((image.width != 0) && (image.height != 0)) {
{ texture.id = rlLoadTexture(image.data, image.width, image.height,
texture.id = rlLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps); image.format, image.mipmaps);
} } else
else TRACELOG(LOG_WARNING, "IMAGE: Data is not valid to load texture"); TRACELOG(LOG_WARNING, "IMAGE: Data is not valid to load texture");
texture.width = image.width; texture.width = image.width;
texture.height = image.height; texture.height = image.height;
@ -3997,6 +4034,14 @@ Texture2D LoadTextureFromImage(Image image)
return texture; return texture;
} }
Texture2D LoadTextureMaskFromImage(Image image, Color color, float threshold)
{
const Image mask = ImageMaskFromImage(image, color, threshold);
const Texture result = LoadTextureFromImage(mask);
UnloadImage(mask);
return result;
}
// Load cubemap from image, multiple image cubemap layouts supported // Load cubemap from image, multiple image cubemap layouts supported
TextureCubemap LoadTextureCubemap(Image image, int layout) TextureCubemap LoadTextureCubemap(Image image, int layout)
{ {