Merge lp:~fboucault/gallery-app/fix_exif_orientation into lp:gallery-app

Proposed by Florian Boucault
Status: Rejected
Rejected by: Florian Boucault
Proposed branch: lp:~fboucault/gallery-app/fix_exif_orientation
Merge into: lp:gallery-app
Diff against target: 644 lines (+58/-504)
4 files modified
src/gallery-application.cpp (+0/-1)
src/photoeditor/photo-image-provider.cpp (+48/-409)
src/photoeditor/photo-image-provider.h (+9/-93)
src/photoeditor/photo-metadata.cpp (+1/-1)
To merge this branch: bzr merge lp:~fboucault/gallery-app/fix_exif_orientation
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Arthur Mello (community) Approve
Review via email: mp+261530@code.launchpad.net

Commit message

When rotating pictures during edit, write the EXIF orientation tag with the right type (unsigned short) instead of signed long.
PhotoImageProvider: change its behaviour to only rectify the EXIF orientation tag type when necessary (removes all other behaviours: caching, etc.)

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Arthur Mello (artmello) wrote :

LGTM

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

1202. By Florian Boucault

Merged with trunk

1201. By Florian Boucault

Merged with trunk

1200. By Florian Boucault

Fix writing of orientation. Should be an unsigned short instead of a long.

1199. By Florian Boucault

When rotating pictures during edit, write the EXIF orientation tag with the right type (unsigned short) instead of signed long.
PhotoImageProvider: change its behaviour to only rectify the EXIF orientation tag type when necessary.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/gallery-application.cpp'
2--- src/gallery-application.cpp 2015-12-16 12:49:12 +0000
3+++ src/gallery-application.cpp 2016-01-13 19:01:54 +0000
4@@ -220,7 +220,6 @@
5 m_view->setTitle("Gallery");
6
7 PhotoImageProvider* provider = new PhotoImageProvider();
8- provider->setLogging(true);
9 m_view->engine()->addImageProvider(PhotoImageProvider::PROVIDER_ID,
10 provider);
11
12
13=== modified file 'src/photoeditor/photo-image-provider.cpp'
14--- src/photoeditor/photo-image-provider.cpp 2015-11-23 17:42:29 +0000
15+++ src/photoeditor/photo-image-provider.cpp 2016-01-13 19:01:54 +0000
16@@ -1,5 +1,5 @@
17 /*
18- * Copyright (C) 2011-2014 Canonical Ltd
19+ * Copyright (C) 2015 Canonical Ltd
20 *
21 * This program is free software: you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 3 as
23@@ -14,430 +14,69 @@
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 *
26 * Authors:
27- * Lucas Beeler <lucas@yorba.org>
28- * Jim Nelson <jim@yorba.org>
29- * Ugo Riboni <ugo.riboni@canonical.com>
30+ * Florian Boucault <florian.boucault@canonical.com>
31 */
32
33 #include "photo-image-provider.h"
34-#include "photo-metadata.h"
35
36-#include <QDebug>
37-#include <QElapsedTimer>
38-#include <QImageReader>
39-#include <QSize>
40-#include <QUrlQuery>
41+#include <QtCore/QFileInfo>
42+#include <QtGui/QImageReader>
43+#include <exiv2/exiv2.hpp>
44
45 const char* PhotoImageProvider::PROVIDER_ID = "photo";
46-const char* PhotoImageProvider::PROVIDER_ID_SCHEME = "image://photo/";
47-
48-const long MAX_CACHE_BYTES = 20L * 1024L * 1024L;
49-
50-/*!
51- * \brief PhotoImageProvider::PhotoImageProvider
52- */
53+const char* EXIF_ORIENTATION_KEY = "Exif.Image.Orientation";
54+
55 PhotoImageProvider::PhotoImageProvider()
56- : QQuickImageProvider(QQuickImageProvider::Image),
57- m_cachedBytes(0),
58- m_logImageLoading(false),
59- m_emitCacheSignals(false)
60+ : QQuickImageProvider(QQuickImageProvider::Image)
61 {
62 }
63
64-/*!
65- * \brief PhotoImageProvider::~PhotoImageProvider
66- */
67 PhotoImageProvider::~PhotoImageProvider()
68 {
69- // NOTE: This assumes that we are not receiving requests any longer
70- while (!m_cachingOrder.isEmpty())
71- delete m_cache.value(m_cachingOrder.takeFirst());
72 }
73
74-#define LOG_IMAGE_STATUS(status) { \
75- if (m_logImageLoading) \
76- loggingStr += status; \
77- }
78-
79-/*!
80- * \brief PhotoImageProvider::requestImage
81- * \param id
82- * \param size
83- * \param requestedSize
84- * \return
85- */
86 QImage PhotoImageProvider::requestImage(const QString& id,
87- QSize* size, const QSize& requestedSize)
88+ QSize* size, const QSize& requestedSize)
89 {
90- // for LOG_IMAGE_STATUS
91- QString loggingStr = "";
92- QElapsedTimer timer;
93- if (m_logImageLoading) timer.start();
94-
95 QUrl url(id);
96-
97- QImage readyImage;
98- uint bytesLoaded = 0;
99-
100- CachedImage* cachedImage = claimCachedImageEntry(id, loggingStr);
101- Q_ASSERT(cachedImage != NULL);
102-
103- readyImage = fetchCachedImage(cachedImage, requestedSize, &bytesLoaded,
104- loggingStr);
105- if (readyImage.isNull())
106- LOG_IMAGE_STATUS("load-failure ");
107-
108- releaseCachedImageEntry(cachedImage, bytesLoaded);
109-
110- if (m_logImageLoading) {
111- if (bytesLoaded > 0) {
112- qDebug("%s %s req:%dx%d ret:%dx%d cache:%ldb/%d loaded:%db time:%lldms", qPrintable(loggingStr),
113- qPrintable(id), requestedSize.width(), requestedSize.height(), readyImage.width(),
114- readyImage.height(), m_cachedBytes, m_cache.size(), bytesLoaded,
115- timer.elapsed());
116- } else {
117- qDebug("%s %s req:%dx%d ret:%dx%d cache:%ldb/%d time:%lldms", qPrintable(loggingStr),
118- qPrintable(id), requestedSize.width(), requestedSize.height(), readyImage.width(),
119- readyImage.height(), m_cachedBytes, m_cache.size(), timer.elapsed());
120- }
121- }
122-
123- if (size != NULL)
124- *size = readyImage.size();
125-
126- return readyImage;
127-}
128-
129-/*!
130- * \brief PhotoImageProvider::setLogging enables to print photo loading
131- * times to stout
132- * \param enableLogging
133- */
134-void PhotoImageProvider::setLogging(bool enableLogging)
135-{
136- m_logImageLoading = enableLogging;
137-}
138-
139-/*!
140- * \brief PhotoImageProvider::setEmitCacheSignals enabled emitting signals to
141- * track the status of the internal cache.
142- * \param emitCacheSignals
143- */
144-void PhotoImageProvider::setEmitCacheSignals(bool emitCacheSignals)
145-{
146- m_emitCacheSignals = emitCacheSignals;
147-}
148-
149-/*!
150- * \brief PhotoImageProvider::claim_cached_image_entry
151- * Returns a CachedImage with an inUseCount > 0, meaning it cannot be
152- * removed from the cache until released
153- * \param id
154- * \param loggingStr
155- * \return
156- */
157-PhotoImageProvider::CachedImage* PhotoImageProvider::claimCachedImageEntry(
158- const QString& id, QString& loggingStr)
159-{
160- // lock the cache table and retrieve the element for the cached image; if
161- // not found, create one as a placeholder
162- m_cacheMutex.lock();
163-
164- CachedImage* cachedImage = m_cache.value(id, NULL);
165- if (cachedImage != NULL) {
166- // remove CachedImage before prepending to FIFO
167- m_cachingOrder.removeOne(id);
168- } else {
169- cachedImage = new CachedImage(id);
170- m_cache.insert(id, cachedImage);
171- LOG_IMAGE_STATUS("new-cache-entry ");
172- }
173-
174- // add to front of FIFO
175- m_cachingOrder.prepend(id);
176-
177- // should be the same size, always
178- Q_ASSERT(m_cache.size() == m_cachingOrder.size());
179-
180- // claim the CachedImage *while cacheMutex_ is locked* ... this prevents the
181- // CachedImage from being removed from the cache while its being filled
182- cachedImage->cleanCount++;
183-
184- m_cacheMutex.unlock();
185-
186- return cachedImage;
187-}
188-
189-/*!
190- * \brief PhotoImageProvider::fetch_cached_image Inspects and loads a proper image
191- * Inspects and loads a proper image for this request into the CachedImage
192- * \param cachedImage
193- * \param requestedSize
194- * \param bytesLoaded
195- * \param loggingStr
196- * \return
197- */
198-QImage PhotoImageProvider::fetchCachedImage(CachedImage *cachedImage,
199- const QSize& requestedSize,
200- uint* bytesLoaded,
201- QString& loggingStr)
202-{
203- Q_ASSERT(cachedImage != NULL);
204-
205- QString file = QUrl(cachedImage->id).path();
206-
207- // the final image returned to the user
208- QImage readyImage;
209- Q_ASSERT(readyImage.isNull());
210-
211- // lock the cached image itself to access
212- cachedImage->imageMutex.lock();
213-
214- // Depending on the file system used the last modified date of a file
215- // might have a really low resolution (2s for FAT32, 1s for ext3). Therefore
216- // we have to take the worse case and accept that there will be additional cache
217- // misses when an image is requested again just after it has been cached.
218- // There is no alternative to this other than accepting false cache hits, which
219- // would result in bugs in the application.
220- QFileInfo photoFile(file);
221- QDateTime fileLastModified = photoFile.lastModified();
222- fileLastModified = fileLastModified.addSecs(2);
223-
224- // if image is available, see if a fit
225- if (cachedImage->isCacheHit(requestedSize)) {
226- if (cachedImage->cachedAt > fileLastModified) {
227- readyImage = cachedImage->image;
228- LOG_IMAGE_STATUS("cache-hit ");
229- if (m_emitCacheSignals) Q_EMIT cacheHit(cachedImage->id, requestedSize);
230- } else {
231- // if the file was modified after the image was cached, reload it
232- LOG_IMAGE_STATUS("cache-stale ");
233- if (m_emitCacheSignals) cacheMiss(cachedImage->id, requestedSize, true);
234- }
235- } else {
236- LOG_IMAGE_STATUS("cache-miss ");
237- if (m_emitCacheSignals) cacheMiss(cachedImage->id, requestedSize, false);
238- }
239-
240- if (bytesLoaded != NULL)
241- *bytesLoaded = 0;
242-
243- // if unavailable or stale, load now
244- if (readyImage.isNull()) {
245- QImageReader reader(file);
246-
247- // load file's original size
248- QSize fullSize = reader.size();
249- QSize loadSize(fullSize);
250-
251- // use scaled load-and-decode if size has been requested
252- if (fullSize.isValid() && (requestedSize.width() > 0 || requestedSize.height() > 0)) {
253- loadSize.scale(requestedSize, Qt::KeepAspectRatio);
254- if (loadSize.width() > fullSize.width() || loadSize.height() > fullSize.height())
255- loadSize = fullSize;
256- }
257-
258- if (loadSize != fullSize) {
259- LOG_IMAGE_STATUS("scaled-load ");
260-
261- // configure reader for scaled load-and-decode
262- reader.setScaledSize(loadSize);
263- } else {
264- LOG_IMAGE_STATUS("full-load ");
265- }
266-
267- readyImage = reader.read();
268- if (!readyImage.isNull()) {
269- if (!fullSize.isValid())
270- fullSize = readyImage.size();
271-
272- Orientation orientation = TOP_LEFT_ORIGIN;
273- std::unique_ptr<PhotoMetadata> metadata(PhotoMetadata::fromFile(file));
274- if (metadata.get() != NULL)
275- orientation = metadata->orientation();
276-
277- // rotate image if not TOP LEFT
278- if (orientation != TOP_LEFT_ORIGIN) {
279- readyImage = readyImage.transformed(
280- OrientationCorrection::fromOrientation(orientation).toTransform());
281+ QString filePath = url.path();
282+
283+ QFileInfo fileInfo(filePath);
284+ QString original = fileInfo.path() + "/.original/" + fileInfo.fileName();
285+ if (QFileInfo::exists(original)) {
286+ Exiv2::Image::AutoPtr exivImage;
287+ try {
288+ exivImage = Exiv2::ImageFactory::open(filePath.toStdString());
289+ exivImage->readMetadata();
290+ Exiv2::ExifData& exifData = exivImage->exifData();
291+ if (exifData[EXIF_ORIENTATION_KEY].typeId() == Exiv2::signedLong) {
292+ exifData[EXIF_ORIENTATION_KEY] = (Exiv2::UShortValue)exifData[EXIF_ORIENTATION_KEY].toLong();
293+ exivImage->writeMetadata();
294 }
295-
296- // If we are reloading an image, the cache total byte count will be the
297- // difference in size between the old image and the new one (could be negative, for
298- // example in cases of cropping).
299- // If we are not reloading, then the current count will be zero and the total byte
300- // count will be the full size of the newly loaded image.
301- int currentByteCount = readyImage.byteCount();
302-
303- cachedImage->storeImage(readyImage, fullSize, orientation);
304- if (m_emitCacheSignals) Q_EMIT cacheAdd(cachedImage->id, requestedSize, loadSize);
305-
306- if (bytesLoaded != NULL)
307- *bytesLoaded = readyImage.byteCount() - currentByteCount;
308- } else {
309- qDebug("Unable to load %s: %s", qPrintable(cachedImage->id),
310- qPrintable(reader.errorString()));
311- }
312- } else {
313- // if the image comes from the cache and the requested size is smaller
314- // than what we cached, scale the image before returning it
315- if (requestedSize.isValid()) {
316- readyImage = readyImage.scaled(requestedSize, Qt::KeepAspectRatio);
317- }
318- }
319-
320- cachedImage->imageMutex.unlock();
321-
322- return readyImage;
323-}
324-
325-/*!
326- * \brief PhotoImageProvider::release_cached_image_entry
327- * Releases a CachedImage to the cache; takes its bytes loaded (0 if nothing
328- * was loaded) and returns the current cached byte total
329- * \param cachedImage
330- * \param bytesLoaded
331- * \param currentCacheEntries
332- */
333-void PhotoImageProvider::releaseCachedImageEntry
334-(CachedImage *cachedImage, uint bytesLoaded)
335-{
336- Q_ASSERT(cachedImage != NULL);
337-
338- // update total cached bytes and remove excess bytes
339- m_cacheMutex.lock();
340-
341- m_cachedBytes += bytesLoaded;
342-
343- // update the CachedImage use count and byte count inside of *cachedMutex_ lock*
344- Q_ASSERT(cachedImage->cleanCount > 0);
345- cachedImage->cleanCount--;
346- if (bytesLoaded != 0)
347- cachedImage->byteCount = bytesLoaded;
348-
349- // trim the cache
350- QList<CachedImage*> dropList;
351- while (m_cachedBytes > MAX_CACHE_BYTES && !m_cachingOrder.isEmpty()) {
352- QString droppedFile = m_cachingOrder.takeLast();
353-
354- CachedImage* droppedCachedImage = m_cache.value(droppedFile);
355- Q_ASSERT(droppedCachedImage != NULL);
356-
357- // for simplicity, stop when dropped item is in use or doesn't contain
358- // an image (which it won't for too long) ... will clean up next time
359- // through
360- if (droppedCachedImage->cleanCount > 0) {
361- m_cachingOrder.append(droppedFile);
362-
363- break;
364- }
365-
366- // remove from map
367- m_cache.remove(droppedFile);
368-
369- // decrement total cached size
370- m_cachedBytes -= droppedCachedImage->byteCount;
371- Q_ASSERT(m_cachedBytes >= 0);
372-
373- dropList.append(droppedCachedImage);
374- }
375-
376- // coherency is good
377- Q_ASSERT(m_cache.size() == m_cachingOrder.size());
378-
379- m_cacheMutex.unlock();
380-
381- // perform actual deletion outside of lock
382- while (!dropList.isEmpty())
383- delete dropList.takeFirst();
384-}
385-
386-/*!
387- * \brief PhotoImageProvider::orientSize
388- * \param size
389- * \param orientation
390- * \return
391- */
392-QSize PhotoImageProvider::orientSize(const QSize& size, Orientation orientation)
393-{
394- switch (orientation) {
395- case LEFT_TOP_ORIGIN:
396- case RIGHT_TOP_ORIGIN:
397- case RIGHT_BOTTOM_ORIGIN:
398- case LEFT_BOTTOM_ORIGIN:
399- return QSize(size.height(), size.width());
400- break;
401-
402- default:
403- // no change
404- return size;
405- }
406-}
407-
408-/*!
409- * \brief PhotoImageProvider::CachedImage::CachedImage
410- * \param id the full URI of the image
411- * \param fileName the filename for the URI (the file itself)
412- */
413-PhotoImageProvider::CachedImage::CachedImage(const QString& id)
414- : id(id), orientation(TOP_LEFT_ORIGIN), cleanCount(0), byteCount(0)
415-{
416-}
417-
418-/*!
419- * \brief PhotoImageProvider::CachedImage::storeImage
420- * Importand: the following should only be called when imageMutex_ is locked
421- * \param image
422- * \param fullSize
423- * \param orientation
424- */
425-void PhotoImageProvider::CachedImage::storeImage(const QImage& newImage,
426- const QSize& newFullSize,
427- Orientation newOrientation)
428-{
429- image = newImage;
430- fullSize = orientSize(newFullSize, orientation);
431- orientation = newOrientation;
432- cachedAt = QDateTime::currentDateTime();
433-}
434-
435-/*!
436- * \brief PhotoImageProvider::CachedImage::isReady
437- * \return
438- */
439-bool PhotoImageProvider::CachedImage::isReady() const
440-{
441- return !image.isNull();
442-}
443-
444-/*!
445- * \brief PhotoImageProvider::CachedImage::isFullSized
446- * \return
447- */
448-bool PhotoImageProvider::CachedImage::isFullSized() const
449-{
450- return isReady() && (image.size() == fullSize);
451-}
452-
453-/*!
454- * \brief PhotoImageProvider::CachedImage::isCacheHit
455- * \param requestedSize
456- * \return
457- */
458-bool PhotoImageProvider::CachedImage::isCacheHit(const QSize& requestedSize) const
459-{
460- if (!isReady())
461- return false;
462-
463- if (isFullSized())
464- return true;
465-
466- QSize properRequestedSize = orientSize(requestedSize, orientation);
467-
468- if ((properRequestedSize.width() != 0 && image.width() >= properRequestedSize.width())
469- || (properRequestedSize.height() != 0 && image.height() >= properRequestedSize.height())) {
470- return true;
471- }
472-
473- return false;
474+ } catch (Exiv2::AnyError& e) {
475+ }
476+ }
477+
478+ QImageReader reader(filePath);
479+ QSize fullSize = reader.size();
480+ QSize loadSize(fullSize);
481+
482+ if (fullSize.isValid() && (requestedSize.width() > 0 || requestedSize.height() > 0)) {
483+ loadSize.scale(requestedSize, Qt::KeepAspectRatio);
484+ if (loadSize.width() > fullSize.width() || loadSize.height() > fullSize.height()) {
485+ loadSize = fullSize;
486+ }
487+ }
488+
489+ if (loadSize != fullSize) {
490+ reader.setScaledSize(loadSize);
491+ }
492+
493+ QImage image = reader.read();
494+
495+ if (size != NULL) {
496+ *size = image.size();
497+ }
498+
499+ return image;
500 }
501
502=== modified file 'src/photoeditor/photo-image-provider.h'
503--- src/photoeditor/photo-image-provider.h 2015-02-26 20:28:06 +0000
504+++ src/photoeditor/photo-image-provider.h 2016-01-13 19:01:54 +0000
505@@ -1,5 +1,5 @@
506 /*
507- * Copyright (C) 2011-2014 Canonical Ltd
508+ * Copyright (C) 2015 Canonical Ltd
509 *
510 * This program is free software: you can redistribute it and/or modify
511 * it under the terms of the GNU General Public License version 3 as
512@@ -14,111 +14,27 @@
513 * along with this program. If not, see <http://www.gnu.org/licenses/>.
514 *
515 * Authors:
516- * Lucas Beeler <lucas@yorba.org>
517- * Jim Nelson <jim@yorba.org>
518- * Ugo Riboni <ugo.riboni@canonical.com>
519-*/
520+ * Florian Boucault <florian.boucault@canonical.com>
521+ */
522
523 #ifndef PHOTO_IMAGE_PROVIDER_H_
524 #define PHOTO_IMAGE_PROVIDER_H_
525
526-// util
527-#include "orientation.h"
528-
529-#include <QDateTime>
530-#include <QFileInfo>
531-#include <QImage>
532-#include <QMap>
533-#include <QMutex>
534-#include <QObject>
535-#include <QQuickImageProvider>
536-#include <QSize>
537-#include <QString>
538-#include <QUrl>
539-
540-/*!
541- * We use a custom image provider for the following reasons:
542- *
543- * 1. QML's image loader does not respect EXIF orientation. This provider will
544- * rotate and mirror the image as necessary.
545- *
546- * 2. QML's image caching appears to be directly related to image size (scaling)
547- * which leads to thrashing when animating a thumbnail or loading images at
548- * various sizes.
549- * The strategy here is to cache the largest requested size of the image
550- * and downscale it if smaller versions are requested. This minimizes
551- * expensive JPEG load-and-decodes.
552- *
553- * 3. Logging allows for monitoring of all image I/O, useful when debugging and
554- * optimizing, and signals can be emitted to monitor and test cache operation.
555- *
556- * 4. The QML cache does not check if a file has been modified on disk after it
557- * was cached, but our cache does. You should always set Image.cache to false
558- * when loading images from this provider in QML.
559- */
560-class PhotoImageProvider : public QObject, public QQuickImageProvider
561+#include <QtQuick/QQuickImageProvider>
562+#include <QtGui/QImage>
563+#include <QtCore/QString>
564+#include <QtCore/QSize>
565+
566+class PhotoImageProvider : public QQuickImageProvider
567 {
568- Q_OBJECT
569-
570 public:
571 static const char* PROVIDER_ID;
572- static const char* PROVIDER_ID_SCHEME;
573
574 PhotoImageProvider();
575 virtual ~PhotoImageProvider();
576
577 virtual QImage requestImage(const QString& id, QSize* size,
578 const QSize& requestedSize);
579-
580- void setLogging(bool enableLogging);
581- void setEmitCacheSignals(bool emitCacheSignals);
582-
583-Q_SIGNALS:
584- void cacheHit(QString id, QSize size);
585- void cacheMiss(QString id, QSize size, bool wasStale);
586- void cacheAdd(QString id, QSize size, QSize cachedSize);
587-
588-private:
589- class CachedImage {
590- public:
591- const QString id;
592- QMutex imageMutex;
593-
594- // these fields should only be accessed when imageMutex_ is locked
595- QImage image;
596- QSize fullSize;
597- Orientation orientation;
598- QDateTime cachedAt;
599-
600- // the following should only be accessed when cacheMutex_ is locked; the
601- // counter controls removing a CachedImage entry from the cache table
602- int cleanCount;
603- uint byteCount;
604-
605- CachedImage(const QString& id);
606-
607- void storeImage(const QImage& newImage, const QSize& newFullSize,
608- Orientation newOrientation);
609- bool isFullSized() const;
610- bool isReady() const;
611- bool isCacheHit(const QSize& requestedSize) const;
612- };
613-
614- QMap<QString, CachedImage*> m_cache;
615- QList<QString> m_cachingOrder;
616- QMutex m_cacheMutex;
617- long m_cachedBytes;
618- bool m_logImageLoading;
619- bool m_emitCacheSignals;
620-
621- static QSize orientSize(const QSize& size, Orientation orientation);
622-
623- CachedImage* claimCachedImageEntry(const QString& id, QString& loggingStr);
624-
625- QImage fetchCachedImage(CachedImage* cachedImage, const QSize& requestedSize,
626- uint* bytesLoaded, QString& loggingStr);
627-
628- void releaseCachedImageEntry(CachedImage* cachedImage, uint bytesLoaded);
629 };
630
631 #endif // PHOTO_IMAGE_PROVIDER_H_
632
633=== modified file 'src/photoeditor/photo-metadata.cpp'
634--- src/photoeditor/photo-metadata.cpp 2015-05-06 20:15:54 +0000
635+++ src/photoeditor/photo-metadata.cpp 2016-01-13 19:01:54 +0000
636@@ -219,7 +219,7 @@
637 {
638 Exiv2::ExifData& exif_data = m_image->exifData();
639
640- exif_data[EXIF_ORIENTATION_KEY] = orientation;
641+ exif_data[EXIF_ORIENTATION_KEY] = (Exiv2::UShortValue)orientation;
642
643 if (!m_keysPresent.contains(EXIF_ORIENTATION_KEY))
644 m_keysPresent.insert(EXIF_ORIENTATION_KEY);

Subscribers

People subscribed via source and target branches