mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
Compute dive computer/camera time offset from sample picture
Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
fe2a264db3
commit
bbb071f1e8
5 changed files with 216 additions and 35 deletions
|
@ -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){
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>343</width>
|
||||
<height>177</height>
|
||||
<width>693</width>
|
||||
<height>606</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -25,7 +25,7 @@
|
|||
</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item alignment="Qt::AlignTop">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Shift times of image(s) by</string>
|
||||
|
@ -40,6 +40,16 @@
|
|||
<day>1</day>
|
||||
</date>
|
||||
</property>
|
||||
<property name="maximumDateTime">
|
||||
<datetime>
|
||||
<hour>23</hour>
|
||||
<minute>59</minute>
|
||||
<second>59</second>
|
||||
<year>2010</year>
|
||||
<month>12</month>
|
||||
<day>31</day>
|
||||
</datetime>
|
||||
</property>
|
||||
<property name="minimumDateTime">
|
||||
<datetime>
|
||||
<hour>0</hour>
|
||||
|
@ -51,14 +61,32 @@
|
|||
</datetime>
|
||||
</property>
|
||||
<property name="maximumDate">
|
||||
<date>
|
||||
<year>2010</year>
|
||||
<month>12</month>
|
||||
<day>31</day>
|
||||
</date>
|
||||
</property>
|
||||
<property name="minimumDate">
|
||||
<date>
|
||||
<year>2000</year>
|
||||
<month>1</month>
|
||||
<day>1</day>
|
||||
</date>
|
||||
</property>
|
||||
<property name="displayFormat">
|
||||
<string>h:mm</string>
|
||||
<property name="maximumTime">
|
||||
<time>
|
||||
<hour>23</hour>
|
||||
<minute>59</minute>
|
||||
<second>59</second>
|
||||
</time>
|
||||
</property>
|
||||
<property name="minimumTime">
|
||||
<time>
|
||||
<hour>0</hour>
|
||||
<minute>0</minute>
|
||||
<second>0</second>
|
||||
</time>
|
||||
</property>
|
||||
<property name="timeSpec">
|
||||
<enum>Qt::LocalTime</enum>
|
||||
|
@ -82,19 +110,113 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>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.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="syncCamera">
|
||||
<property name="toolTip">
|
||||
<string>Determine camera time offset</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select image of divecomputer showing time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="displayDC">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<widget class="QDateTimeEdit" name="dcTime">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>70</y>
|
||||
<width>161</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>10</y>
|
||||
<width>234</width>
|
||||
<height>60</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Which date and time are displayed on the image?</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QGraphicsView" name="DCImage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>10</y>
|
||||
<width>361</width>
|
||||
<height>281</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
|
|
|
@ -12,8 +12,11 @@
|
|||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
#include <QTime>
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QDateTime>
|
||||
#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));
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue