diff --git a/plugins/visualizers/source/content/pl_visualizers.cpp b/plugins/visualizers/source/content/pl_visualizers.cpp index d938979b3..b0d477712 100644 --- a/plugins/visualizers/source/content/pl_visualizers.cpp +++ b/plugins/visualizers/source/content/pl_visualizers.cpp @@ -22,7 +22,7 @@ namespace hex::plugin::visualizers { ContentRegistry::PatternLanguage::addVisualizer("line_plot", drawLinePlotVisualizer, ParamCount::exactly(1)); ContentRegistry::PatternLanguage::addVisualizer("scatter_plot", drawScatterPlotVisualizer, ParamCount::exactly(2)); ContentRegistry::PatternLanguage::addVisualizer("image", drawImageVisualizer, ParamCount::exactly(1)); - ContentRegistry::PatternLanguage::addVisualizer("bitmap", drawBitmapVisualizer, ParamCount::exactly(3)); + ContentRegistry::PatternLanguage::addVisualizer("bitmap", drawBitmapVisualizer, ParamCount::between(3, 4)); ContentRegistry::PatternLanguage::addVisualizer("3d", draw3DVisualizer, ParamCount::between(2, 6)); ContentRegistry::PatternLanguage::addVisualizer("sound", drawSoundVisualizer, ParamCount::exactly(3)); ContentRegistry::PatternLanguage::addVisualizer("coordinates", drawCoordinateVisualizer, ParamCount::exactly(2)); diff --git a/plugins/visualizers/source/content/pl_visualizers/image.cpp b/plugins/visualizers/source/content/pl_visualizers/image.cpp index 0784ac67e..e6d888ecf 100644 --- a/plugins/visualizers/source/content/pl_visualizers/image.cpp +++ b/plugins/visualizers/source/content/pl_visualizers/image.cpp @@ -7,6 +7,9 @@ #include namespace hex::plugin::visualizers { + std::vector getIndices(pl::ptrn::Pattern *colorTablePattern, u128 width, u128 height); + ImGuiExt::Texture getTexture(pl::ptrn::Pattern *colorTablePattern, std::vector& indices, u128 width, u128 height); + void drawImageVisualizer(pl::ptrn::Pattern &, bool shouldReset, std::span arguments) { static ImGuiExt::Texture texture; @@ -40,9 +43,22 @@ namespace hex::plugin::visualizers { auto pattern = arguments[0].toPattern(); auto width = arguments[1].toUnsigned(); auto height = arguments[2].toUnsigned(); + bool hasColorTable = false; - auto data = pattern->getBytes(); - texture = ImGuiExt::Texture::fromBitmap(data.data(), data.size(), width, height, ImGuiExt::Texture::Filter::Nearest); + if (arguments.size() == 4) { + auto colorTablePattern = arguments[3].toPattern(); + + if (colorTablePattern->getSize() > 0) { + auto indices = getIndices(pattern.get(), width, height); + texture = getTexture(colorTablePattern.get(), indices, width, height); + hasColorTable = true; + } + } + + if (!hasColorTable) { + auto data = pattern->getBytes(); + texture = ImGuiExt::Texture::fromBitmap(data.data(), data.size(), width, height,ImGuiExt::Texture::Filter::Nearest); + } } if (texture.isValid()) @@ -50,6 +66,7 @@ namespace hex::plugin::visualizers { if (ImGui::IsWindowHovered()) { auto scrollDelta = ImGui::GetIO().MouseWheel; + if (scrollDelta != 0.0F) { scale += scrollDelta * 0.1F; scale = std::clamp(scale, 0.1F, 10.0F); @@ -57,4 +74,85 @@ namespace hex::plugin::visualizers { } } -} \ No newline at end of file + template ImGuiExt::Texture unmapColors(pl::ptrn::Pattern *colorTablePattern, std::vector& indices, u128 width, u128 height) { + std::vector colorTable = patternToArray(colorTablePattern); + auto colorCount = colorTable.size(); + auto indexCount = indices.size(); + std::vector image(indexCount); + + for (u32 i = 0; i < indexCount; i++) { + auto index = indices[i]; + + if (index >= colorCount) + index = 0; + image[i] = colorTable[index]; + } + void *tmp = image.data(); + ImU8 *data = static_cast(tmp); + ImGuiExt::Texture texture = ImGuiExt::Texture::fromBitmap(data, indexCount*sizeof(T), width, height, ImGuiExt::Texture::Filter::Nearest); + return texture; + } + + std::vector getIndices(pl::ptrn::Pattern *pattern, u128 width, u128 height) { + auto indexCount = 2 * width * height / pattern->getSize(); + std::vector indices; + auto *iterable = dynamic_cast(pattern); + + if (iterable == nullptr || iterable->getEntryCount() <= 0) + return indices; + auto content = iterable->getEntry(0); + auto byteCount = content->getSize(); + + if (byteCount >= indexCount && indexCount != 0) { + auto bytePerIndex = byteCount / indexCount; + + if (bytePerIndex == 1) { + auto temp = patternToArray(pattern); + indices = std::vector(temp.begin(), temp.end()); + } else if (bytePerIndex == 2) { + auto temp = patternToArray(pattern); + indices = std::vector(temp.begin(), temp.end()); + } else if (bytePerIndex == 4) { + auto temp = patternToArray(pattern); + indices = std::vector(temp.begin(), temp.end()); + } + } else if (indexCount != 0) { + auto indicesPerByte = indexCount / byteCount; + auto temp = patternToArray(pattern); + + if (indicesPerByte == 2) { + for (u32 i = 0; i < temp.size(); i++) { + indices.push_back(temp[i] & 0xF); + indices.push_back((temp[i] >> 4) & 0xF); + } + } else if (indicesPerByte == 4) { + for (u32 i = 0; i < temp.size(); i++) { + indices.push_back(temp[i] & 0x3); + indices.push_back((temp[i] >> 2) & 0x3); + indices.push_back((temp[i] >> 4) & 0x3); + indices.push_back((temp[i] >> 6) & 0x3); + } + } + } + return indices; + } + + ImGuiExt::Texture getTexture(pl::ptrn::Pattern *colorTablePattern, std::vector& indices, u128 width, u128 height) { + ImGuiExt::Texture texture; + auto iterable = dynamic_cast(colorTablePattern); + + if (iterable == nullptr || iterable->getEntryCount() <= 0) + return texture; + auto content = iterable->getEntry(0); + auto colorTypeSize = content->getSize()*2; + + if (colorTypeSize == 1) { + texture = unmapColors(colorTablePattern, indices, width, height); + } else if (colorTypeSize == 2) { + texture = unmapColors(colorTablePattern, indices, width, height); + } else if (colorTypeSize == 4) { + texture = unmapColors(colorTablePattern, indices, width, height); + } + return texture; + } +}