├── .gitignore ├── InspectNormalMap.png ├── LICENSE ├── README.md ├── imgInspect.gif ├── imgInspect.h └── inspectPicture.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /InspectNormalMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CedricGuillemet/imgInspect/5b29b20f72109fb5106bcaccc31a616ee414a541/InspectNormalMap.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Cedric Guillemet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # imgInspect 2 | imgui tooltip control to inspect image pixels 3 | 4 | ![Image of imgInspect](https://github.com/CedricGuillemet/imgInspect/blob/master/imgInspect.gif) 5 | 6 | ![inspect pictures](https://github.com/CedricGuillemet/imgInspect/blob/master/inspectPicture.png) 7 | ![inspect normal map](https://github.com/CedricGuillemet/imgInspect/blob/master/InspectNormalMap.png) 8 | -------------------------------------------------------------------------------- /imgInspect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CedricGuillemet/imgInspect/5b29b20f72109fb5106bcaccc31a616ee414a541/imgInspect.gif -------------------------------------------------------------------------------- /imgInspect.h: -------------------------------------------------------------------------------- 1 | // https://github.com/CedricGuillemet/imgInspect 2 | // 3 | // The MIT License(MIT) 4 | // 5 | // Copyright(c) 2019 Cedric Guillemet 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files(the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions : 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | /* 26 | example 27 | Image pickerImage; 28 | ImGui::ImageButton(pickerImage.textureID, ImVec2(pickerImage.mWidth, pickerImage.mHeight)); 29 | ImRect rc = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); 30 | ImVec2 mouseUVCoord = (io.MousePos - rc.Min) / rc.GetSize(); 31 | mouseUVCoord.y = 1.f - mouseUVCoord.y; 32 | 33 | 34 | if (io.KeyShift && io.MouseDown[0] && mouseUVCoord.x >= 0.f && mouseUVCoord.y >= 0.f) 35 | { 36 | int width = pickerImage.mWidth; 37 | int height = pickerImage.mHeight; 38 | 39 | imageInspect(width, height, pickerImage.GetBits(), mouseUVCoord, displayedTextureSize); 40 | } 41 | */ 42 | #pragma once 43 | 44 | namespace ImageInspect 45 | { 46 | inline void histogram(const int width, const int height, const unsigned char* const bits) 47 | { 48 | unsigned int count[4][256] = {0}; 49 | 50 | const unsigned char* ptrCols = bits; 51 | 52 | ImGui::InvisibleButton("histogram", ImVec2(512, 256)); 53 | for (int l = 0; l < height * width; l++) 54 | { 55 | count[0][*ptrCols++]++; 56 | count[1][*ptrCols++]++; 57 | count[2][*ptrCols++]++; 58 | count[3][*ptrCols++]++; 59 | } 60 | 61 | unsigned int maxv = count[0][0]; 62 | unsigned int* pCount = &count[0][0]; 63 | for (int i = 0; i < 3 * 256; i++, pCount++) 64 | { 65 | maxv = (maxv > *pCount) ? maxv : *pCount; 66 | } 67 | 68 | ImDrawList* drawList = ImGui::GetWindowDrawList(); 69 | const ImVec2 rmin = ImGui::GetItemRectMin(); 70 | const ImVec2 rmax = ImGui::GetItemRectMax(); 71 | const ImVec2 size = ImGui::GetItemRectSize(); 72 | const float hFactor = size.y / float(maxv); 73 | 74 | for (int i = 0; i <= 10; i++) 75 | { 76 | float ax = rmin.x + (size.x / 10.f) * float(i); 77 | float ay = rmin.y + (size.y / 10.f) * float(i); 78 | drawList->AddLine(ImVec2(rmin.x, ay), ImVec2(rmax.x, ay), 0x80808080); 79 | drawList->AddLine(ImVec2(ax, rmin.y), ImVec2(ax, rmax.y), 0x80808080); 80 | } 81 | 82 | const float barWidth = (size.x / 256.f); 83 | for (int j = 0; j < 256; j++) 84 | { 85 | // pixel count << 2 + color index(on 2 bits) 86 | uint32_t cols[3] = {(count[0][j] << 2), (count[1][j] << 2) + 1, (count[2][j] << 2) + 2}; 87 | if (cols[0] > cols[1]) 88 | ImSwap(cols[0], cols[1]); 89 | if (cols[1] > cols[2]) 90 | ImSwap(cols[1], cols[2]); 91 | if (cols[0] > cols[1]) 92 | ImSwap(cols[0], cols[1]); 93 | float heights[3]; 94 | uint32_t colors[3]; 95 | uint32_t currentColor = 0xFFFFFFFF; 96 | for (int i = 0; i < 3; i++) 97 | { 98 | heights[i] = rmax.y - (cols[i] >> 2) * hFactor; 99 | colors[i] = currentColor; 100 | currentColor -= 0xFF << ((cols[i] & 3) * 8); 101 | } 102 | 103 | float currentHeight = rmax.y; 104 | const float left = rmin.x + barWidth * float(j); 105 | const float right = left + barWidth; 106 | for (int i = 0; i < 3; i++) 107 | { 108 | if (heights[i] >= currentHeight) 109 | { 110 | continue; 111 | } 112 | drawList->AddRectFilled(ImVec2(left, currentHeight), ImVec2(right, heights[i]), colors[i]); 113 | currentHeight = heights[i]; 114 | } 115 | } 116 | } 117 | inline void drawNormal(ImDrawList* draw_list, const ImRect& rc, float x, float y) 118 | { 119 | draw_list->AddCircle(rc.GetCenter(), rc.GetWidth() / 2.f, 0x20AAAAAA, 24, 1.f); 120 | draw_list->AddCircle(rc.GetCenter(), rc.GetWidth() / 4.f, 0x20AAAAAA, 24, 1.f); 121 | draw_list->AddLine(rc.GetCenter(), rc.GetCenter() + ImVec2(x, y) * rc.GetWidth() / 2.f, 0xFF0000FF, 2.f); 122 | } 123 | 124 | inline void inspect(const int width, 125 | const int height, 126 | const unsigned char* const bits, 127 | ImVec2 mouseUVCoord, 128 | ImVec2 displayedTextureSize) 129 | { 130 | ImGui::BeginTooltip(); 131 | ImGui::BeginGroup(); 132 | ImDrawList* draw_list = ImGui::GetWindowDrawList(); 133 | static const float zoomRectangleWidth = 160.f; 134 | 135 | // bitmap zoom 136 | ImGui::InvisibleButton("AnotherInvisibleMan", ImVec2(zoomRectangleWidth, zoomRectangleWidth)); 137 | const ImRect pickRc(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); 138 | draw_list->AddRectFilled(pickRc.Min, pickRc.Max, 0xFF000000); 139 | static int zoomSize = 4; 140 | const float quadWidth = zoomRectangleWidth / float(zoomSize * 2 + 1); 141 | const ImVec2 quadSize(quadWidth, quadWidth); 142 | const int basex = ImClamp(int(mouseUVCoord.x * width), zoomSize, width - zoomSize); 143 | const int basey = ImClamp(int(mouseUVCoord.y * height), zoomSize, height - zoomSize); 144 | for (int y = -zoomSize; y <= zoomSize; y++) 145 | { 146 | for (int x = -zoomSize; x <= zoomSize; x++) 147 | { 148 | uint32_t texel = ((uint32_t*)bits)[(basey - y) * width + x + basex]; 149 | ImVec2 pos = pickRc.Min + ImVec2(float(x + zoomSize), float(y + zoomSize)) * quadSize; 150 | draw_list->AddRectFilled(pos, pos + quadSize, texel); 151 | } 152 | } 153 | ImGui::SameLine(); 154 | 155 | // center quad 156 | const ImVec2 pos = pickRc.Min + ImVec2(float(zoomSize), float(zoomSize)) * quadSize; 157 | draw_list->AddRect(pos, pos + quadSize, 0xFF0000FF, 0.f, 15, 2.f); 158 | 159 | // normal direction 160 | ImGui::InvisibleButton("AndOneMore", ImVec2(zoomRectangleWidth, zoomRectangleWidth)); 161 | ImRect normRc(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); 162 | for (int y = -zoomSize; y <= zoomSize; y++) 163 | { 164 | for (int x = -zoomSize; x <= zoomSize; x++) 165 | { 166 | uint32_t texel = ((uint32_t*)bits)[(basey - y) * width + x + basex]; 167 | const ImVec2 posQuad = normRc.Min + ImVec2(float(x + zoomSize), float(y + zoomSize)) * quadSize; 168 | //draw_list->AddRectFilled(pos, pos + quadSize, texel); 169 | const float nx = float(texel & 0xFF) / 128.f - 1.f; 170 | const float ny = float((texel & 0xFF00)>>8) / 128.f - 1.f; 171 | const ImRect rc(posQuad, posQuad + quadSize); 172 | drawNormal(draw_list, rc, nx, ny); 173 | } 174 | } 175 | 176 | 177 | 178 | ImGui::EndGroup(); 179 | ImGui::SameLine(); 180 | ImGui::BeginGroup(); 181 | uint32_t texel = ((uint32_t*)bits)[(basey - zoomSize * 2 - 1) * width + basex]; 182 | ImVec4 color = ImColor(texel); 183 | ImVec4 colHSV; 184 | ImGui::ColorConvertRGBtoHSV(color.x, color.y, color.z, colHSV.x, colHSV.y, colHSV.z); 185 | ImGui::Text("U %1.3f V %1.3f", mouseUVCoord.x, mouseUVCoord.y); 186 | ImGui::Text("Coord %d %d", int(mouseUVCoord.x * width), int(mouseUVCoord.y * height)); 187 | ImGui::Separator(); 188 | ImGui::Text("R 0x%02x G 0x%02x B 0x%02x", int(color.x * 255.f), int(color.y * 255.f), int(color.z * 255.f)); 189 | ImGui::Text("R %1.3f G %1.3f B %1.3f", color.x, color.y, color.z); 190 | ImGui::Separator(); 191 | ImGui::Text( 192 | "H 0x%02x S 0x%02x V 0x%02x", int(colHSV.x * 255.f), int(colHSV.y * 255.f), int(colHSV.z * 255.f)); 193 | ImGui::Text("H %1.3f S %1.3f V %1.3f", colHSV.x, colHSV.y, colHSV.z); 194 | ImGui::Separator(); 195 | ImGui::Text("Alpha 0x%02x", int(color.w * 255.f)); 196 | ImGui::Text("Alpha %1.3f", color.w); 197 | ImGui::Separator(); 198 | ImGui::Text("Size %d, %d", int(displayedTextureSize.x), int(displayedTextureSize.y)); 199 | ImGui::EndGroup(); 200 | histogram(width, height, bits); 201 | ImGui::EndTooltip(); 202 | } 203 | } // namespace ImageInspect 204 | -------------------------------------------------------------------------------- /inspectPicture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CedricGuillemet/imgInspect/5b29b20f72109fb5106bcaccc31a616ee414a541/inspectPicture.png --------------------------------------------------------------------------------