From bbb071f1e8e9429ea49d869437a56d2876fb8287 Mon Sep 17 00:00:00 2001 From: "Robert C. Helling" Date: Thu, 13 Feb 2014 16:43:55 +0100 Subject: Compute dive computer/camera time offset from sample picture Signed-off-by: Robert C. Helling Signed-off-by: Dirk Hohndel --- qt-ui/divelistview.cpp | 16 ++--- qt-ui/divelistview.h | 2 +- qt-ui/shiftimagetimes.ui | 152 ++++++++++++++++++++++++++++++++++++++++++----- qt-ui/simplewidgets.cpp | 70 ++++++++++++++++++++-- qt-ui/simplewidgets.h | 11 +++- 5 files changed, 216 insertions(+), 35 deletions(-) diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp index 14a2f30e5..c8a5f2b72 100644 --- a/qt-ui/divelistview.cpp +++ b/qt-ui/divelistview.cpp @@ -804,6 +804,7 @@ void DiveListView::loadImages() { struct memblock mem; EXIFInfo exif; + int retval; time_t imagetime; QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open Image Files"), lastUsedImageDir(), tr("Image Files (*.jpg *.jpeg *.pnm *.tif *.tiff)")); @@ -818,23 +819,16 @@ void DiveListView::loadImages() updateLastImageTimeOffset(shiftDialog.amount()); for (int i = 0; i < fileNames.size(); ++i) { - struct tm tm; - int year, month, day, hour, min, sec; - int retval; if (readfile(fileNames.at(i).toUtf8().data(), &mem) <= 0) continue; retval = exif.parseFrom((const unsigned char *) mem.buffer, (unsigned) mem.size); free(mem.buffer); if (retval != PARSE_EXIF_SUCCESS) continue; - sscanf(exif.DateTime.c_str(), "%d:%d:%d %d:%d:%d", &year, &month, &day, &hour, &min, &sec); - tm.tm_year = year; - tm.tm_mon = month - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - imagetime = utc_mktime(&tm) + shiftDialog.amount(); + imagetime = shiftDialog.epochFromExiv(&exif); + if (!imagetime) + continue; + imagetime += shiftDialog.amount(); int j = 0; struct dive *dive; for_each_dive(j, dive){ diff --git a/qt-ui/divelistview.h b/qt-ui/divelistview.h index c6321223c..c77b85f24 100644 --- a/qt-ui/divelistview.h +++ b/qt-ui/divelistview.h @@ -52,6 +52,7 @@ public slots: void shiftTimes(); void loadImages(); void uploadToDivelogsDE(); + QString lastUsedImageDir(); signals: void currentDiveChanged(int divenr); @@ -73,7 +74,6 @@ private: void restoreExpandedRows(); int lastVisibleColumn(); void selectTrip ( dive_trip_t* trip ); - QString lastUsedImageDir(); void updateLastUsedImageDir(const QString& s); void updateLastImageTimeOffset(int offset); int lastImageTimeOffset(); diff --git a/qt-ui/shiftimagetimes.ui b/qt-ui/shiftimagetimes.ui index 653103b53..0e91ad63f 100644 --- a/qt-ui/shiftimagetimes.ui +++ b/qt-ui/shiftimagetimes.ui @@ -6,8 +6,8 @@ 0 0 - 343 - 177 + 693 + 606 @@ -25,7 +25,7 @@ - + Shift times of image(s) by @@ -40,6 +40,16 @@ 1 + + + 23 + 59 + 59 + 2010 + 12 + 31 + + 0 @@ -51,14 +61,32 @@ + + 2010 + 12 + 31 + + + 2000 1 1 - - h:mm + + + + + Qt::LocalTime @@ -82,19 +110,113 @@ + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Horizontal + + + + + + + + 16777215 + 60 + + + + Qt::LeftToRight + + + To compute the offset between the clocks of your dive computer and your camera use your camera to take a picture of your dive compuer displaying the current time. Download that image to your computer and press this button. + + + true + + + + + + + Determine camera time offset + + + Select image of divecomputer showing time + + + + + + + false + + + + + + + + 0 + 70 + 161 + 24 + + + + + + + 0 + 10 + 234 + 60 + + + + + 16777215 + 60 + + + + Which date and time are displayed on the image? + + + true + + + + + + 260 + 10 + 361 + 281 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + + - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 5d7ed299a..2a77a1c5d 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -12,8 +12,11 @@ #include #include #include - +#include +#include +#include "exif.h" #include "../dive.h" +#include "../file.h" #include "mainwindow.h" class MinMaxAvgWidgetPrivate { @@ -168,23 +171,80 @@ void ShiftImageTimesDialog::buttonClicked(QAbstractButton* button) } } +void ShiftImageTimesDialog::syncCameraClicked() +{ + struct memblock mem; + EXIFInfo exiv; + int retval; + QPixmap picture; + QDateTime dcDateTime = QDateTime::QDateTime(); + QStringList fileNames = QFileDialog::getOpenFileNames(this, + tr("Open Image File"), + MainWindow().dive_list()->lastUsedImageDir(), + tr("Image Files (*.jpg *.jpeg *.pnm *.tif *.tiff)")); + + if (fileNames.isEmpty()) + return; + + picture.load(fileNames.at(0)); + ui.displayDC->setEnabled(TRUE); + QGraphicsScene *scene = new QGraphicsScene (this); + + scene->addPixmap(picture.scaled(ui.DCImage->size())); + ui.DCImage->setScene(scene); + if (readfile(fileNames.at(0).toUtf8().data(), &mem) <= 0) + return; + retval = exiv.parseFrom((const unsigned char *) mem.buffer, (unsigned) mem.size); + free(mem.buffer); + if (retval != PARSE_EXIF_SUCCESS) + return; + dcImageEpoch = epochFromExiv(&exiv); + dcDateTime.setTime_t(dcImageEpoch); + ui.dcTime->setDateTime(dcDateTime); + connect(ui.dcTime, SIGNAL(dateTimeChanged(const QDateTime &)), this, SLOT(dcDateTimeChanged(const QDateTime &))); +} + +time_t ShiftImageTimesDialog::epochFromExiv(EXIFInfo *exif) +{ + struct tm tm; + int year, month, day, hour, min, sec; + + sscanf(exif->DateTime.c_str(), "%d:%d:%d %d:%d:%d", &year, &month, &day, &hour, &min, &sec); + tm.tm_year = year; + tm.tm_mon = month - 1; + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = min; + tm.tm_sec = sec; + return (utc_mktime(&tm)); +} + +void ShiftImageTimesDialog::dcDateTimeChanged(const QDateTime &newDateTime) +{ + if (!dcImageEpoch) + return; + setOffset(newDateTime.toTime_t() - dcImageEpoch); +} + ShiftImageTimesDialog::ShiftImageTimesDialog(QWidget *parent): QDialog(parent), m_amount(0) { ui.setupUi(this); connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonClicked(QAbstractButton*))); + connect(ui.syncCamera, SIGNAL(clicked()), this, SLOT(syncCameraClicked())); + dcImageEpoch = (time_t) 0; } -int ShiftImageTimesDialog::amount() const +time_t ShiftImageTimesDialog::amount() const { return m_amount; } -void ShiftImageTimesDialog::setOffset(int offset) +void ShiftImageTimesDialog::setOffset(time_t offset) { if (offset >= 0) { - ui.forward->setDown(TRUE); + ui.forward->setChecked(TRUE); } else { - ui.backwards->setDown(TRUE); + ui.backwards->setChecked(TRUE); offset *= -1; } ui.timeEdit->setTime(QTime::QTime(offset / 3600, (offset % 3600) / 60, offset % 60)); diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index d227c91df..098b227f6 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -10,6 +10,7 @@ class QAbstractButton; #include "ui_renumber.h" #include "ui_shifttimes.h" #include "ui_shiftimagetimes.h" +#include "exif.h" class MinMaxAvgWidget : public QWidget{ Q_OBJECT @@ -59,13 +60,17 @@ class ShiftImageTimesDialog : public QDialog { Q_OBJECT public: explicit ShiftImageTimesDialog(QWidget *parent); - int amount() const; - void setOffset(int offset); + time_t amount() const; + void setOffset(time_t offset); + time_t epochFromExiv(EXIFInfo *exif); private slots: void buttonClicked(QAbstractButton *button); + void syncCameraClicked(); + void dcDateTimeChanged(const QDateTime &); private: Ui::ShiftImageTimesDialog ui; - int m_amount; + time_t m_amount; + time_t dcImageEpoch; }; bool isGnome3Session(); -- cgit v1.2.3-70-g09d2