From 176e7073eb6cb0487fe63a4b77b55988f7fbe063 Mon Sep 17 00:00:00 2001 From: Yggdrasil75 Date: Wed, 19 Nov 2025 13:43:29 -0500 Subject: [PATCH 1/3] broken version for occam to look at --- tests/g2chromatic2.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tests/g2chromatic2.cpp b/tests/g2chromatic2.cpp index 1485cdf..0d94935 100644 --- a/tests/g2chromatic2.cpp +++ b/tests/g2chromatic2.cpp @@ -13,6 +13,7 @@ #include "../imgui/imgui.h" #include "../imgui/backends/imgui_impl_glfw.h" #include "../imgui/backends/imgui_impl_opengl3.h" +//#include "../imgui/" #include #include "../stb/stb_image.h" @@ -70,11 +71,25 @@ void Preview(Grid2& grid) { } void livePreview(GLFWwindow* window, Grid2& grid) { - // frame Frame = grid.getGridAsFrame(frame::colormap::RGB); - // int image_width = Frame.getWidth(); - // int image_height = Frame.getHeight(); - // auto data = reinterpret_cast(Frame.getData()); - // uint8_t* image_data = stbi_load_from_memory((const unsigned char*)data, (int)data.size(), &image_width, &image_height, 3, 4); + frame Frame = grid.getGridAsFrame(frame::colormap::RGB); + int image_width = Frame.getWidth(); + int image_height = Frame.getHeight(); + std::vector framedata = Frame.getData(); + + GLuint textu; + glGenTextures(1, &textu); + glBindTexture(GL_TEXTURE_2D, textu); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image_width, image_height, 0, GL_RGB, GL_UNSIGNED_BYTE, framedata.data()); + + ImGui::Begin(""); + //ImGui::Image((ImTextureRef)(intptr_t)textu, ImVec2(image_width, image_height)); + ImGui::Image(ImTextureRef((uint64_t)textu), ImVec2((float)image_width, (float)image_height)); + ImGui::End(); + + glDeleteTextures(1,&textu); } std::vector> pickSeeds(Grid2 grid, AnimationConfig config) { From 75daa0f50143b14bcc47a89e319ec93df9024e52 Mon Sep 17 00:00:00 2001 From: Yggdrasil75 Date: Thu, 20 Nov 2025 10:55:21 -0500 Subject: [PATCH 2/3] stupid makefile stuff. well, it kinda works now. still no live preview but checkpointing it here. --- makefile | 63 ++++++++++++++++++++------------ tests/g2chromatic2.cpp | 82 +++++++++++++++--------------------------- tests/stb_image.cpp | 2 ++ 3 files changed, 71 insertions(+), 76 deletions(-) create mode 100644 tests/stb_image.cpp diff --git a/makefile b/makefile index 2d92935..b396943 100644 --- a/makefile +++ b/makefile @@ -1,35 +1,52 @@ -# Compiler and flags -CXX := g++ -CXXFLAGS := -std=c++23 -O3 -march=native -I./imgui -LDFLAGS := -L./imgui -limgui -lstb -lGL -PKG_FLAGS := $(shell pkg-config --cflags --libs glfw3) - # Directories BIN_DIR := ./bin SRC_DIR := ./tests +IMGUI_DIR = ./imgui +OBJ_DIR := $(BIN_DIR)/obj +STB_DIR := ./stb + +# Compiler and flags +CXX := g++ +CXXFLAGS = -std=c++23 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I$(STB_DIR) +#CXXFLAGS += -g -Wall -Wformat +CXXFLAGS += `pkg-config --cflags glfw3` +CFLAGS = $(CXXFLAGS) +LDFLAGS := -L./imgui -limgui -lGL +LINUX_GL_LIBS = -lGL +PKG_FLAGS := $(LINUX_GL_LIBS) `pkg-config --static --cflags --libs glfw3` +CXXFLAGS += $(PKG_FLAGS) # Source files SRC := $(SRC_DIR)/g2chromatic2.cpp -TARGET := $(BIN_DIR)/g2gradc +SRC += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp +SRC += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp +SRC += $(SRC_DIR)/stb_image.cpp +OBJS = $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(basename $(notdir $(SRC))))) +UNAME_S := $(shell uname -s) +EXE := $(BIN_DIR)/g2gradc -# Default target -all: $(TARGET) +$(shell mkdir -p $(OBJ_DIR)) -# Create binary directory if it doesn't exist -$(BIN_DIR): - @mkdir -p $(BIN_DIR) +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< -# Build target -$(TARGET): $(SRC) | $(BIN_DIR) - $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(PKG_FLAGS) +$(OBJ_DIR)/%.o: %.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< -# Run the program -run: $(TARGET) - ./$(TARGET) +$(OBJ_DIR)/%.o: $(IMGUI_DIR)/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(IMGUI_DIR)/backends/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +$(OBJ_DIR)/%.o: $(STB_DIR)/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +all: $(EXE) + @echo Build complete for $(ECHO_MESSAGE) + +$(EXE): $(OBJS) + $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) -# Clean build artifacts clean: - rm -rf $(BIN_DIR) - -# Phony targets -.PHONY: all run clean \ No newline at end of file + rm -f $(EXE) $(OBJS) \ No newline at end of file diff --git a/tests/g2chromatic2.cpp b/tests/g2chromatic2.cpp index 0d94935..5cfa16c 100644 --- a/tests/g2chromatic2.cpp +++ b/tests/g2chromatic2.cpp @@ -13,7 +13,6 @@ #include "../imgui/imgui.h" #include "../imgui/backends/imgui_impl_glfw.h" #include "../imgui/backends/imgui_impl_opengl3.h" -//#include "../imgui/" #include #include "../stb/stb_image.h" @@ -70,11 +69,11 @@ void Preview(Grid2& grid) { } } -void livePreview(GLFWwindow* window, Grid2& grid) { - frame Frame = grid.getGridAsFrame(frame::colormap::RGB); - int image_width = Frame.getWidth(); - int image_height = Frame.getHeight(); - std::vector framedata = Frame.getData(); +void livePreview(Grid2& grid) { + currentPreviewFrame = grid.getGridAsFrame(frame::colormap::RGB); + int image_width = currentPreviewFrame.getWidth(); + int image_height = currentPreviewFrame.getHeight(); + std::vector framedata = currentPreviewFrame.getData(); GLuint textu; glGenTextures(1, &textu); @@ -84,12 +83,7 @@ void livePreview(GLFWwindow* window, Grid2& grid) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image_width, image_height, 0, GL_RGB, GL_UNSIGNED_BYTE, framedata.data()); - ImGui::Begin(""); - //ImGui::Image((ImTextureRef)(intptr_t)textu, ImVec2(image_width, image_height)); - ImGui::Image(ImTextureRef((uint64_t)textu), ImVec2((float)image_width, (float)image_height)); - ImGui::End(); - - glDeleteTextures(1,&textu); + previewTexture = textu; } std::vector> pickSeeds(Grid2 grid, AnimationConfig config) { @@ -352,6 +346,7 @@ int main() { std::future mainlogicthread; Grid2 grid; + AnimationConfig config; while (!glfwWindowShouldClose(window)) { glfwPollEvents(); @@ -369,69 +364,50 @@ int main() { ImGui::SliderInt("framecount", &i3, 10, 5000); ImGui::SliderInt("numSeeds", &i4, 0, 10); - // Disable button while generating if (isGenerating) { ImGui::BeginDisabled(); } if (ImGui::Button("Generate Animation")) { - AnimationConfig config = AnimationConfig(i1, i2, i3, f, i4); + config = AnimationConfig(i1, i2, i3, f, i4); mainlogicthread = std::async(std::launch::async, mainLogic, config, std::ref(grid)); } if (isGenerating) { ImGui::EndDisabled(); - // Show cancel button and progress indicator ImGui::SameLine(); if (ImGui::Button("Cancel")) { cancelGeneration(); } - // Optional: Show a progress indicator ImGui::Text("Generating..."); } //ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); // is this broken or is it just cause I have no refresh buffer in this loop? + + ImGui::Text("livepreview"); + if (isGenerating) { + livePreview(grid); + ImVec2 availableSize = ImGui::GetContentRegionAvail(); + + float aspectRatio = static_cast(currentPreviewFrame.getWidth()) / + static_cast(currentPreviewFrame.getHeight()); + + ImVec2 imageSize = ImVec2(config.height,config.width); + ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left + ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right + auto ptex = const_cast(static_cast(currentPreviewFrame.getData().data())); + ImGui::ImageWithBg((ImTextureRef)ptex, imageSize, uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + + + } else { + ImGui::Text("No preview available"); + ImGui::Text("Start generation to see live preview"); + } + ImGui::End(); } - // ImGui::NewFrame(); - // { - // ImGui::Begin("Live Preview"); - - // if (previewTexture != 0) { - // // Get available space - // ImVec2 availableSize = ImGui::GetContentRegionAvail(); - - // // Maintain aspect ratio (assuming square or config width/height) - // float aspectRatio = static_cast(currentPreviewFrame.getWidth()) / - // static_cast(currentPreviewFrame.getHeight()); - - // ImVec2 imageSize; - // if (availableSize.x / aspectRatio <= availableSize.y) { - // imageSize.x = availableSize.x; - // imageSize.y = availableSize.x / aspectRatio; - // } else { - // imageSize.y = availableSize.y; - // imageSize.x = availableSize.y * aspectRatio; - // } - - // ImGui::Image((ImTextureID)(intptr_t)previewTexture, imageSize); - - // ImGui::Text("Frame: %dx%d", currentPreviewFrame.getWidth(), currentPreviewFrame.getHeight()); - // if (isGenerating) { - // ImGui::TextColored(ImVec4(0, 1, 0, 1), "Generating..."); - // } else { - // ImGui::Text("Ready"); - // } - // } else { - // ImGui::Text("No preview available"); - // ImGui::Text("Start generation to see live preview"); - // } - - // ImGui::End(); - // } - ImGui::Render(); int display_w, display_h; diff --git a/tests/stb_image.cpp b/tests/stb_image.cpp new file mode 100644 index 0000000..badb3ef --- /dev/null +++ b/tests/stb_image.cpp @@ -0,0 +1,2 @@ +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" \ No newline at end of file From 7f0a8278d756333ff05c32dd73a5238fd0daca4e Mon Sep 17 00:00:00 2001 From: Yggdrasil75 Date: Thu, 20 Nov 2025 14:45:30 -0500 Subject: [PATCH 3/3] better, still not great. will fix later. --- tests/g2chromatic2.cpp | 112 +++++++++++++++++++++++++++-------------- util/grid/grid2.hpp | 95 ++++++++++++++++++++++++++++++++-- 2 files changed, 167 insertions(+), 40 deletions(-) diff --git a/tests/g2chromatic2.cpp b/tests/g2chromatic2.cpp index 5cfa16c..4f5564f 100644 --- a/tests/g2chromatic2.cpp +++ b/tests/g2chromatic2.cpp @@ -20,6 +20,7 @@ #include #include #include +#include std::mutex m; std::atomic isGenerating{false}; @@ -28,7 +29,15 @@ std::future generationFuture; std::mutex previewMutex; std::atomic updatePreview{false}; frame currentPreviewFrame; -GLuint previewTexture = 0; +GLuint textu = 0; +std::string previewText; + +struct Shared { + std::mutex mutex; + Grid2 grid; + bool hasNewFrame = false; + int currentFrame = 0; +}; struct AnimationConfig { int width = 1024; @@ -69,21 +78,22 @@ void Preview(Grid2& grid) { } } -void livePreview(Grid2& grid) { - currentPreviewFrame = grid.getGridAsFrame(frame::colormap::RGB); - int image_width = currentPreviewFrame.getWidth(); - int image_height = currentPreviewFrame.getHeight(); - std::vector framedata = currentPreviewFrame.getData(); +void livePreview(const Grid2& grid) { + std::lock_guard lock(previewMutex); + + currentPreviewFrame = grid.getGridAsFrame(frame::colormap::RGBA); - GLuint textu; glGenTextures(1, &textu); glBindTexture(GL_TEXTURE_2D, textu); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image_width, image_height, 0, GL_RGB, GL_UNSIGNED_BYTE, framedata.data()); - previewTexture = textu; + glBindTexture(GL_TEXTURE_2D, textu); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, currentPreviewFrame.getWidth(), currentPreviewFrame.getHeight(), + 0, GL_RGBA, GL_UNSIGNED_BYTE, currentPreviewFrame.getData().data()); + + updatePreview = true; } std::vector> pickSeeds(Grid2 grid, AnimationConfig config) { @@ -210,10 +220,16 @@ bool exportavi(std::vector frames, AnimationConfig config) { return success; } -void mainLogic(const AnimationConfig& config, Grid2& grid) { +void mainLogic(const AnimationConfig& config, Shared& state) { isGenerating = true; try { - grid = setup(config); + Grid2 grid = setup(config); + { + std:: lock_guard lock(state.mutex); + state.grid = grid; + state.hasNewFrame = true; + state.currentFrame = 0; + } Preview(grid); std::vector> seeds = pickSeeds(grid, config); std::vector frames; @@ -227,16 +243,21 @@ void mainLogic(const AnimationConfig& config, Grid2& grid) { expandPixel(grid,config,seeds); + std::lock_guard lock(state.mutex); + state.grid = grid; + state.hasNewFrame = true; + state.currentFrame = i; + // Print compression info for this frame if (i % 10 == 0 ) { frame bgrframe; std::cout << "Processing frame " << i + 1 << "/" << config.totalFrames << std::endl; bgrframe = grid.getGridAsFrame(frame::colormap::BGR); - bgrframe.printCompressionStats(); frames.push_back(bgrframe); //bgrframe.decompress(); //BMPWriter::saveBMP(std::format("output/grayscalesource.{}.bmp", i), bgrframe); bgrframe.compressFrameLZ78(); + bgrframe.printCompressionStats(); } } exportavi(frames,config); @@ -305,7 +326,7 @@ int main() { //ImGui::SetNextWindowSize(ImVec2(1110,667)); //auto beg = ImGui::Begin("Gradient thing", &window); //if (beg) { - std::cout << "stuff breaks at 223" << std::endl; + // std::cout << "stuff breaks at 223" << std::endl; bool application_not_closed = true; //float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); GLFWwindow* window = glfwCreateWindow((int)(1280), (int)(800), "Chromatic gradient generator thing", nullptr, nullptr); @@ -315,7 +336,7 @@ int main() { glfwSwapInterval(1); //IMGUI_CHECKVERSION(); //this might be more important than I realize. but cant run with it so currently ignoring. ImGui::CreateContext(); - std::cout << "context created" << std::endl; + // std::cout << "context created" << std::endl; ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui::StyleColorsDark(); @@ -331,7 +352,7 @@ int main() { ImGui_ImplOpenGL3_Init(glsl_version); - std::cout << "created glfw window" << std::endl; + // std::cout << "created glfw window" << std::endl; // Our state @@ -345,8 +366,10 @@ int main() { static int i4 = 8; std::future mainlogicthread; + Shared state; Grid2 grid; AnimationConfig config; + previewText = "Please generate"; while (!glfwWindowShouldClose(window)) { glfwPollEvents(); @@ -370,7 +393,7 @@ int main() { if (ImGui::Button("Generate Animation")) { config = AnimationConfig(i1, i2, i3, f, i4); - mainlogicthread = std::async(std::launch::async, mainLogic, config, std::ref(grid)); + mainlogicthread = std::async(std::launch::async, mainLogic, config, std::ref(state)); } if (isGenerating) { @@ -381,58 +404,73 @@ int main() { cancelGeneration(); } - ImGui::Text("Generating..."); - } - //ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); // is this broken or is it just cause I have no refresh buffer in this loop? - - ImGui::Text("livepreview"); - if (isGenerating) { - livePreview(grid); - ImVec2 availableSize = ImGui::GetContentRegionAvail(); + // Check for new frames from the generation thread + bool hasNewFrame = false; + { + std::lock_guard lock(state.mutex); + if (state.hasNewFrame) { + livePreview(state.grid); + state.hasNewFrame = false; + previewText = "Generating... Frame: " + std::to_string(state.currentFrame); + } + } - float aspectRatio = static_cast(currentPreviewFrame.getWidth()) / - static_cast(currentPreviewFrame.getHeight()); - - ImVec2 imageSize = ImVec2(config.height,config.width); - ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left - ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right - auto ptex = const_cast(static_cast(currentPreviewFrame.getData().data())); - ImGui::ImageWithBg((ImTextureRef)ptex, imageSize, uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + ImGui::Text(previewText.c_str()); + if (textu != 0) { + ImVec2 imageSize = ImVec2(config.width * 0.3f, config.height * 0.3f); // Scale down for preview + ImVec2 uv_min = ImVec2(0.0f, 0.0f); + ImVec2 uv_max = ImVec2(1.0f, 1.0f); + ImGui::Image((void*)(intptr_t)textu, imageSize, uv_min, uv_max); + } else { + ImGui::Text("Generating preview..."); + } } else { ImGui::Text("No preview available"); ImGui::Text("Start generation to see live preview"); } - + //std::cout << "sleeping" << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + //std::cout << "ending" << std::endl; ImGui::End(); } - + + // std::cout << "ending frame" << std::endl; ImGui::Render(); int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); + + // std::cout << "rendering" << std::endl; ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); //mainlogicthread.join(); + + // std::cout << "swapping buffers" << std::endl; } cancelGeneration(); + + // std::cout << "shutting down" << std::endl; ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); + // std::cout << "destroying" << std::endl; glfwDestroyWindow(window); - if (previewTexture != 0) { - glDeleteTextures(1, &previewTexture); - previewTexture = 0; + if (textu != 0) { + glDeleteTextures(1, &textu); + textu = 0; } glfwTerminate(); FunctionTimer::printStats(FunctionTimer::Mode::ENHANCED); + + // std::cout << "printing" << std::endl; return 0; } //I need this: https://raais.github.io/ImStudio/ diff --git a/util/grid/grid2.hpp b/util/grid/grid2.hpp index 6d49a83..de8750b 100644 --- a/util/grid/grid2.hpp +++ b/util/grid/grid2.hpp @@ -67,7 +67,7 @@ public: return Positions.bucket_count(); } - bool empty() { + bool empty() const { return Positions.empty(); } @@ -194,7 +194,9 @@ protected: //TODO: spatial map SpatialGrid spatialGrid; float spatialCellSize = 2.0f; + public: + bool usable = false; //get position from id Vec2 getPositionID(size_t id) const { Vec2 it = Positions.at(id); @@ -459,6 +461,7 @@ public: shrinkIfNeeded(); updateNeighborMap(); + usable = true; return getAllIDs(); } @@ -620,6 +623,78 @@ public: } } + + + void getGridRegionAsRGBA(const Vec2& minCorner, const Vec2& maxCorner, + int& width, int& height, std::vector& rgbData) const { + TIME_FUNCTION; + // std::cout << "excessdebug g2.483" << std::endl; + // Calculate dimensions + width = static_cast(maxCorner.x - minCorner.x); + height = static_cast(maxCorner.y - minCorner.y); + + if (width <= 0 || height <= 0) { + width = height = 0; + rgbData.clear(); + rgbData.shrink_to_fit(); + return; + } + // std::cout << "excessdebug g2.494" << std::endl; + + // Initialize RGB data (3 bytes per pixel: R, G, B) + std::vector rgbaBuffer(width * height, Vec4(0.0f, 0.0f, 0.0f, 0.0f)); + + // For each position in the grid, find the corresponding pixel + for (const auto& [id, pos] : Positions) { + // std::cout << "excessdebug g2.501." << id << std::endl; + size_t size = Sizes.at(id); + + // Calculate pixel coordinates + int pixelXm = static_cast(pos.x - size/2 - minCorner.x); + int pixelXM = static_cast(pos.x + size/2 - minCorner.x); + int pixelYm = static_cast(pos.y - size/2 - minCorner.y); + int pixelYM = static_cast(pos.y + size/2 - minCorner.y); + + pixelXm = std::max(0, pixelXm); + pixelXM = std::min(width - 1, pixelXM); + pixelYm = std::max(0, pixelYm); + pixelYM = std::min(height - 1, pixelYM); + // std::cout << "excessdebug g2.514." << id << std::endl; + + // Ensure within bounds + if (pixelXM >= minCorner.x && pixelXm < width && pixelYM >= minCorner.y && pixelYm < height) { + // std::cout << "excessdebug g2.518." << id << " - (" << pixelXm << "," << pixelYM << ")" << std::endl; + const Vec4& color = Colors.at(id); + float srcAlpha = color.a; + float invSrcAlpha = 1.0f - srcAlpha; + for (int py = pixelYm; py <= pixelYM; ++py){ + for (int px = pixelXm; px <= pixelXM; ++px){ + // std::cout << "excessdebug g2.524." << id << " - (" << py << "," << px << ")" << std::endl; + int index = (py * width + px); + Vec4 dest = rgbaBuffer[index]; + + dest.r = color.r * srcAlpha + dest.r; // * invSrcAlpha; + dest.g = color.g * srcAlpha + dest.g; // * invSrcAlpha; + dest.b = color.b * srcAlpha + dest.b; // * invSrcAlpha; + dest.a = srcAlpha + dest.a; // * invSrcAlpha; + rgbaBuffer[index] = dest; + } + } + } + } + rgbData.resize(rgbaBuffer.size() * 4); + for (int i = 0; i < rgbaBuffer.size(); ++i) { + const Vec4& color = rgbaBuffer[i]; + int bgrIndex = i * 4; + + // Convert from [0,1] to [0,255] and store as RGB + rgbData[bgrIndex + 0] = static_cast(color.r * 255); + rgbData[bgrIndex + 1] = static_cast(color.g * 255); + rgbData[bgrIndex + 2] = static_cast(color.b * 255); + rgbData[bgrIndex + 2] = static_cast(color.a * 255); + + } + } //get full as rgb/bgr void getGridAsRGB(int& width, int& height, std::vector& rgbData) { @@ -645,6 +720,17 @@ public: resultFrame.setData(rgbData); return resultFrame; } + + frame getGridRegionAsFrameRGBA(const Vec2& minCorner, const Vec2& maxCorner) const { + TIME_FUNCTION; + int width, height; + std::vector rgbData; + getGridRegionAsRGBA(minCorner, maxCorner, width, height, rgbData); + + frame resultFrame(width, height, frame::colormap::RGB); + resultFrame.setData(rgbData); + return resultFrame; + } // Get region as frame (BGR format) frame getGridRegionAsFrameBGR(const Vec2& minCorner, const Vec2& maxCorner) const { @@ -659,7 +745,7 @@ public: } // Get entire grid as frame with specified format - frame getGridAsFrame(frame::colormap format = frame::colormap::RGB) { + frame getGridAsFrame(frame::colormap format = frame::colormap::RGB) const { TIME_FUNCTION; Vec2 minCorner, maxCorner; getBoundingBox(minCorner, maxCorner); @@ -669,6 +755,9 @@ public: case frame::colormap::RGB: Frame = std::move(getGridRegionAsFrameRGB(minCorner, maxCorner)); break; + case frame::colormap::RGBA: + Frame = std::move(getGridRegionAsFrameRGBA(minCorner, maxCorner)); + break; case frame::colormap::BGR: Frame = std::move(getGridRegionAsFrameBGR(minCorner, maxCorner)); break; @@ -708,7 +797,7 @@ public: } //get bounding box - void getBoundingBox(Vec2& minCorner, Vec2& maxCorner) { + void getBoundingBox(Vec2& minCorner, Vec2& maxCorner) const { TIME_FUNCTION; if (Positions.empty()) { minCorner = Vec2(0, 0);