From 13e5dae3160aac7d401f72c0c59fe1021ec64818 Mon Sep 17 00:00:00 2001 From: Ray San Date: Wed, 23 May 2018 13:24:21 +0200 Subject: [PATCH] Renamed folder and reviewed sample Working on generated raw importer --- {examples => design}/window_mockup.png | Bin .../image_2x2_RGBA.raw | Bin .../image_raw_importer/image_raw_importer.c | 191 ++++++++++++++++++ .../image_raw_importer.old.c} | 24 +-- .../raw_importer_REF.png | Bin .../raw_importer_REV0.png | Bin .../raw_importer_REV1.png | Bin .../raw_importer_REV2.png | Bin .../raw_importer_REV3.png | Bin .../raw_importer_REV4.png | Bin .../image_raw_importer/raw_importer_REV5.png | Bin 0 -> 6581 bytes 11 files changed, 203 insertions(+), 12 deletions(-) rename {examples => design}/window_mockup.png (100%) rename examples/{raw_importer => image_raw_importer}/image_2x2_RGBA.raw (100%) create mode 100644 examples/image_raw_importer/image_raw_importer.c rename examples/{raw_importer/raw_importer.c => image_raw_importer/image_raw_importer.old.c} (94%) rename examples/{raw_importer => image_raw_importer}/raw_importer_REF.png (100%) rename examples/{raw_importer => image_raw_importer}/raw_importer_REV0.png (100%) rename examples/{raw_importer => image_raw_importer}/raw_importer_REV1.png (100%) rename examples/{raw_importer => image_raw_importer}/raw_importer_REV2.png (100%) rename examples/{raw_importer => image_raw_importer}/raw_importer_REV3.png (100%) rename examples/{raw_importer => image_raw_importer}/raw_importer_REV4.png (100%) create mode 100644 examples/image_raw_importer/raw_importer_REV5.png diff --git a/examples/window_mockup.png b/design/window_mockup.png similarity index 100% rename from examples/window_mockup.png rename to design/window_mockup.png diff --git a/examples/raw_importer/image_2x2_RGBA.raw b/examples/image_raw_importer/image_2x2_RGBA.raw similarity index 100% rename from examples/raw_importer/image_2x2_RGBA.raw rename to examples/image_raw_importer/image_2x2_RGBA.raw diff --git a/examples/image_raw_importer/image_raw_importer.c b/examples/image_raw_importer/image_raw_importer.c new file mode 100644 index 0000000..28af480 --- /dev/null +++ b/examples/image_raw_importer/image_raw_importer.c @@ -0,0 +1,191 @@ +/******************************************************************************************* +* +* raw_importer - image raw importer +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2018 raylib technologies +* +**********************************************************************************************/ + +#include "raylib.h" + +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" + +#include // Required for: strcpy() +#include // Required for: atoi() + +//---------------------------------------------------------------------------------- +// Controls Functions Declaration +//---------------------------------------------------------------------------------- +static void ImportRAW(); // Button: ImportRAW logic + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //--------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 600; + + InitWindow(screenWidth, screenHeight, "Image RAW Importer"); + + Texture2D texture = { 0 }; + + // raw_importer: controls initialization + //---------------------------------------------------------------------------------- + Vector2 windowOffset = { screenWidth/2 - 200/2, screenHeight/2 - 465/2 }; + + bool importWindowActive = false; + int widthValue = 0; + int heightValue = 0; + int pixelFormatActive = 0; + const char *pixelFormatTextList[3] = { "ONE", "TWO", "THREE" }; + int channelsActive = 0; + const char *channelsTextList[4] = { "1", "2", "3", "4" }; + int bitDepthActive = 0; + const char *bitDepthTextList[3] = { "8", "16", "32" }; + int headerSizeValue = 0; + //---------------------------------------------------------------------------------- + + // Image file info + int dataSize = 0; + char fileName[32] = "\0"; + + bool btnLoadPressed = false; + + bool imageLoaded = false; + float imageScale = 1.0f; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // Check if a file is dropped + if (IsFileDropped()) + { + int fileCount = 0; + char **droppedFiles = GetDroppedFiles(&fileCount); + + // Check file extensions for drag-and-drop + if ((fileCount == 1) && IsFileExtension(droppedFiles[0], ".raw")) + { + FILE *imageFile = fopen(droppedFiles[0], "rb"); + fseek(imageFile, 0L, SEEK_END); + dataSize = ftell(imageFile); + fclose(imageFile); + + // NOTE: Returned string is just a pointer to droppedFiles[0], + // we need to make a copy of that data somewhere else: fileName + strcpy(fileName, GetFileName(droppedFiles[0])); + + // Try to guess possible raw values + // Let's assume image is square, RGBA, 8 bit per channel + widthValue = round(sqrt(dataSize/4)); + heightValue = widthValue; + headerSizeValue = dataSize - widthValue*heightValue*4; + + importWindowActive = true; + } + + ClearDroppedFiles(); + } + + // Check if load button has been pressed + if (btnLoadPressed) + { + // Convert input textImageWidth, textImageHeight to int + + int format = UNCOMPRESSED_R8G8B8A8; + int channels = atoi(channelsTextList[channelsActive]); + int bpp = atoi(bitDepthTextList[bitDepthActive]); + + // Depending on channels and bit depth, select correct pixel format + if ((widthValue != 0) && (heightValue != 0) && (bpp == 8)) + { + switch (channels) + { + case 1: format = UNCOMPRESSED_GRAYSCALE; break; + case 2: format = UNCOMPRESSED_GRAY_ALPHA; break; + case 3: format = UNCOMPRESSED_R8G8B8; break; + case 4: format = UNCOMPRESSED_R8G8B8A8; break; + default: break; + } + + Image image = LoadImageRaw(fileName, widthValue, heightValue, format, headerSizeValue); + texture = LoadTextureFromImage(image); + UnloadImage(image); + + importWindowActive = false; + btnLoadPressed = false; + + if (texture.id > 0) + { + imageLoaded = true; + imageScale = (float)(screenHeight - 100)/texture.height; + } + } + } + + if (imageLoaded) imageScale += (float)GetMouseWheelMove(); // Image scale control + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(GetColor(style[DEFAULT_BACKGROUND_COLOR])); + + // raygui: controls drawing + //---------------------------------------------------------------------------------- + if (importWindowActive) + { + importWindowActive = !GuiWindowBox((Rectangle){ windowOffset.x + 0, windowOffset.y + 0, 200, 465 }, "Image RAW Import Options"); + + GuiLabel((Rectangle){ windowOffset.x + 10, windowOffset.y + 30, 65, 20 }, "Import file:"); + GuiLabel((Rectangle){ windowOffset.x + 85, windowOffset.y + 30, 75, 20 }, "Untitled.raw"); + GuiLabel((Rectangle){ windowOffset.x + 10, windowOffset.y + 50, 65, 20 }, "File size:"); + GuiLabel((Rectangle){ windowOffset.x + 85, windowOffset.y + 50, 75, 20 }, "2132421 bytes"); + GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 85, 180, 80 }, "Resolution"); + GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 100, 33, 25 }, "Width:"); + widthValue = GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 100, 80, 25 }, widthValue, 100); + GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 100, 30, 25 }, "pixels"); + GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 130, 33, 25 }, "Height:"); + heightValue = GuiValueBox((Rectangle){ windowOffset.x + 60, windowOffset.y + 130, 80, 25 }, heightValue, 100); + GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 130, 30, 25 }, "pixels"); + GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 180, 180, 160 }, "Pixel Format"); + pixelFormatActive = GuiComboBox((Rectangle){ windowOffset.x + 20, windowOffset.y + 195, 160, 25 }, pixelFormatTextList, 3, pixelFormatActive); + GuiLine((Rectangle){ windowOffset.x + 20, windowOffset.y + 220, 160, 20 }, 1); + GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 235, 50, 20 }, "Channels:"); + channelsActive = GuiToggleGroup((Rectangle){ windowOffset.x + 20, windowOffset.y + 255, 159, 25 }, channelsTextList, 4, channelsActive); + GuiLabel((Rectangle){ windowOffset.x + 20, windowOffset.y + 285, 50, 20 }, "Bit Depth:"); + bitDepthActive = GuiToggleGroup((Rectangle){ windowOffset.x + 20, windowOffset.y + 305, 159, 25 }, bitDepthTextList, 3, bitDepthActive); + GuiGroupBox((Rectangle){ windowOffset.x + 10, windowOffset.y + 355, 180, 50 }, "Header"); + GuiLabel((Rectangle){ windowOffset.x + 25, windowOffset.y + 370, 27, 25 }, "Size:"); + headerSizeValue = GuiValueBox((Rectangle){ windowOffset.x + 55, windowOffset.y + 370, 85, 25 }, headerSizeValue, 100); + GuiLabel((Rectangle){ windowOffset.x + 145, windowOffset.y + 370, 30, 25 }, "bytes"); + + btnLoadPressed = GuiButton((Rectangle){ windowOffset.x + 10, windowOffset.y + 420, 180, 30 }, "Import RAW"); + } + + //---------------------------------------------------------------------------------- + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + if (texture.id != 0) UnloadTexture(texture); + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/raw_importer/raw_importer.c b/examples/image_raw_importer/image_raw_importer.old.c similarity index 94% rename from examples/raw_importer/raw_importer.c rename to examples/image_raw_importer/image_raw_importer.old.c index 27d4960..55ca268 100644 --- a/examples/raw_importer/raw_importer.c +++ b/examples/image_raw_importer/image_raw_importer.old.c @@ -36,10 +36,10 @@ int main(int argc, char *argv[0]) bool btnLoadPressed = false; - int buttonToggleChannel = 3; + int buttonToggleChannel = 1; int buttonToggleDepth = 0; - char *arrayChannel[4] = { "1", "2", "3", "4" }; - char *arrayDepth[3] = { "8", "16", "32" }; + const char *arrayChannel[4] = { "1", "2", "3", "4" }; + const char *arrayDepth[3] = { "8", "16", "32" }; // Image file info int dataSize = 0; @@ -149,24 +149,24 @@ int main(int argc, char *argv[0]) //---------------------------------------------------------------------------------- BeginDrawing(); - ClearBackground(GuiGetBackgroundColor()); + ClearBackground(RAYWHITE); - DrawRectangleLines(10, 10, SCREEN_WIDTH - 20, SCREEN_HEIGHT - 20, GuiLinesColor()); + DrawRectangleLines(10, 10, SCREEN_WIDTH - 20, SCREEN_HEIGHT - 20, BLUE); if (texture.id != 0) { DrawTextureEx(texture, (Vector2){ SCREEN_WIDTH/2 - texture.width*imageScale/2, SCREEN_HEIGHT/2 - texture.height*imageScale/2 }, 0, imageScale, WHITE); - DrawText(FormatText("SCALE x%.0f", imageScale), 20, SCREEN_HEIGHT - 40, 20, GuiTextColor()); + DrawText(FormatText("SCALE x%.0f", imageScale), 20, SCREEN_HEIGHT - 40, 20, BLUE); } - else DrawText("drag & drop RAW image file", 320, 180, 10, GuiTextColor()); + else DrawText("drag & drop RAW image file", 320, 180, 10, BLUE); if (showImportPanel) { DrawRectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, Fade(LIGHTGRAY, 0.5f)); - DrawRectangleRec(panel, GuiBackgroundColor()); - DrawRectangleLines(panel.x, panel.y, panel.width, panel.height, GuiLinesColor()); + DrawRectangleRec(panel, RAYWHITE); + DrawRectangleLines(panel.x, panel.y, panel.width, panel.height, BLUE); GuiLabel((Rectangle){ panel.x + 10, panel.y + 10, 0, 0 }, FormatText("Import file: %s", fileName)); GuiLabel((Rectangle){ panel.x + 10, panel.y + 30, 0, 0 }, FormatText("File size: %i bytes", dataSize)); @@ -177,12 +177,12 @@ int main(int argc, char *argv[0]) GuiLabel((Rectangle){ panel.x + 20, panel.y + 80, 0, 0 }, "Width:"); GuiLabel((Rectangle){ panel.x + 150, panel.y + 80, 0, 0 }, "pixels"); - GuiTextBox((Rectangle){ panel.x + 60, panel.y + 75, 80, 20 }, textImageWidth, 4); + GuiTextBox((Rectangle){ panel.x + 60, panel.y + 75, 80, 20 }, textImageWidth, 4, false); GuiLabel((Rectangle){ panel.x + 20, panel.y + 105, 0, 0 }, "Height:"); GuiLabel((Rectangle){ panel.x + 150, panel.y + 105, 0, 0 }, "pixels"); - GuiTextBox((Rectangle){ panel.x + 60, panel.y + 100, 80, 20 }, textImageHeight, 4); + GuiTextBox((Rectangle){ panel.x + 60, panel.y + 100, 80, 20 }, textImageHeight, 4, false); // ----- Pixel data panel ----- GuiGroupBox((Rectangle){ panel.x + 10, panel.y + 155, 180, 110 }, "Pixels Data"); @@ -199,7 +199,7 @@ int main(int argc, char *argv[0]) GuiLabel((Rectangle){ panel.x + 20, panel.y + 305, 0, 0 }, "Size:"); GuiLabel((Rectangle){ panel.x + 150, panel.y + 305, 0, 0 }, "bytes"); - GuiTextBox((Rectangle){ panel.x + 60, panel.y + 300, 80, 20 }, textImageSize, 4); + GuiTextBox((Rectangle){ panel.x + 60, panel.y + 300, 80, 20 }, textImageSize, 4, false); btnLoadPressed = GuiButton((Rectangle){ panel.x + 10, panel.y + 350, 180, 24 }, "Load RAW Image"); } diff --git a/examples/raw_importer/raw_importer_REF.png b/examples/image_raw_importer/raw_importer_REF.png similarity index 100% rename from examples/raw_importer/raw_importer_REF.png rename to examples/image_raw_importer/raw_importer_REF.png diff --git a/examples/raw_importer/raw_importer_REV0.png b/examples/image_raw_importer/raw_importer_REV0.png similarity index 100% rename from examples/raw_importer/raw_importer_REV0.png rename to examples/image_raw_importer/raw_importer_REV0.png diff --git a/examples/raw_importer/raw_importer_REV1.png b/examples/image_raw_importer/raw_importer_REV1.png similarity index 100% rename from examples/raw_importer/raw_importer_REV1.png rename to examples/image_raw_importer/raw_importer_REV1.png diff --git a/examples/raw_importer/raw_importer_REV2.png b/examples/image_raw_importer/raw_importer_REV2.png similarity index 100% rename from examples/raw_importer/raw_importer_REV2.png rename to examples/image_raw_importer/raw_importer_REV2.png diff --git a/examples/raw_importer/raw_importer_REV3.png b/examples/image_raw_importer/raw_importer_REV3.png similarity index 100% rename from examples/raw_importer/raw_importer_REV3.png rename to examples/image_raw_importer/raw_importer_REV3.png diff --git a/examples/raw_importer/raw_importer_REV4.png b/examples/image_raw_importer/raw_importer_REV4.png similarity index 100% rename from examples/raw_importer/raw_importer_REV4.png rename to examples/image_raw_importer/raw_importer_REV4.png diff --git a/examples/image_raw_importer/raw_importer_REV5.png b/examples/image_raw_importer/raw_importer_REV5.png new file mode 100644 index 0000000000000000000000000000000000000000..3f5e01298722cc6a8ca2739733046286a7cf2454 GIT binary patch literal 6581 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 X&#spGm2N&LO0asx8mk-&{?GphHKDUw literal 0 HcmV?d00001