diff --git a/CMakeMod/FindExif.cmake b/CMakeMod/FindExif.cmake new file mode 100644 index 0000000..f7a4de6 --- /dev/null +++ b/CMakeMod/FindExif.cmake @@ -0,0 +1,28 @@ +# - Try to find LibExif +# Once done this will define +# Exif_FOUND - System has LibExif +# Exif_INCLUDE_DIRS - The LibExif include directories +# Exif_LIBRARIES - The libraries needed to use LibExif +# Exif_DEFINITIONS - Compiler switches required for using LibExif + +find_package(PkgConfig) +pkg_check_modules(PC_Exif QUIET libExif) +set(Exif_DEFINITIONS ${PC_Exif_CFLAGS_OTHER}) + +find_path(Exif_INCLUDE_DIR exif-utils.h + HINTS ${PC_Exif_INCLUDEDIR} ${PC_Exif_INCLUDE_DIRS} + PATH_SUFFIXES libexif ) + +find_library(Exif_LIBRARY NAMES exif + HINTS ${PC_Exif_LIBDIR} ${PC_Exif_LIBRARY_DIRS} ) + +set(Exif_LIBRARIES ${Exif_LIBRARY} ) +set(Exif_INCLUDE_DIRS ${Exif_INCLUDE_DIR} ) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set Exif_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(Exif DEFAULT_MSG + Exif_LIBRARY Exif_INCLUDE_DIR) + +mark_as_advanced(Exif_INCLUDE_DIR Exif_LIBRARY ) diff --git a/README.md b/README.md index d13659b..e9b59c0 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ All captured with Nikon D5100, raw processed by Rawtherapee, then assembled by T ## Build This project is written in C++ with usage of QT framework and some other libraries -(ImageMagic, VidStab, V4L, GPHOTO2). +(ImageMagic, VidStab, V4L, GPHOTO2, exif). I invest effort to create tools multiplatform, but I tested it on Ubuntu Linux only. Moreover, V4L is Linux-only api. It uses avconv or ffmpeg to build final videos. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c2c7d2c..a79afa4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,7 +9,8 @@ FIND_PACKAGE(Qt5 REQUIRED COMPONENTS Core Multimedia) FIND_PACKAGE(ImageMagick REQUIRED COMPONENTS Magick++ MagickCore) FIND_PACKAGE(VidStab REQUIRED) FIND_PACKAGE(V4L REQUIRED) -FIND_PACKAGE(GPHOTO2 REQUIRED) +FIND_PACKAGE(GPHOTO2 REQUIRED) +FIND_PACKAGE(Exif REQUIRED) set(DESCRIBE_CMD "git describe --tags --dirty=+dirty --match 'v[0-9]*' | sed -E 's/^v//' ") execute_process( @@ -33,7 +34,8 @@ include_directories( ${VIDSTAB_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} # timelapse_version.h ${V4L_INCLUDE_DIRS} - ${GPHOTO2_INCLUDE_DIR}) + ${GPHOTO2_INCLUDE_DIR} + ${Exif_INCLUDE_DIRS}) # enable warnings ADD_DEFINITIONS( -Wall -Wextra -pedantic -fPIC) @@ -74,6 +76,9 @@ message(STATUS "V4L_FOUND: ${V4L_FOUND}") message(STATUS "GPHOTO2_FOUND: ${GPHOTO2_FOUND}") message(STATUS "GPHOTO2_INCLUDE_DIR: ${GPHOTO2_INCLUDE_DIR}") message(STATUS "GPHOTO2_LIBRARIES: ${GPHOTO2_LIBRARIES}") +message(STATUS "Exif_FOUND: ${Exif_FOUND}") +message(STATUS "Exif_INCLUDE_DIR: ${Exif_INCLUDE_DIR}") +message(STATUS "Exif_LIBRARIES: ${Exif_LIBRARIES}") set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) @@ -164,7 +169,8 @@ target_link_libraries(timelapse ${ImageMagick_LIBRARIES} # Magick++-6.Q16 ${VIDSTAB_LIBRARIES} ${V4L_LIBRARIES} - ${GPHOTO2_LIBRARIES}) + ${GPHOTO2_LIBRARIES} + ${Exif_LIBRARIES}) target_link_libraries(timelapse_assembly timelapse diff --git a/src/capture.cpp b/src/capture.cpp index ea245e2..d21b212 100644 --- a/src/capture.cpp +++ b/src/capture.cpp @@ -26,6 +26,8 @@ #include #include +#include + namespace timelapse { AdaptiveShutterSpeedAlg::AdaptiveShutterSpeedAlg( @@ -374,13 +376,41 @@ void TimeLapseCapture::onImageCaptured(QString format, Magick::Blob blob, Magick shutterSpdAlg->update(capturedImage); } - QDateTime now = QDateTime::currentDateTime(); - QString exifDateTime = now.toString("yyyy:MM:dd HH:mm:ss");\ + if (capturedImage.attribute("EXIF:DateTime").length() == 0) { + QDateTime now = QDateTime::currentDateTime(); + QString exifDateTime = now.toString("yyyy:MM:dd HH:mm:ss"); + + Magick::Blob profile = capturedImage.exifProfile(); + ExifData *data = exif_data_new(); + + exif_data_set_option(data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); + exif_data_set_data_type(data, EXIF_DATA_TYPE_COMPRESSED); + exif_data_set_byte_order(data, EXIF_BYTE_ORDER_INTEL); + + exif_data_load_data(data, static_cast(profile.data()), profile.length()); - // ImageMagick don't support writing of exif data - // TODO: setup exif timestamp correctly - capturedImage.attribute("EXIF:DateTime", exifDateTime.toStdString()); - //capturedImage.defineValue("EXIF", "DateTime", exifDateTime.toStdString()); + ExifMem *exifMem = exif_mem_new_default(); + ExifEntry *pE = exif_entry_new(); + exif_content_add_entry(data->ifd[EXIF_IFD_0], pE); + exif_entry_initialize(pE, EXIF_TAG_DATE_TIME); + std::string dateStr = exifDateTime.toStdString(); + pE->data = static_cast(exif_mem_alloc(exifMem, dateStr.length() +1 +8)); + memcpy(pE->data, dateStr.c_str(), dateStr.length() +1); + //memcpy(pE->data, "ASCII\0\0\0", 8); + //memcpy(pE->data+8, dateStr.c_str(), dateStr.length() +1); + + unsigned char *d; + unsigned int ds; + + exif_data_dump(data); + exif_data_save_data(data, &d, &ds); + profile = Magick::Blob(d, ds); + capturedImage.exifProfile(profile); + + exif_entry_unref(pE); + exif_mem_free(exifMem, d); + exif_data_free(data); + } capturedImage.compressType(Magick::JPEGCompression); capturedImage.magick("JPEG");