resolve conflict
This commit is contained in:
		
							
								
								
									
										6
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
									
									
									
									
								
							| @@ -25,7 +25,7 @@ LINUX_GL_LIBS = -lGL | ||||
|  | ||||
| CXXFLAGS = -std=c++20 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends | ||||
| CXXFLAGS += -DIMGUI_DEFINE_MATH_OPERATORS -Ofast | ||||
| LIBS = | ||||
| LIBS = -lexiv2 | ||||
|  | ||||
| ##--------------------------------------------------------------------- | ||||
| ## OPENGL ES | ||||
| @@ -44,9 +44,9 @@ LIBS = | ||||
|  | ||||
| ifeq ($(UNAME_S), Linux) #LINUX | ||||
| 	ECHO_MESSAGE = "Linux" | ||||
| 	LIBS += $(LINUX_GL_LIBS) -ldl `sdl2-config --libs` | ||||
| 	LIBS += $(LINUX_GL_LIBS) -ldl -L/usr/lib -lSDL2 | ||||
|  | ||||
| 	CXXFLAGS += `sdl2-config --cflags` | ||||
| 	CXXFLAGS += -I/usr/include/SDL2 -D_REENTRANT | ||||
| 	CFLAGS = $(CXXFLAGS) | ||||
| endif | ||||
|  | ||||
|   | ||||
							
								
								
									
										310
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										310
									
								
								main.cpp
									
									
									
									
									
								
							| @@ -7,6 +7,7 @@ | ||||
| #include "lib/imgui.h" | ||||
| #include "lib/imgui_internal.h" | ||||
| #include <cstdint> | ||||
| #include <exiv2/tags.hpp> | ||||
| #include <iostream> | ||||
| #include <stdexcept> | ||||
| #include <stdio.h> | ||||
| @@ -34,50 +35,139 @@ | ||||
| #include "lib/backends/tex_inspect_opengl.h" | ||||
| #include "lib/argparse.hpp" | ||||
|  | ||||
| #include <exiv2/exiv2.hpp> | ||||
|  | ||||
| struct Args : public argparse::Args { | ||||
|   std::string &fpath = arg("path to the image"); | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct EXIFData { | ||||
|   std::string CameraMake; | ||||
|   std::string CameraModel; | ||||
|   std::string LensModel; | ||||
|   std::string ImageOrientation; | ||||
|   std::string ImageDimensionX; | ||||
|   std::string ImageDimensiony; | ||||
|   std::string ISO; | ||||
|   std::string ShutterSpeed; | ||||
|   std::string FNumber; | ||||
|   std::string FocalLength; | ||||
|   std::string ExposureBias; | ||||
|   std::string MeteringMode; | ||||
|   std::string Flash; | ||||
|   std::string Time; | ||||
|   std::string TimeTaken; | ||||
|   std::string TimeTakenOffset; | ||||
|   std::string GPSLat; | ||||
|   std::string GPSLatref; | ||||
|   std::string GPSLon; | ||||
|   std::string GPSLonref; | ||||
| }; | ||||
|  | ||||
| struct Texture | ||||
| { | ||||
|     ImTextureID texture; | ||||
|     ImVec2 size; | ||||
|     int channels; | ||||
|     EXIFData exif; | ||||
| }; | ||||
|  | ||||
| static uint8_t* image = nullptr; | ||||
|  | ||||
| Texture LoadTexture(const char * path) | ||||
| { | ||||
|     const int channelCount = 4; | ||||
|     int imageFileChannelCount; | ||||
|     int width, height; | ||||
|     image = (uint8_t *)stbi_load(path, &width, &height, &imageFileChannelCount, channelCount); | ||||
|     if (image == NULL) | ||||
|     { | ||||
|         fprintf(stderr, "%s\nFailed to open %s\n", stbi_failure_reason(), path); | ||||
|  | ||||
|         return {nullptr,{0,0}}; | ||||
| EXIFData printExifData(const std::string& imagePath) { | ||||
|     EXIFData d; | ||||
|     d.CameraMake = "NULL"; | ||||
|     try { | ||||
|         // Load the image | ||||
|         Exiv2::Image::UniquePtr img = Exiv2::ImageFactory::open(imagePath); | ||||
|         if (img.get() == 0) { | ||||
|             std::cerr << "Error: Could not open image file " << imagePath << std::endl; | ||||
|             return d; | ||||
|         } | ||||
|         img->readMetadata(); | ||||
|  | ||||
|         // Get the Exif data | ||||
|         Exiv2::ExifData &exifData = img->exifData(); | ||||
|         if (exifData.empty()) { | ||||
|             std::cerr << "No EXIF data found in file " << imagePath << std::endl; | ||||
|             return d; | ||||
|         } | ||||
|  | ||||
|         // Helper function to print EXIF data if available | ||||
|         auto printExifValue = [&exifData](const char* key, std::string *d) { | ||||
|             Exiv2::ExifKey exifKey(key); | ||||
|             Exiv2::ExifData::const_iterator pos = exifData.findKey(exifKey); | ||||
|             if (pos != exifData.end()) { | ||||
|                 *d = pos->value().toString(); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         // Print common EXIF data | ||||
|         printExifValue("Exif.Image.Make", &d.CameraMake); | ||||
|         printExifValue("Exif.Image.Model", &d.CameraModel); | ||||
|         printExifValue("Exif.Photo.LensModel", &d.LensModel); | ||||
|  | ||||
|         printExifValue("Exif.Image.Orientation", &d.ImageOrientation); | ||||
|     // | ||||
|         printExifValue("Exif.Photo.ExposureTime", &d.ShutterSpeed); | ||||
|         printExifValue("Exif.Photo.FNumber", &d.FNumber); | ||||
|         printExifValue("Exif.Photo.ISOSpeedRatings", &d.ISO); | ||||
|         printExifValue("Exif.Photo.FocalLength", &d.FocalLength); | ||||
|         printExifValue("Exif.Photo.ExposureBiasValue", &d.ExposureBias); | ||||
|         printExifValue("Exif.Photo.MeteringMode", &d.MeteringMode); | ||||
|         printExifValue("Exif.Photo.Flash", &d.Flash); | ||||
|  | ||||
|         printExifValue("Exif.Image.DateTime", &d.Time); | ||||
|         printExifValue("Exif.Photo.DateTimeOriginal", &d.TimeTaken); | ||||
|         printExifValue("Exif.Photo.OffsetTime", &d.TimeTakenOffset); | ||||
|         printExifValue("Exif.Photo.PixelXDimension", &d.ImageDimensionX); | ||||
|         printExifValue("Exif.Photo.PixelYDimension", &d.ImageDimensiony); | ||||
|  | ||||
|         printExifValue("Exif.GPSInfo.GPSLatitudeRef", &d.GPSLatref); | ||||
|         printExifValue("Exif.GPSInfo.GPSLatitude", &d.GPSLat); | ||||
|         printExifValue("Exif.GPSInfo.GPSLongitudeRef", &d.GPSLonref); | ||||
|         printExifValue("Exif.GPSInfo.GPSLongitude", &d.GPSLon); | ||||
|  | ||||
|  | ||||
| /* | ||||
| Exif.Image.Make                              0x010f Ascii       5  SONY | ||||
| Exif.Image.Model                             0x0110 Ascii      10  ILCE-7RM5 | ||||
|  | ||||
| Exif.Image.Orientation                       0x0112 Short       1  8 | ||||
| Exif.Photo.PixelXDimension                   0xa002 Long        1  9504 | ||||
| Exif.Photo.PixelYDimension                   0xa003 Long        1  6336 | ||||
|  | ||||
| Exif.Photo.ExposureTime                      0x829a Rational    1  1/400 | ||||
| Exif.Photo.FNumber                           0x829d Rational    1  56/10 | ||||
| Exif.Photo.ISOSpeedRatings                   0x8827 Short       1  100 | ||||
| Exif.Photo.FocalLength                       0x920a Rational    1  400/10 | ||||
| Exif.Photo.ExposureBiasValue                 0x9204 SRational   1  -10/10 | ||||
| Exif.Photo.MeteringMode                      0x9207 Short       1  5 | ||||
| Exif.Photo.Flash                             0x9209 Short       1  16 | ||||
|  | ||||
| Exif.Image.DateTime                          0x0132 Ascii      20  2024:06:07 08:58:07 | ||||
| Exif.Photo.DateTimeOriginal                  0x9003 Ascii      20  2024:06:07 08:58:07 | ||||
| Exif.Photo.OffsetTime                        0x9010 Ascii       7  -05:00 | ||||
|  | ||||
| Exif.GPSInfo.GPSLatitudeRef                  0x0001 Ascii       2  N | ||||
| Exif.GPSInfo.GPSLatitude                     0x0002 Rational    3  40/1 43/1 32231/1000 | ||||
| Exif.GPSInfo.GPSLongitudeRef                 0x0003 Ascii       2  W | ||||
| Exif.GPSInfo.GPSLongitude                    0x0004 Rational    3  73/1 59/1 16688/1000 | ||||
| */ | ||||
|  | ||||
|     } catch (Exiv2::Error& e) { | ||||
|         std::cerr << "Error: " << e.what() << std::endl; | ||||
|     } | ||||
|  | ||||
|     GLenum dataFormat = GL_RGBA; | ||||
|     GLuint textureHandle; | ||||
|     glGenTextures(1, &textureHandle); | ||||
|     glBindTexture(GL_TEXTURE_2D, textureHandle); | ||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
|     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, dataFormat, GL_UNSIGNED_BYTE, image); | ||||
|  | ||||
|     Texture t; | ||||
|     t.texture = (void*)(uintptr_t)(textureHandle); | ||||
|     t.size = ImVec2((float)width,(float)height); | ||||
|     t.channels = channelCount; | ||||
|  | ||||
|     return t; | ||||
|   return d; | ||||
| } | ||||
|  | ||||
| Texture ReloadTexture(ImTextureID id, int width, int height) { | ||||
|     GLuint tid = (GLuint)(uintptr_t)id; | ||||
|  | ||||
|  | ||||
| Texture ReloadTexture(Texture tin, int width, int height) { | ||||
|     GLuint tid = (GLuint)(uintptr_t)tin.texture; | ||||
|     glDeleteTextures((GLsizei)1, &tid); | ||||
|  | ||||
|     GLenum dataFormat = GL_RGBA; | ||||
| @@ -91,6 +181,8 @@ Texture ReloadTexture(ImTextureID id, int width, int height) { | ||||
|     Texture t; | ||||
|     t.texture = (void*)(uintptr_t)(textureHandle); | ||||
|     t.size = ImVec2((float)width,(float)height); | ||||
|     t.exif = tin.exif; | ||||
|     t.channels = tin.channels; | ||||
|  | ||||
|     return t; | ||||
| } | ||||
| @@ -120,6 +212,43 @@ void RotateImage(Texture t) { | ||||
|   delete[] tempBuffer; | ||||
| } | ||||
|  | ||||
| Texture LoadTexture(const char * path) | ||||
| { | ||||
|     const int channelCount = 4; | ||||
|     int imageFileChannelCount; | ||||
|     int width, height; | ||||
|     image = (uint8_t *)stbi_load(path, &width, &height, &imageFileChannelCount, channelCount); | ||||
|  | ||||
|     if (image == NULL) | ||||
|     { | ||||
|         fprintf(stderr, "%s\nFailed to open %s\n", stbi_failure_reason(), path); | ||||
|  | ||||
|         return {nullptr,{0,0}}; | ||||
|     } | ||||
|  | ||||
|     auto exif = printExifData(path); | ||||
|  | ||||
|  | ||||
|  | ||||
|     GLenum dataFormat = GL_RGBA; | ||||
|     GLuint textureHandle; | ||||
|     glGenTextures(1, &textureHandle); | ||||
|     glBindTexture(GL_TEXTURE_2D, textureHandle); | ||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
|     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, dataFormat, GL_UNSIGNED_BYTE, image); | ||||
|  | ||||
|     Texture t; | ||||
|     t.texture = (void*)(uintptr_t)(textureHandle); | ||||
|     t.size = ImVec2((float)width,(float)height); | ||||
|     t.channels = channelCount; | ||||
|     t.exif = exif; | ||||
|  | ||||
|  | ||||
|     return t; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| const int MAX_ANNOATED_TEXELS = 10000; | ||||
|  | ||||
| @@ -136,6 +265,7 @@ int main(int argc, char* argv[]) { | ||||
|   bool GRID_ENABLED = false; | ||||
|   bool AA_ENABLED = true; | ||||
|   bool SHOW_HELP = false; | ||||
|   bool SHOW_EXIF = false; | ||||
|   int MODE = 0; | ||||
|  | ||||
|   // Decide GL+GLSL versions | ||||
| @@ -252,11 +382,14 @@ int main(int argc, char* argv[]) { | ||||
|               break; | ||||
|             case SDL_SCANCODE_R: | ||||
|               RotateImage(t); | ||||
|               t = ReloadTexture(t.texture, t.size.y, t.size.x); | ||||
|               t = ReloadTexture(t, t.size.y, t.size.x); | ||||
|               break; | ||||
|             case SDL_SCANCODE_Q: | ||||
|               done = true; | ||||
|               break; | ||||
|             case SDL_SCANCODE_E: | ||||
|               SHOW_EXIF = !SHOW_EXIF; | ||||
|               break; | ||||
|             default: | ||||
|               break; | ||||
|         } | ||||
| @@ -284,7 +417,7 @@ int main(int argc, char* argv[]) { | ||||
|       ImGui::SetNextWindowPos(viewport->Pos); | ||||
|       ImGui::SetNextWindowSize(viewport->Size); | ||||
|       ImGui::Begin("Main", NULL, | ||||
|                    ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize); | ||||
|                    ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBringToFrontOnFocus); | ||||
|       auto wSize = ImGui::GetContentRegionAvail(); | ||||
|       if (t.texture != 0) { | ||||
|  | ||||
| @@ -364,11 +497,132 @@ int main(int argc, char* argv[]) { | ||||
|         ImGui::Text("\tFloat Values"); | ||||
|         ImGui::Separator(); | ||||
|         ImGui::Text("h - show help popup"); | ||||
|         ImGui::Text("e - toggle EXIF info"); | ||||
|         ImGui::Separator(); | ||||
|         ImGui::Text("q - quit"); | ||||
|         ImGui::Separator(); | ||||
|         ImGui::Text("click anywhere to continue"); | ||||
|         ImGui::EndPopup(); | ||||
|       } | ||||
|       if (SHOW_EXIF && t.exif.CameraMake != "NULL") { | ||||
|         ImGuiWindowClass topmost; | ||||
|         topmost.ClassId = ImHashStr("TopMost"); | ||||
|         topmost.ViewportFlagsOverrideSet = ImGuiViewportFlags_TopMost; | ||||
|         ImGui::SetNextWindowClass(&topmost); | ||||
|         ImGui::Begin("EXIF", NULL, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize  | ImGuiWindowFlags_NoFocusOnAppearing); | ||||
|         if(ImGui::BeginTable("Hardware", 2)) { | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Make"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.CameraMake.c_str()); | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Model"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.CameraModel.c_str()); | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Lens"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.LensModel.c_str()); | ||||
|  | ||||
|           ImGui::EndTable(); | ||||
|         } | ||||
|  | ||||
|         ImGui::Separator(); | ||||
|  | ||||
|         if(ImGui::BeginTable("Photo", 2)) { | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Shutter Speed"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.ShutterSpeed.c_str()); | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("F-Stop"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.FNumber.c_str()); | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("ISO"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.ISO.c_str()); | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Focal Length"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.FocalLength.c_str()); | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Exposure Comp"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.ExposureBias.c_str()); | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Metering Mode"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.MeteringMode.c_str()); | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Flash"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s", t.exif.Flash.c_str()); | ||||
|  | ||||
|           ImGui::EndTable(); | ||||
|         } | ||||
|  | ||||
|         ImGui::Separator(); | ||||
|  | ||||
|         if(ImGui::BeginTable("Meta", 2)) { | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Date"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s %s", t.exif.TimeTaken.c_str(), t.exif.TimeTakenOffset.c_str()); | ||||
|  | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Dimensions"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%sx%s", t.exif.ImageDimensionX.c_str(), t.exif.ImageDimensiony.c_str()); | ||||
|  | ||||
|           ImGui::EndTable(); | ||||
|         } | ||||
|  | ||||
|         ImGui::Separator(); | ||||
|  | ||||
|         if(ImGui::BeginTable("Location", 2)) { | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Latitude"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s %s", t.exif.GPSLat.c_str(), t.exif.GPSLatref.c_str()); | ||||
|  | ||||
|  | ||||
|           ImGui::TableNextRow(); | ||||
|           ImGui::TableSetColumnIndex(0); | ||||
|           ImGui::Text("Longitude"); | ||||
|           ImGui::TableSetColumnIndex(1); | ||||
|           ImGui::Text("%s %s", t.exif.GPSLon.c_str(), t.exif.GPSLonref.c_str()); | ||||
|  | ||||
|           ImGui::EndTable(); | ||||
|         } | ||||
|  | ||||
|         ImGui::Separator(); | ||||
|         ImGui::Text("Press e to hide"); | ||||
|  | ||||
|         ImGui::End(); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Rendering | ||||
|   | ||||
		Reference in New Issue
	
	Block a user