1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

feat(exif): Honour exif orientation tag

Fixes #1848
This commit is contained in:
anthony.bilinski 2017-09-11 16:55:13 -07:00
parent c49959711e
commit 414fa178b4
7 changed files with 96 additions and 2 deletions

View File

@ -31,6 +31,7 @@ sudo apt-get install -y --force-yes \
build-essential \ build-essential \
check \ check \
checkinstall \ checkinstall \
libexif-dev \
libgdk-pixbuf2.0-dev \ libgdk-pixbuf2.0-dev \
libglib2.0-dev \ libglib2.0-dev \
libgtk2.0-dev \ libgtk2.0-dev \

View File

@ -266,6 +266,7 @@ sudo apt-get install \
build-essential \ build-essential \
cmake \ cmake \
ffmpeg \ ffmpeg \
libexif-dev \
libgdk-pixbuf2.0-dev \ libgdk-pixbuf2.0-dev \
libglib2.0-dev \ libglib2.0-dev \
libgtk2.0-dev \ libgtk2.0-dev \
@ -300,6 +301,7 @@ sudo dnf groupinstall "Development Tools" "C Development Tools and Libraries"
sudo dnf install \ sudo dnf install \
ffmpeg-devel \ ffmpeg-devel \
gtk2-devel \ gtk2-devel \
libexif-devel \
libXScrnSaver-devel \ libXScrnSaver-devel \
libtool \ libtool \
openal-soft-devel \ openal-soft-devel \
@ -324,6 +326,7 @@ sudo dnf install \
```bash ```bash
sudo zypper install \ sudo zypper install \
libexif-devel \
libQt5Concurrent-devel \ libQt5Concurrent-devel \
libQt5Network-devel \ libQt5Network-devel \
libQt5OpenGL-devel \ libQt5OpenGL-devel \
@ -358,6 +361,7 @@ sudo apt-get install \
libavdevice-ffmpeg-dev \ libavdevice-ffmpeg-dev \
libavfilter-ffmpeg-dev \ libavfilter-ffmpeg-dev \
libavutil-ffmpeg-dev \ libavutil-ffmpeg-dev \
libexif-dev \
libgdk-pixbuf2.0-dev \ libgdk-pixbuf2.0-dev \
libglib2.0-dev \ libglib2.0-dev \
libgtk2.0-dev \ libgtk2.0-dev \
@ -387,6 +391,7 @@ sudo apt-get install \
libavdevice-dev \ libavdevice-dev \
libavfilter-dev \ libavfilter-dev \
libavutil-dev \ libavutil-dev \
libexif-dev \
libgdk-pixbuf2.0-dev \ libgdk-pixbuf2.0-dev \
libglib2.0-dev \ libglib2.0-dev \
libgtk2.0-dev \ libgtk2.0-dev \

View File

@ -95,6 +95,7 @@ search_dependency(LIBAVCODEC PACKAGE libavcodec)
search_dependency(LIBAVDEVICE PACKAGE libavdevice) search_dependency(LIBAVDEVICE PACKAGE libavdevice)
search_dependency(LIBAVFORMAT PACKAGE libavformat) search_dependency(LIBAVFORMAT PACKAGE libavformat)
search_dependency(LIBAVUTIL PACKAGE libavutil) search_dependency(LIBAVUTIL PACKAGE libavutil)
search_dependency(LIBEXIF PACKAGE libexif)
search_dependency(LIBQRENCODE PACKAGE libqrencode) search_dependency(LIBQRENCODE PACKAGE libqrencode)
search_dependency(LIBSODIUM PACKAGE libsodium) search_dependency(LIBSODIUM PACKAGE libsodium)
search_dependency(LIBSWSCALE PACKAGE libswscale) search_dependency(LIBSWSCALE PACKAGE libswscale)

View File

@ -167,7 +167,7 @@ install() {
else else
brew install cmake brew install cmake
fi fi
brew install ffmpeg qrencode qt5 sqlcipher openal-soft brew install ffmpeg libexif qrencode qt5 sqlcipher openal-soft
fcho "Cloning filter_audio ... " fcho "Cloning filter_audio ... "
git clone --branch v0.0.1 --depth=1 https://github.com/irungentoo/filter_audio "$FILTERAUIO_DIR" git clone --branch v0.0.1 --depth=1 https://github.com/irungentoo/filter_audio "$FILTERAUIO_DIR"

View File

@ -157,6 +157,7 @@ win32 {
-lavformat \ -lavformat \
-lavcodec \ -lavcodec \
-lavutil \ -lavutil \
-lexif \
-lswscale \ -lswscale \
-lOpenAL32 \ -lOpenAL32 \
-lopus \ -lopus \
@ -214,6 +215,7 @@ win32 {
-lavdevice \ -lavdevice \
-lavcodec \ -lavcodec \
-lavutil \ -lavutil \
-lexif \
-lswscale \ -lswscale \
-lz \ -lz \
-ljpeg \ -ljpeg \
@ -250,6 +252,7 @@ win32 {
-lavdevice \ -lavdevice \
-lavcodec \ -lavcodec \
-lavutil \ -lavutil \
-lexif \
-lswscale \ -lswscale \
-lqrencode \ -lqrencode \
-lsqlcipher \ -lsqlcipher \

View File

@ -27,6 +27,8 @@
#include "src/widget/style.h" #include "src/widget/style.h"
#include "src/widget/widget.h" #include "src/widget/widget.h"
#include <libexif/exif-loader.h>
#include <QBuffer> #include <QBuffer>
#include <QDebug> #include <QDebug>
#include <QDesktopServices> #include <QDesktopServices>
@ -528,7 +530,18 @@ void FileTransferWidget::showPreview(const QString& filename)
// Subtract to make border visible // Subtract to make border visible
const int size = qMax(ui->previewButton->width(), ui->previewButton->height()) - 4; const int size = qMax(ui->previewButton->width(), ui->previewButton->height()) - 4;
const QImage image = QImage(filename); QFile imageFile(filename);
if (!imageFile.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file for preview";
return;
}
const QByteArray imageFileData = imageFile.readAll();
QImage image = QImage::fromData(imageFileData);
const int exifOrientation = getExifOrientation(imageFileData.constData(), imageFileData.size());
if (exifOrientation) {
applyTransformation(exifOrientation, image);
}
const QPixmap iconPixmap = scaleCropIntoSquare(QPixmap::fromImage(image), size); const QPixmap iconPixmap = scaleCropIntoSquare(QPixmap::fromImage(image), size);
ui->previewButton->setIcon(QIcon(iconPixmap)); ui->previewButton->setIcon(QIcon(iconPixmap));
@ -585,3 +598,56 @@ QPixmap FileTransferWidget::scaleCropIntoSquare(const QPixmap& source, const int
// Picture was rectangle in the first place, no cropping // Picture was rectangle in the first place, no cropping
return result; return result;
} }
int FileTransferWidget::getExifOrientation(const char* data, const int size)
{
ExifData* exifData = exif_data_new_from_data(reinterpret_cast<const unsigned char*>(data), size);
if (!exifData)
return 0;
int orientation = 0;
const ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
const ExifEntry* const exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION);
if (exifEntry) {
orientation = exif_get_short(exifEntry->data, byteOrder);
}
exif_data_free(exifData);
return orientation;
}
void FileTransferWidget::applyTransformation(const int orientation, QImage& image)
{
QTransform exifTransform;
switch(static_cast<ExifOrientation>(orientation))
{
case ExifOrientation::TopLeft:
break;
case ExifOrientation::TopRight:
image = image.mirrored(1,0);
break;
case ExifOrientation::BottomRight:
exifTransform.rotate(180);
break;
case ExifOrientation::BottomLeft:
image = image.mirrored(0, 1);
break;
case ExifOrientation::LeftTop:
exifTransform.rotate(90);
image = image.mirrored(0, 1);
break;
case ExifOrientation::RightTop:
exifTransform.rotate(-90);
break;
case ExifOrientation::RightBottom:
exifTransform.rotate(-90);
image = image.mirrored(0, 1);
break;
case ExifOrientation::LeftBottom:
exifTransform.rotate(90);
break;
default:
qWarning() << "Invalid exif orientation passed to applyTransformation!";
}
image = image.transformed(exifTransform);
}

View File

@ -75,6 +75,8 @@ private slots:
private: private:
static QPixmap scaleCropIntoSquare(const QPixmap& source, int targetSize); static QPixmap scaleCropIntoSquare(const QPixmap& source, int targetSize);
static int getExifOrientation(const char* data, const int size);
static void applyTransformation(const int oritentation, QImage& image);
private: private:
Ui::FileTransferWidget* ui; Ui::FileTransferWidget* ui;
@ -92,6 +94,22 @@ private:
qreal meanData[TRANSFER_ROLLING_AVG_COUNT] = {0.0}; qreal meanData[TRANSFER_ROLLING_AVG_COUNT] = {0.0};
bool active; bool active;
enum class ExifOrientation {
/* do not change values, this is exif spec
*
* name corresponds to where the 0 row and 0 column is in form row-column
* i.e. entry 5 here means that the 0'th row corresponds to the left side of the scene and the 0'th column corresponds
* to the top of the captured scene. This means that the image needs to be mirrored and rotated to be displayed.
*/
TopLeft = 1,
TopRight = 2,
BottomRight = 3,
BottomLeft = 4,
LeftTop = 5,
RightTop = 6,
RightBottom = 7,
LeftBottom = 8
};
}; };
#endif // FILETRANSFERWIDGET_H #endif // FILETRANSFERWIDGET_H