Dive pictures: Scale thumbnails on demand

To potentially conserve memory, don't keep copies of scaled thumbnails.
Scale the thumbnails on demand.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2018-04-11 06:56:46 +02:00 committed by Dirk Hohndel
parent 6b4e830670
commit c0bca3ad04
2 changed files with 19 additions and 14 deletions

View file

@ -17,7 +17,7 @@ static QImage getThumbnailFromCache(const PictureEntry &entry)
return thumbnailCache.value(entry.filename); return thumbnailCache.value(entry.filename);
} }
static void scaleImages(PictureEntry &entry, int size, int maxSize) static void scaleImages(PictureEntry &entry, int maxSize)
{ {
QImage thumbnail = getThumbnailFromCache(entry); QImage thumbnail = getThumbnailFromCache(entry);
// If thumbnails were written by an earlier version, they might be smaller than needed. // If thumbnails were written by an earlier version, they might be smaller than needed.
@ -29,9 +29,7 @@ static void scaleImages(PictureEntry &entry, int size, int maxSize)
thumbnailCache.insert(entry.filename, thumbnail); thumbnailCache.insert(entry.filename, thumbnail);
} }
entry.imageProfile = thumbnail.scaled(maxSize / maxZoom, maxSize / maxZoom, Qt::KeepAspectRatio); entry.image = thumbnail;
entry.image = size == maxSize ? thumbnail
: thumbnail.scaled(size, size, Qt::KeepAspectRatio);
} }
DivePictureModel *DivePictureModel::instance() DivePictureModel *DivePictureModel::instance()
@ -42,7 +40,8 @@ DivePictureModel *DivePictureModel::instance()
DivePictureModel::DivePictureModel() : rowDDStart(0), DivePictureModel::DivePictureModel() : rowDDStart(0),
rowDDEnd(0), rowDDEnd(0),
zoomLevel(0.0) zoomLevel(0.0),
defaultSize(defaultIconMetrics().sz_pic)
{ {
} }
@ -62,11 +61,11 @@ void DivePictureModel::setZoomLevel(int level)
zoomLevel = -1.0; zoomLevel = -1.0;
if (zoomLevel > 1.0) if (zoomLevel > 1.0)
zoomLevel = 1.0; zoomLevel = 1.0;
updateThumbnails(); updateZoom();
layoutChanged(); layoutChanged();
} }
void DivePictureModel::updateThumbnails() void DivePictureModel::updateZoom()
{ {
// Calculate size of thumbnails. The standard size is defaultIconMetrics().sz_pic. // Calculate size of thumbnails. The standard size is defaultIconMetrics().sz_pic.
// We use exponential scaling so that the central point is the standard // We use exponential scaling so that the central point is the standard
@ -75,10 +74,14 @@ void DivePictureModel::updateThumbnails()
// Naturally, these three zoom levels are then represented by // Naturally, these three zoom levels are then represented by
// -1.0 (minimum), 0 (standard) and 1.0 (maximum). The actual size is // -1.0 (minimum), 0 (standard) and 1.0 (maximum). The actual size is
// calculated as standard_size*3.0^zoomLevel. // calculated as standard_size*3.0^zoomLevel.
int defaultSize = defaultIconMetrics().sz_pic; size = static_cast<int>(round(defaultSize * pow(maxZoom, zoomLevel)));
}
void DivePictureModel::updateThumbnails()
{
int maxSize = defaultSize * maxZoom; int maxSize = defaultSize * maxZoom;
int size = static_cast<int>(round(defaultSize * pow(maxZoom, zoomLevel))); updateZoom();
QtConcurrent::blockingMap(pictures, [size, maxSize](PictureEntry &entry){scaleImages(entry, size, maxSize);}); QtConcurrent::blockingMap(pictures, [maxSize](PictureEntry &entry){scaleImages(entry, maxSize);});
} }
void DivePictureModel::updateDivePictures() void DivePictureModel::updateDivePictures()
@ -101,7 +104,7 @@ void DivePictureModel::updateDivePictures()
if (dive->id == displayed_dive.id) if (dive->id == displayed_dive.id)
rowDDStart = pictures.count(); rowDDStart = pictures.count();
FOR_EACH_PICTURE(dive) FOR_EACH_PICTURE(dive)
pictures.push_back({picture, picture->filename, {}, {}, picture->offset.seconds}); pictures.push_back({picture, picture->filename, {}, picture->offset.seconds});
if (dive->id == displayed_dive.id) if (dive->id == displayed_dive.id)
rowDDEnd = pictures.count(); rowDDEnd = pictures.count();
} }
@ -134,10 +137,10 @@ QVariant DivePictureModel::data(const QModelIndex &index, int role) const
ret = entry.filename; ret = entry.filename;
break; break;
case Qt::DecorationRole: case Qt::DecorationRole:
ret = entry.image; ret = entry.image.scaled(size, size, Qt::KeepAspectRatio);
break; break;
case Qt::UserRole: // Used by profile widget to access bigger thumbnails case Qt::UserRole: // Used by profile widget to access bigger thumbnails
ret = entry.imageProfile; ret = entry.image.scaled(defaultSize, defaultSize, Qt::KeepAspectRatio);
break; break;
case Qt::DisplayRole: case Qt::DisplayRole:
ret = QFileInfo(entry.filename).fileName(); ret = QFileInfo(entry.filename).fileName();

View file

@ -10,7 +10,6 @@ struct PictureEntry {
struct picture *picture; struct picture *picture;
QString filename; QString filename;
QImage image; QImage image;
QImage imageProfile; // For the profile widget keep a copy of a constant sized image
int offsetSeconds; int offsetSeconds;
}; };
@ -31,7 +30,10 @@ private:
DivePictureModel(); DivePictureModel();
QList<PictureEntry> pictures; QList<PictureEntry> pictures;
double zoomLevel; // -1.0: minimum, 0.0: standard, 1.0: maximum double zoomLevel; // -1.0: minimum, 0.0: standard, 1.0: maximum
int defaultSize;
int size;
void updateThumbnails(); void updateThumbnails();
void updateZoom();
}; };
#endif #endif