feat: Added type distribution graph to information view
This commit is contained in:
parent
d463491026
commit
4b6a75fb60
@ -24,6 +24,7 @@ namespace hex::plugin::builtin {
|
|||||||
float m_averageEntropy = 0;
|
float m_averageEntropy = 0;
|
||||||
float m_highestBlockEntropy = 0;
|
float m_highestBlockEntropy = 0;
|
||||||
std::vector<float> m_blockEntropy;
|
std::vector<float> m_blockEntropy;
|
||||||
|
std::array<std::vector<float>, 12> m_blockTypeDistributions;
|
||||||
u64 m_blockEntropyProcessedCount = 0;
|
u64 m_blockEntropyProcessedCount = 0;
|
||||||
|
|
||||||
double m_entropyHandlePosition;
|
double m_entropyHandlePosition;
|
||||||
|
@ -681,6 +681,7 @@
|
|||||||
"hex.builtin.view.information.analyzing": "Analyzing...",
|
"hex.builtin.view.information.analyzing": "Analyzing...",
|
||||||
"hex.builtin.view.information.block_size": "Block size",
|
"hex.builtin.view.information.block_size": "Block size",
|
||||||
"hex.builtin.view.information.block_size.desc": "{0} blocks of {1} bytes",
|
"hex.builtin.view.information.block_size.desc": "{0} blocks of {1} bytes",
|
||||||
|
"hex.builtin.view.information.byte_types": "Byte types",
|
||||||
"hex.builtin.view.information.control": "Control",
|
"hex.builtin.view.information.control": "Control",
|
||||||
"hex.builtin.view.information.description": "Description:",
|
"hex.builtin.view.information.description": "Description:",
|
||||||
"hex.builtin.view.information.distribution": "Byte distribution",
|
"hex.builtin.view.information.distribution": "Byte distribution",
|
||||||
|
@ -75,6 +75,48 @@ namespace hex::plugin::builtin {
|
|||||||
return (-entropy) / 8; // log2(256) = 8
|
return (-entropy) / 8; // log2(256) = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::array<float, 12> calculateTypeDistribution(std::array<ImU64, 256> &valueCounts, size_t blockSize) {
|
||||||
|
std::array<ImU64, 12> counts = {};
|
||||||
|
|
||||||
|
for (u16 value = 0x00; value < u16(valueCounts.size()); value++) {
|
||||||
|
const auto &count = valueCounts[value];
|
||||||
|
|
||||||
|
if (count == 0) [[unlikely]]
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (std::iscntrl(value))
|
||||||
|
counts[0] += count;
|
||||||
|
if (std::isprint(value))
|
||||||
|
counts[1] += count;
|
||||||
|
if (std::isspace(value))
|
||||||
|
counts[2] += count;
|
||||||
|
if (std::isblank(value))
|
||||||
|
counts[3] += count;
|
||||||
|
if (std::isgraph(value))
|
||||||
|
counts[4] += count;
|
||||||
|
if (std::ispunct(value))
|
||||||
|
counts[5] += count;
|
||||||
|
if (std::isalnum(value))
|
||||||
|
counts[6] += count;
|
||||||
|
if (std::isalpha(value))
|
||||||
|
counts[7] += count;
|
||||||
|
if (std::isupper(value))
|
||||||
|
counts[8] += count;
|
||||||
|
if (std::islower(value))
|
||||||
|
counts[9] += count;
|
||||||
|
if (std::isdigit(value))
|
||||||
|
counts[10] += count;
|
||||||
|
if (std::isxdigit(value))
|
||||||
|
counts[11] += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<float, 12> distribution = {};
|
||||||
|
for (u32 i = 0; i < distribution.size(); i++)
|
||||||
|
distribution[i] = static_cast<float>(counts[i]) / blockSize;
|
||||||
|
|
||||||
|
return distribution;
|
||||||
|
}
|
||||||
|
|
||||||
void ViewInformation::analyze() {
|
void ViewInformation::analyze() {
|
||||||
this->m_analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this](auto &task) {
|
this->m_analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this](auto &task) {
|
||||||
auto provider = ImHexApi::Provider::get();
|
auto provider = ImHexApi::Provider::get();
|
||||||
@ -97,6 +139,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
std::array<ImU64, 256> blockValueCounts = { 0 };
|
std::array<ImU64, 256> blockValueCounts = { 0 };
|
||||||
|
|
||||||
|
this->m_blockTypeDistributions.fill({});
|
||||||
this->m_blockEntropy.clear();
|
this->m_blockEntropy.clear();
|
||||||
this->m_blockEntropy.resize(provider->getSize() / this->m_blockSize);
|
this->m_blockEntropy.resize(provider->getSize() / this->m_blockSize);
|
||||||
this->m_valueCounts.fill(0);
|
this->m_valueCounts.fill(0);
|
||||||
@ -113,6 +156,13 @@ namespace hex::plugin::builtin {
|
|||||||
count++;
|
count++;
|
||||||
if ((count % this->m_blockSize) == 0) [[unlikely]] {
|
if ((count % this->m_blockSize) == 0) [[unlikely]] {
|
||||||
this->m_blockEntropy[this->m_blockEntropyProcessedCount] = calculateEntropy(blockValueCounts, this->m_blockSize);
|
this->m_blockEntropy[this->m_blockEntropyProcessedCount] = calculateEntropy(blockValueCounts, this->m_blockSize);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto typeDist = calculateTypeDistribution(blockValueCounts, this->m_blockSize);
|
||||||
|
for (u8 i = 0; i < typeDist.size(); i++)
|
||||||
|
this->m_blockTypeDistributions[i].push_back(typeDist[i]);
|
||||||
|
}
|
||||||
|
|
||||||
this->m_blockEntropyProcessedCount += 1;
|
this->m_blockEntropyProcessedCount += 1;
|
||||||
blockValueCounts = { 0 };
|
blockValueCounts = { 0 };
|
||||||
task.update(count);
|
task.update(count);
|
||||||
@ -152,7 +202,7 @@ namespace hex::plugin::builtin {
|
|||||||
// Analyzed region
|
// Analyzed region
|
||||||
ImGui::Header("hex.builtin.view.information.region"_lang, true);
|
ImGui::Header("hex.builtin.view.information.region"_lang, true);
|
||||||
|
|
||||||
if (ImGui::BeginTable("information", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
|
if (ImGui::BeginTable("information", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoKeepColumnsVisible)) {
|
||||||
ImGui::TableSetupColumn("type");
|
ImGui::TableSetupColumn("type");
|
||||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
|
||||||
@ -227,11 +277,32 @@ namespace hex::plugin::builtin {
|
|||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::TextUnformatted("hex.builtin.view.information.byte_types"_lang);
|
||||||
|
if (ImPlot::BeginPlot("##byte_types", ImVec2(-1, 0), ImPlotFlags_NoChild | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_AntiAliased)) {
|
||||||
|
ImPlot::SetupAxes("hex.builtin.common.type"_lang, "hex.builtin.common.count"_lang, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock);
|
||||||
|
ImPlot::SetupAxesLimits(0, this->m_blockTypeDistributions[0].size(), -0.1F, 1.1F, ImGuiCond_Always);
|
||||||
|
ImPlot::SetupLegend(ImPlotLocation_South, ImPlotLegendFlags_Horizontal | ImPlotLegendFlags_Outside);
|
||||||
|
|
||||||
|
constexpr static std::array Names = { "iscntrl", "isprint", "isspace", "isblank", "isgraph", "ispunct", "isalnum", "isalpha", "isupper", "islower", "isdigit", "isxdigit" };
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 12; i++) {
|
||||||
|
ImPlot::PlotLine(Names[i], this->m_blockTypeDistributions[i].data(), this->m_blockTypeDistributions[i].size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImPlot::DragLineX(1, &this->m_entropyHandlePosition, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||||
|
u64 address = u64(std::max<double>(this->m_entropyHandlePosition, 0) * this->m_blockSize) + provider->getBaseAddress();
|
||||||
|
address = std::min(address, provider->getBaseAddress() + provider->getSize() - 1);
|
||||||
|
ImHexApi::HexEditor::setSelection(address, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImPlot::EndPlot();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
|
|
||||||
ImGui::TextUnformatted("hex.builtin.view.information.entropy"_lang);
|
ImGui::TextUnformatted("hex.builtin.view.information.entropy"_lang);
|
||||||
|
|
||||||
if (ImPlot::BeginPlot("##entropy", ImVec2(-1, 0), ImPlotFlags_NoChild | ImPlotFlags_CanvasOnly)) {
|
if (ImPlot::BeginPlot("##entropy", ImVec2(-1, 0), ImPlotFlags_NoChild | ImPlotFlags_CanvasOnly | ImPlotFlags_AntiAliased)) {
|
||||||
ImPlot::SetupAxes("hex.builtin.common.address"_lang, "hex.builtin.view.information.entropy"_lang, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock);
|
ImPlot::SetupAxes("hex.builtin.common.address"_lang, "hex.builtin.view.information.entropy"_lang, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock);
|
||||||
ImPlot::SetupAxesLimits(0, this->m_blockEntropy.size(), -0.1F, 1.1F, ImGuiCond_Always);
|
ImPlot::SetupAxesLimits(0, this->m_blockEntropy.size(), -0.1F, 1.1F, ImGuiCond_Always);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user