diff --git a/lib/histogram.h b/lib/histogram.h new file mode 100644 index 0000000..c9541b7 --- /dev/null +++ b/lib/histogram.h @@ -0,0 +1,94 @@ +#include +#include "./imgui.h" +#include "./imgui_internal.h" + +class Histogram { + +public: + unsigned int **counts = nullptr; + int width = 0; + int height = 0; + int channels = 0; + + Histogram(); + + void Load() { + + }; + + void Draw() { + + }; + +}; + +inline void histogram(const int width, const int height, const int channels, const unsigned char* const bits) { + unsigned int count[4][256] = {0}; + + const unsigned char* ptrCols = bits; + + ImGui::InvisibleButton("histogram", ImVec2(512, 256)); + for (int l = 0; l < height * width; l++) + { + count[0][*ptrCols++]++; + count[1][*ptrCols++]++; + count[2][*ptrCols++]++; + count[3][*ptrCols++]++; + } + + unsigned int maxv = count[0][0]; + unsigned int* pCount = &count[0][0]; + for (int i = 0; i < 3 * 256; i++, pCount++) + { + maxv = (maxv > *pCount) ? maxv : *pCount; + } + + ImDrawList* drawList = ImGui::GetWindowDrawList(); + const ImVec2 rmin = ImGui::GetItemRectMin(); + const ImVec2 rmax = ImGui::GetItemRectMax(); + const ImVec2 size = ImGui::GetItemRectSize(); + const float hFactor = size.y / float(maxv); + + for (int i = 0; i <= 10; i++) + { + float ax = rmin.x + (size.x / 10.f) * float(i); + float ay = rmin.y + (size.y / 10.f) * float(i); + drawList->AddLine(ImVec2(rmin.x, ay), ImVec2(rmax.x, ay), 0x80808080); + drawList->AddLine(ImVec2(ax, rmin.y), ImVec2(ax, rmax.y), 0x80808080); + } + + const float barWidth = (size.x / 256.f); + for (int j = 0; j < 256; j++) + { + // pixel count << 2 + color index(on 2 bits) + uint32_t cols[3] = {(count[0][j] << 2), (count[1][j] << 2) + 1, (count[2][j] << 2) + 2}; + if (cols[0] > cols[1]) + ImSwap(cols[0], cols[1]); + if (cols[1] > cols[2]) + ImSwap(cols[1], cols[2]); + if (cols[0] > cols[1]) + ImSwap(cols[0], cols[1]); + float heights[3]; + uint32_t colors[3]; + uint32_t currentColor = 0xFFFFFFFF; + for (int i = 0; i < 3; i++) + { + heights[i] = rmax.y - (cols[i] >> 2) * hFactor; + colors[i] = currentColor; + currentColor -= 0xFF << ((cols[i] & 3) * 8); + } + + float currentHeight = rmax.y; + const float left = rmin.x + barWidth * float(j); + const float right = left + barWidth; + for (int i = 0; i < 3; i++) + { + if (heights[i] >= currentHeight) + { + continue; + } + drawList->AddRectFilled(ImVec2(left, currentHeight), ImVec2(right, heights[i]), colors[i]); + currentHeight = heights[i]; + } + } +} diff --git a/main.cpp b/main.cpp index eb1c881..4f82285 100644 --- a/main.cpp +++ b/main.cpp @@ -37,6 +37,8 @@ #include +#include "lib/histogram.h" + struct Args : public argparse::Args { std::string &fpath = arg("path to the image"); }; @@ -228,8 +230,6 @@ Texture LoadTexture(const char * path) auto exif = printExifData(path); - - GLenum dataFormat = GL_RGBA; GLuint textureHandle; glGenTextures(1, &textureHandle); @@ -244,6 +244,23 @@ Texture LoadTexture(const char * path) t.channels = channelCount; t.exif = exif; + if (t.exif.ImageOrientation == "3") { + RotateImage(t); + ReloadTexture(t, t.size.x, t.size.y); + t = ReloadTexture(t, t.size.y, t.size.x); + RotateImage(t); + t = ReloadTexture(t, t.size.y, t.size.x); + } else if (t.exif.ImageOrientation == "6") { + RotateImage(t); + t = ReloadTexture(t, t.size.y, t.size.x); + } else if (t.exif.ImageOrientation == "8") { + RotateImage(t); + t = ReloadTexture(t, t.size.y, t.size.x); + RotateImage(t); + t = ReloadTexture(t, t.size.y, t.size.x); + RotateImage(t); + t = ReloadTexture(t, t.size.y, t.size.x); + } return t; } @@ -596,6 +613,12 @@ int main(int argc, char* argv[]) { ImGui::TableSetColumnIndex(1); ImGui::Text("%sx%s", t.exif.ImageDimensionX.c_str(), t.exif.ImageDimensiony.c_str()); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("Orientation"); + ImGui::TableSetColumnIndex(1); + ImGui::Text("%s", t.exif.ImageOrientation.c_str()); + ImGui::EndTable(); }