- Change display options to be passed down from the window, and have the imageselector pass a struct back that contains image metadata

- Added ImageDisplayOptions_t to control user controllable options for how we show an image (aspect filtering, stretching)
- Added ImageDetails_t to encapsulate image metadata along with its image options
This commit is contained in:
Alfred Reynolds
2021-08-03 14:14:11 +12:00
parent e09c4d4f9f
commit 096a68636c
9 changed files with 225 additions and 161 deletions

View File

@@ -12,26 +12,54 @@
#include <algorithm> // std::shuffle #include <algorithm> // std::shuffle
#include <random> // std::default_random_engine #include <random> // std::default_random_engine
ImageSelector::ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspectIn, bool fitAspectAxisToWindowIn): ImageSelector::ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
pathTraverser(pathTraverser), aspect(aspectIn), fitAspectAxisToWindow(fitAspectAxisToWindowIn) pathTraverser(pathTraverser)
{ {
} }
ImageSelector::~ImageSelector(){} ImageSelector::~ImageSelector(){}
int ImageSelector::getImageRotation(const std::string& fileName) int ReadExifTag(ExifData* exifData, ExifTag tag, bool shortRead = false)
{ {
int orientation = 0; int value = -1;
ExifData *exifData = exif_data_new_from_file(fileName.c_str());
if (exifData)
{
ExifByteOrder byteOrder = exif_data_get_byte_order(exifData); ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
ExifEntry *exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION); ExifEntry *exifEntry = exif_data_get_entry(exifData, tag);
if (exifEntry) if (exifEntry)
{ {
orientation = exif_get_short(exifEntry->data, byteOrder); if (shortRead)
{
value = exif_get_short(exifEntry->data, byteOrder);
} }
else
{
value = exif_get_long(exifEntry->data, byteOrder);
}
}
return value;
}
void ImageSelector::populateImageDetails(const std::string&fileName, ImageDetails_t &imageDetails, const ImageDisplayOptions_t &baseOptions)
{
int orientation = -1;
int imageWidth = -1;
int imageHeight = -1;
ExifData *exifData = exif_data_new_from_file(fileName.c_str());
if (exifData)
{
orientation = ReadExifTag(exifData, EXIF_TAG_ORIENTATION, true);
/*
// It looks like you can't trust Exif dimensions, so just forcefully load the file below
// try to get the image dimensions from exifData so we don't need to fully load the file
imageWidth = ReadExifTag(exifData, EXIF_TAG_IMAGE_WIDTH);
if ( imageWidth == -1)
imageWidth = ReadExifTag(exifData, EXIF_TAG_PIXEL_X_DIMENSION);
imageHeight = ReadExifTag(exifData, EXIF_TAG_RELATED_IMAGE_WIDTH); // means height, height is related to width
if ( imageHeight == -1)
imageHeight = ReadExifTag(exifData, EXIF_TAG_PIXEL_Y_DIMENSION);*/
exif_data_free(exifData); exif_data_free(exifData);
} }
@@ -46,97 +74,103 @@ int ImageSelector::getImageRotation(const std::string& fileName)
case 6: case 6:
degrees = 90; degrees = 90;
break; break;
default:
break;
} }
return degrees;
}
bool ImageSelector::imageMatchesFilter(const std::string& fileName, const int rotation) if (imageWidth <=0 || imageHeight <=0)
{
if(!QFileInfo::exists(QString(fileName.c_str())))
{ {
if(debugMode) // fallback to QPixmap to determine image size
{
std::cout << "file not found: " << fileName << std::endl;
}
return false;
}
if(!imageValidForAspect(fileName, rotation)) {
if(debugMode)
{
std::cout << "image aspect ratio doesn't match filter '" << aspect << "' : " << fileName << std::endl;
}
return false;
}
return true;
}
bool ImageSelector::imageValidForAspect(const std::string &fileName, const int rotation)
{
QPixmap p( fileName.c_str() ); QPixmap p( fileName.c_str() );
int imageWidth = p.width(); imageWidth = p.width();
int imageHeight = p.height(); imageHeight = p.height();
if ( rotation == 90 || rotation == 270 ) }
// if the image is rotated then swap height/width here to show displayed sizes
if( degrees == 90 || degrees == 270 )
{ {
std::swap(imageWidth,imageHeight); std::swap(imageWidth,imageHeight);
} }
switch(aspect) // setup the imageDetails structure
imageDetails.filename = fileName;
imageDetails.width = imageWidth;
imageDetails.height = imageHeight;
imageDetails.rotation = degrees;
if (imageWidth > imageHeight) {
imageDetails.aspect = EImageAspect_Landscape;
} else if (imageHeight > imageWidth) {
imageDetails.aspect = EImageAspect_Portrait;
} else {
imageDetails.aspect = EImageAspect_Any;
}
imageDetails.options = baseOptions;
}
bool ImageSelector::imageMatchesFilter(const ImageDetails_t& imageDetails)
{
if(!QFileInfo::exists(QString(imageDetails.filename.c_str())))
{ {
case 'a': if(debugMode)
// allow all
break;
case 'l':
if ( imageWidth < imageHeight )
{ {
std::cout << "file not found: " << imageDetails.filename << std::endl;
}
return false; return false;
} }
break;
case 'p': if(!imageValidForAspect(imageDetails))
if ( imageHeight < imageWidth )
{ {
if(debugMode)
{
std::cout << "image aspect ratio doesn't match filter '" << imageDetails.options.onlyAspect << "' : " << imageDetails.filename << std::endl;
}
return false; return false;
} }
break;
}
return true; return true;
} }
bool ImageSelector::imageValidForAspect(const ImageDetails_t& imageDetails)
{
if (imageDetails.options.onlyAspect == EImageAspect_Any ||
imageDetails.aspect == imageDetails.options.onlyAspect)
{
return true;
}
return false;
}
RandomImageSelector::RandomImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspect, bool fitAspectAxisToWindow):
ImageSelector(pathTraverser, aspect, fitAspectAxisToWindow) RandomImageSelector::RandomImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
ImageSelector(pathTraverser)
{ {
srand (time(NULL)); srand (time(NULL));
} }
RandomImageSelector::~RandomImageSelector(){} RandomImageSelector::~RandomImageSelector(){}
const std::string RandomImageSelector::getNextImage(ImageOptions_t &options) const ImageDetails_t RandomImageSelector::getNextImage(const ImageDisplayOptions_t &baseOptions)
{ {
std:: string filename; ImageDetails_t imageDetails;
try try
{ {
QStringList images = pathTraverser->getImages(); QStringList images = pathTraverser->getImages();
unsigned int selectedImage = selectRandom(images); unsigned int selectedImage = selectRandom(images);
filename = pathTraverser->getImagePath(images.at(selectedImage).toStdString()); populateImageDetails(pathTraverser->getImagePath(images.at(selectedImage).toStdString()), imageDetails, baseOptions);
options.rotation = getImageRotation(filename); while(!imageMatchesFilter(imageDetails))
while(!imageMatchesFilter(filename, options.rotation))
{ {
unsigned int selectedImage = selectRandom(images); unsigned int selectedImage = selectRandom(images);
filename = pathTraverser->getImagePath(images.at(selectedImage).toStdString()); populateImageDetails(pathTraverser->getImagePath(images.at(selectedImage).toStdString()), imageDetails, baseOptions);
options.rotation = getImageRotation(filename);
} }
} }
catch(const std::string& err) catch(const std::string& err)
{ {
std::cerr << "Error: " << err << std::endl; std::cerr << "Error: " << err << std::endl;
} }
std::cout << "updating image: " << filename << std::endl; std::cout << "updating image: " << imageDetails.filename << std::endl;
options.aspect = aspect; pathTraverser->UpdateOptionsForImage(imageDetails.filename, imageDetails.options);
options.fitAspectAxisToWindow = fitAspectAxisToWindow; return imageDetails;
pathTraverser->UpdateOptionsForImage(filename, options);
return filename;
} }
unsigned int RandomImageSelector::selectRandom(const QStringList& images) const unsigned int RandomImageSelector::selectRandom(const QStringList& images) const
@@ -152,8 +186,8 @@ unsigned int RandomImageSelector::selectRandom(const QStringList& images) const
return rand() % images.size(); return rand() % images.size();
} }
ShuffleImageSelector::ShuffleImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspect, bool fitAspectAxisToWindow): ShuffleImageSelector::ShuffleImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
ImageSelector(pathTraverser, aspect, fitAspectAxisToWindow), ImageSelector(pathTraverser),
current_image_shuffle(-1), current_image_shuffle(-1),
images() images()
{ {
@@ -164,27 +198,24 @@ ShuffleImageSelector::~ShuffleImageSelector()
{ {
} }
const std::string ShuffleImageSelector::getNextImage(ImageOptions_t &options) const ImageDetails_t ShuffleImageSelector::getNextImage(const ImageDisplayOptions_t &baseOptions)
{ {
reloadImagesIfNoneLeft(); reloadImagesIfNoneLeft();
ImageDetails_t imageDetails;
if (images.size() == 0) if (images.size() == 0)
{ {
return ""; return imageDetails;
} }
std::string filename = pathTraverser->getImagePath(images.at(current_image_shuffle).toStdString()); populateImageDetails(pathTraverser->getImagePath(images.at(current_image_shuffle).toStdString()), imageDetails, baseOptions);
current_image_shuffle = current_image_shuffle + 1; // ignore and move to next image current_image_shuffle = current_image_shuffle + 1; // ignore and move to next image
options.rotation = getImageRotation(filename); while(!imageMatchesFilter(imageDetails)) {
while(!imageMatchesFilter(filename, options.rotation)) {
reloadImagesIfNoneLeft(); reloadImagesIfNoneLeft();
std::string filename = pathTraverser->getImagePath(images.at(current_image_shuffle).toStdString()); populateImageDetails(pathTraverser->getImagePath(images.at(current_image_shuffle).toStdString()), imageDetails,baseOptions);
options.rotation = getImageRotation(filename);
current_image_shuffle = current_image_shuffle + 1; // ignore and move to next image current_image_shuffle = current_image_shuffle + 1; // ignore and move to next image
} }
std::cout << "updating image: " << filename << std::endl; std::cout << "updating image: " << imageDetails.filename << std::endl;
options.aspect = aspect; pathTraverser->UpdateOptionsForImage(imageDetails.filename, imageDetails.options);
options.fitAspectAxisToWindow = fitAspectAxisToWindow; return imageDetails;
pathTraverser->UpdateOptionsForImage(filename, options);
return filename;
} }
void ShuffleImageSelector::reloadImagesIfNoneLeft() void ShuffleImageSelector::reloadImagesIfNoneLeft()
@@ -200,8 +231,8 @@ void ShuffleImageSelector::reloadImagesIfNoneLeft()
} }
} }
SortedImageSelector::SortedImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspect, bool fitAspectAxisToWindow): SortedImageSelector::SortedImageSelector(std::unique_ptr<PathTraverser>& pathTraverser):
ImageSelector(pathTraverser, aspect, fitAspectAxisToWindow), ImageSelector(pathTraverser),
images() images()
{ {
srand (time(NULL)); srand (time(NULL));
@@ -223,26 +254,23 @@ bool operator<(const QString& lhs, const QString& rhs) noexcept{
} }
const std::string SortedImageSelector::getNextImage(ImageOptions_t &options) const ImageDetails_t SortedImageSelector::getNextImage(const ImageDisplayOptions_t &baseOptions)
{ {
reloadImagesIfEmpty(); reloadImagesIfEmpty();
ImageDetails_t imageDetails;
if (images.size() == 0) if (images.size() == 0)
{ {
return ""; return imageDetails;
} }
std::string filename = pathTraverser->getImagePath(images.takeFirst().toStdString()); populateImageDetails(pathTraverser->getImagePath(images.takeFirst().toStdString()), imageDetails, baseOptions);
options.rotation = getImageRotation(filename); while(!imageMatchesFilter(imageDetails)) {
while(!imageMatchesFilter(filename, options.rotation)) {
reloadImagesIfEmpty(); reloadImagesIfEmpty();
filename = pathTraverser->getImagePath(images.takeFirst().toStdString()); populateImageDetails(pathTraverser->getImagePath(images.takeFirst().toStdString()), imageDetails, baseOptions);
options.rotation = getImageRotation(filename);
} }
std::cout << "updating image: " << filename << std::endl; std::cout << "updating image: " << imageDetails.filename << std::endl;
options.aspect = aspect; pathTraverser->UpdateOptionsForImage(imageDetails.filename, imageDetails.options);
options.fitAspectAxisToWindow = fitAspectAxisToWindow; return imageDetails;
pathTraverser->UpdateOptionsForImage(filename, options);
return filename;
} }
void SortedImageSelector::reloadImagesIfEmpty() void SortedImageSelector::reloadImagesIfEmpty()

View File

@@ -4,41 +4,33 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <QStringList> #include <QStringList>
#include "imagestructs.h"
class MainWindow; class MainWindow;
class PathTraverser; class PathTraverser;
struct ImageOptions_t
{
char aspect;
bool fitAspectAxisToWindow;
int rotation;
};
class ImageSelector class ImageSelector
{ {
public: public:
ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspectIn, bool fitAspectAxisToWindow); ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser);
virtual ~ImageSelector(); virtual ~ImageSelector();
virtual const std::string getNextImage(ImageOptions_t &options) = 0; virtual const ImageDetails_t getNextImage(const ImageDisplayOptions_t &baseOptions) = 0;
void setDebugMode(bool debugModeIn) { debugMode = debugModeIn;} void setDebugMode(bool debugModeIn) { debugMode = debugModeIn;}
protected: protected:
int getImageRotation(const std::string &fileName); void populateImageDetails(const std::string&filename, ImageDetails_t &imageDetails, const ImageDisplayOptions_t &baseOptions);
bool imageValidForAspect(const std::string &fileName, const int rotation); bool imageValidForAspect(const ImageDetails_t& imageDetails);
bool imageMatchesFilter(const std::string& fileName, const int rotation); bool imageMatchesFilter(const ImageDetails_t& imageDetails);
std::unique_ptr<PathTraverser>& pathTraverser; std::unique_ptr<PathTraverser>& pathTraverser;
char aspect;
bool fitAspectAxisToWindow = false;
bool debugMode = false; bool debugMode = false;
}; };
class RandomImageSelector : public ImageSelector class RandomImageSelector : public ImageSelector
{ {
public: public:
RandomImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspect, bool fitAspectAxisToWindow); RandomImageSelector(std::unique_ptr<PathTraverser>& pathTraverser);
virtual ~RandomImageSelector(); virtual ~RandomImageSelector();
virtual const std::string getNextImage(ImageOptions_t &options); virtual const ImageDetails_t getNextImage(const ImageDisplayOptions_t &baseOptions);
private: private:
unsigned int selectRandom(const QStringList& images) const; unsigned int selectRandom(const QStringList& images) const;
@@ -47,9 +39,9 @@ private:
class ShuffleImageSelector : public ImageSelector class ShuffleImageSelector : public ImageSelector
{ {
public: public:
ShuffleImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspect, bool fitAspectAxisToWindow); ShuffleImageSelector(std::unique_ptr<PathTraverser>& pathTraverser);
virtual ~ShuffleImageSelector(); virtual ~ShuffleImageSelector();
virtual const std::string getNextImage(ImageOptions_t &options); virtual const ImageDetails_t getNextImage(const ImageDisplayOptions_t &baseOptions);
private: private:
void reloadImagesIfNoneLeft(); void reloadImagesIfNoneLeft();
@@ -60,9 +52,9 @@ private:
class SortedImageSelector : public ImageSelector class SortedImageSelector : public ImageSelector
{ {
public: public:
SortedImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspect, bool fitAspectAxisToWindow); SortedImageSelector(std::unique_ptr<PathTraverser>& pathTraverser);
virtual ~SortedImageSelector(); virtual ~SortedImageSelector();
virtual const std::string getNextImage(ImageOptions_t &options); virtual const ImageDetails_t getNextImage(const ImageDisplayOptions_t &baseOptions);
private: private:
void reloadImagesIfEmpty(); void reloadImagesIfEmpty();

28
src/imagestructs.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef IMAGESTRUCTS_H
#define IMAGESTRUCTS_H
#include <string>
// possible aspect ratios of an image
enum EImageAspect { EImageAspect_Landscape = 0, EImageAspect_Portrait, EImageAspect_Any };
// options to consider when displaying an image
struct ImageDisplayOptions_t
{
EImageAspect onlyAspect = EImageAspect_Any;
bool fitAspectAxisToWindow = false;
};
// details of a particular image
struct ImageDetails_t
{
int width = 0;
int height = 0;
int rotation = 0;
EImageAspect aspect = EImageAspect_Any;
std::string filename;
ImageDisplayOptions_t options;
};
#endif // IMAGESTRUCTS_H

View File

@@ -21,16 +21,15 @@ ImageSwitcher::ImageSwitcher(MainWindow& w, unsigned int timeout, std::unique_pt
void ImageSwitcher::updateImage() void ImageSwitcher::updateImage()
{ {
ImageOptions_t options; ImageDetails_t imageDetails = selector->getNextImage(window.getBaseOptions());
std::string filename(selector->getNextImage(options)); if (imageDetails.filename == "")
if (filename == "")
{ {
window.warn("No image found."); window.warn("No image found.");
timerNoContent.start(timeoutNoContent); timerNoContent.start(timeoutNoContent);
} }
else else
{ {
window.setImage(filename, options); window.setImage(imageDetails);
timerNoContent.stop(); // we have loaded content so stop the fast polling timerNoContent.stop(); // we have loaded content so stop the fast polling
} }
} }

View File

@@ -31,8 +31,7 @@ int main(int argc, char *argv[])
bool shuffle = false; bool shuffle = false;
bool sorted = false; bool sorted = false;
bool debugMode = false; bool debugMode = false;
char aspect = 'a'; ImageDisplayOptions_t baseDisplayOptions;
bool fitAspectAxisToWindow = false;
std::string valid_aspects = "alp"; // all, landscape, portait std::string valid_aspects = "alp"; // all, landscape, portait
std::string overlay = ""; std::string overlay = "";
std::string imageList = ""; // comma delimited list of images to show std::string imageList = ""; // comma delimited list of images to show
@@ -57,11 +56,26 @@ int main(int argc, char *argv[])
path = optarg; path = optarg;
break; break;
case 'a': case 'a':
aspect = optarg[0]; if ( valid_aspects.find(optarg[0]) == std::string::npos )
if ( valid_aspects.find(aspect) == std::string::npos )
{ {
std::cout << "Invalid Aspect option, defaulting to all" << std::endl; std::cout << "Invalid Aspect option, defaulting to all" << std::endl;
aspect = 'a'; baseDisplayOptions.onlyAspect = EImageAspect_Any;
}
else
{
switch(optarg[0])
{
case 'l':
baseDisplayOptions.onlyAspect = EImageAspect_Landscape;
break;
case 'p':
baseDisplayOptions.onlyAspect = EImageAspect_Portrait;
break;
default:
case 'a':
baseDisplayOptions.onlyAspect = EImageAspect_Any;
break;
}
} }
break; break;
case 't': case 't':
@@ -103,7 +117,7 @@ int main(int argc, char *argv[])
} }
if(stretchInt==1) if(stretchInt==1)
{ {
fitAspectAxisToWindow = true; baseDisplayOptions.fitAspectAxisToWindow = true;
} }
if (path.empty() && imageList.empty()) if (path.empty() && imageList.empty())
@@ -130,15 +144,15 @@ int main(int argc, char *argv[])
std::unique_ptr<ImageSelector> selector; std::unique_ptr<ImageSelector> selector;
if (sorted) if (sorted)
{ {
selector = std::unique_ptr<ImageSelector>(new SortedImageSelector(pathTraverser, aspect, fitAspectAxisToWindow)); selector = std::unique_ptr<ImageSelector>(new SortedImageSelector(pathTraverser));
} }
else if (shuffle) else if (shuffle)
{ {
selector = std::unique_ptr<ImageSelector>(new ShuffleImageSelector(pathTraverser, aspect, fitAspectAxisToWindow)); selector = std::unique_ptr<ImageSelector>(new ShuffleImageSelector(pathTraverser));
} }
else else
{ {
selector = std::unique_ptr<ImageSelector>(new RandomImageSelector(pathTraverser, aspect, fitAspectAxisToWindow)); selector = std::unique_ptr<ImageSelector>(new RandomImageSelector(pathTraverser));
} }
selector->setDebugMode(debugMode); selector->setDebugMode(debugMode);
if(debugMode) if(debugMode)
@@ -150,6 +164,7 @@ int main(int argc, char *argv[])
o.setDebugMode(debugMode); o.setDebugMode(debugMode);
w.setOverlay(&o); w.setOverlay(&o);
w.setDebugMode(debugMode); w.setDebugMode(debugMode);
w.setBaseOptions(baseDisplayOptions);
w.show(); w.show();
ImageSwitcher switcher(w, rotationSeconds * 1000, selector); ImageSwitcher switcher(w, rotationSeconds * 1000, selector);

View File

@@ -108,16 +108,15 @@ void MainWindow::resizeEvent(QResizeEvent* event)
updateImage(true); updateImage(true);
} }
void MainWindow::setImage(const std::string& path, const ImageOptions_t& options) void MainWindow::setImage(const ImageDetails_t &imageDetails)
{ {
currentImage = path; currentImage = imageDetails;
imageOptions = options;
updateImage(false); updateImage(false);
} }
void MainWindow::updateImage(bool immediately) void MainWindow::updateImage(bool immediately)
{ {
if (currentImage == "") if (currentImage.filename == "")
return; return;
QLabel *label = this->findChild<QLabel*>("image"); QLabel *label = this->findChild<QLabel*>("image");
@@ -129,7 +128,7 @@ void MainWindow::updateImage(bool immediately)
this->setPalette(palette); this->setPalette(palette);
} }
QPixmap p( currentImage.c_str() ); QPixmap p( currentImage.filename.c_str() );
if(debugMode) if(debugMode)
{ {
std::cout << "size:" << p.width() << "x" << p.height() << std::endl; std::cout << "size:" << p.width() << "x" << p.height() << std::endl;
@@ -142,10 +141,10 @@ void MainWindow::updateImage(bool immediately)
if (overlay != NULL) if (overlay != NULL)
{ {
drawText(background, overlay->getMarginTopLeft(), overlay->getFontsizeTopLeft(), overlay->getRenderedTopLeft(currentImage).c_str(), Qt::AlignTop|Qt::AlignLeft); drawText(background, overlay->getMarginTopLeft(), overlay->getFontsizeTopLeft(), overlay->getRenderedTopLeft(currentImage.filename).c_str(), Qt::AlignTop|Qt::AlignLeft);
drawText(background, overlay->getMarginTopRight(), overlay->getFontsizeTopRight(), overlay->getRenderedTopRight(currentImage).c_str(), Qt::AlignTop|Qt::AlignRight); drawText(background, overlay->getMarginTopRight(), overlay->getFontsizeTopRight(), overlay->getRenderedTopRight(currentImage.filename).c_str(), Qt::AlignTop|Qt::AlignRight);
drawText(background, overlay->getMarginBottomLeft(), overlay->getFontsizeBottomLeft(), overlay->getRenderedBottomLeft(currentImage).c_str(), Qt::AlignBottom|Qt::AlignLeft); drawText(background, overlay->getMarginBottomLeft(), overlay->getFontsizeBottomLeft(), overlay->getRenderedBottomLeft(currentImage.filename).c_str(), Qt::AlignBottom|Qt::AlignLeft);
drawText(background, overlay->getMarginBottomRight(), overlay->getFontsizeBottomRight(), overlay->getRenderedBottomRight(currentImage).c_str(), Qt::AlignBottom|Qt::AlignRight); drawText(background, overlay->getMarginBottomRight(), overlay->getFontsizeBottomRight(), overlay->getRenderedBottomRight(currentImage.filename).c_str(), Qt::AlignBottom|Qt::AlignRight);
if (debugMode) if (debugMode)
{ {
// draw a thumbnail version of the source image in the bottom left, to check for cropping issues // draw a thumbnail version of the source image in the bottom left, to check for cropping issues
@@ -207,7 +206,7 @@ void MainWindow::setOverlay(Overlay* o)
QPixmap MainWindow::getBlurredBackground(const QPixmap& originalSize, const QPixmap& scaled) QPixmap MainWindow::getBlurredBackground(const QPixmap& originalSize, const QPixmap& scaled)
{ {
if (imageOptions.fitAspectAxisToWindow) { if (currentImage.options.fitAspectAxisToWindow) {
// our scaled version will just fill the whole screen, us it directly // our scaled version will just fill the whole screen, us it directly
return scaled.copy(); return scaled.copy();
} else if (scaled.width() < width()) { } else if (scaled.width() < width()) {
@@ -225,21 +224,21 @@ QPixmap MainWindow::getBlurredBackground(const QPixmap& originalSize, const QPix
QPixmap MainWindow::getRotatedPixmap(const QPixmap& p) QPixmap MainWindow::getRotatedPixmap(const QPixmap& p)
{ {
QMatrix matrix; QMatrix matrix;
matrix.rotate(imageOptions.rotation); matrix.rotate(currentImage.rotation);
return p.transformed(matrix); return p.transformed(matrix);
} }
QPixmap MainWindow::getScaledPixmap(const QPixmap& p) QPixmap MainWindow::getScaledPixmap(const QPixmap& p)
{ {
if (imageOptions.fitAspectAxisToWindow) if (currentImage.options.fitAspectAxisToWindow)
{ {
if (imageOptions.aspect == 'p') if (currentImage.aspect == EImageAspect_Portrait)
{ {
// potrait mode, make height of image fit screen and crop top/bottom // potrait mode, make height of image fit screen and crop top/bottom
QPixmap pTemp = p.scaledToHeight(height(), Qt::SmoothTransformation); QPixmap pTemp = p.scaledToHeight(height(), Qt::SmoothTransformation);
return pTemp.copy(0,0,width(),height()); return pTemp.copy(0,0,width(),height());
} }
else if (imageOptions.aspect == 'l') else if (currentImage.aspect == EImageAspect_Landscape)
{ {
// landscape mode, make width of image fit screen and crop top/bottom // landscape mode, make width of image fit screen and crop top/bottom
QPixmap pTemp = p.scaledToWidth(width(), Qt::SmoothTransformation); QPixmap pTemp = p.scaledToWidth(width(), Qt::SmoothTransformation);

View File

@@ -3,6 +3,7 @@
#include <QMainWindow> #include <QMainWindow>
#include <QPixmap> #include <QPixmap>
#include "imagestructs.h"
#include "imageselector.h" #include "imageselector.h"
namespace Ui { namespace Ui {
@@ -22,19 +23,21 @@ public:
bool event(QEvent* event) override; bool event(QEvent* event) override;
void resizeEvent(QResizeEvent* event) override; void resizeEvent(QResizeEvent* event) override;
~MainWindow(); ~MainWindow();
void setImage(const std::string& path, const ImageOptions_t &options); void setImage(const ImageDetails_t &imageDetails);
void setBlurRadius(unsigned int blurRadius); void setBlurRadius(unsigned int blurRadius);
void setBackgroundOpacity(unsigned int opacity); void setBackgroundOpacity(unsigned int opacity);
void warn(std::string text); void warn(std::string text);
void setOverlay(Overlay* overlay); void setOverlay(Overlay* overlay);
void setDebugMode(bool debugModeIn) {debugMode = debugModeIn;} void setDebugMode(bool debugModeIn) {debugMode = debugModeIn;}
void setBaseOptions(const ImageDisplayOptions_t &baseOptionsIn) { baseImageOptions = baseOptionsIn; }
const ImageDisplayOptions_t &getBaseOptions() { return baseImageOptions; }
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
std::string currentImage;
unsigned int blurRadius = 20; unsigned int blurRadius = 20;
unsigned int backgroundOpacity = 150; unsigned int backgroundOpacity = 150;
ImageOptions_t imageOptions; ImageDisplayOptions_t baseImageOptions;
ImageDetails_t currentImage;
bool debugMode = false; bool debugMode = false;
Overlay* overlay; Overlay* overlay;

View File

@@ -25,7 +25,7 @@ QStringList PathTraverser::getImageFormats() const {
return imageFormats; return imageFormats;
} }
void PathTraverser::LoadOptionsForDirectory(const std::string &directoryPath, ImageOptions_t &options) const void PathTraverser::LoadOptionsForDirectory(const std::string &directoryPath, ImageDisplayOptions_t &options) const
{ {
QDir directory(directoryPath.c_str()); QDir directory(directoryPath.c_str());
QString jsonFile = directory.filePath(QString("options.json")); QString jsonFile = directory.filePath(QString("options.json"));
@@ -79,7 +79,7 @@ const std::string RecursivePathTraverser::getImagePath(const std::string image)
return image; return image;
} }
void RecursivePathTraverser::UpdateOptionsForImage(const std::string& filename, ImageOptions_t& options) const void RecursivePathTraverser::UpdateOptionsForImage(const std::string& filename, ImageDisplayOptions_t& options) const
{ {
QDir d = QFileInfo(filename.c_str()).absoluteDir(); QDir d = QFileInfo(filename.c_str()).absoluteDir();
LoadOptionsForDirectory(d.absolutePath().toStdString(), options); LoadOptionsForDirectory(d.absolutePath().toStdString(), options);
@@ -103,7 +103,7 @@ const std::string DefaultPathTraverser::getImagePath(const std::string image) co
return directory.filePath(QString(image.c_str())).toStdString(); return directory.filePath(QString(image.c_str())).toStdString();
} }
void DefaultPathTraverser::UpdateOptionsForImage(const std::string& filename, ImageOptions_t& options) const void DefaultPathTraverser::UpdateOptionsForImage(const std::string& filename, ImageDisplayOptions_t& options) const
{ {
UNUSED(filename); UNUSED(filename);
LoadOptionsForDirectory(directory.absolutePath().toStdString(), options); LoadOptionsForDirectory(directory.absolutePath().toStdString(), options);
@@ -129,7 +129,7 @@ const std::string ImageListPathTraverser::getImagePath(const std::string image)
return image; return image;
} }
void ImageListPathTraverser::UpdateOptionsForImage(const std::string& filename, ImageOptions_t& options) const void ImageListPathTraverser::UpdateOptionsForImage(const std::string& filename, ImageDisplayOptions_t& options) const
{ {
// no per file options modification supported // no per file options modification supported
UNUSED(filename); UNUSED(filename);

View File

@@ -16,13 +16,13 @@ class PathTraverser
virtual ~PathTraverser(); virtual ~PathTraverser();
virtual QStringList getImages() const = 0; virtual QStringList getImages() const = 0;
virtual const std::string getImagePath(const std::string image) const = 0; virtual const std::string getImagePath(const std::string image) const = 0;
virtual void UpdateOptionsForImage(const std::string& filename, ImageOptions_t& options) const = 0; virtual void UpdateOptionsForImage(const std::string& filename, ImageDisplayOptions_t& options) const = 0;
protected: protected:
const std::string path; const std::string path;
bool debugMode = false; bool debugMode = false;
QStringList getImageFormats() const; QStringList getImageFormats() const;
void LoadOptionsForDirectory(const std::string &directoryPath, ImageOptions_t &options) const; void LoadOptionsForDirectory(const std::string &directoryPath, ImageDisplayOptions_t &options) const;
}; };
class RecursivePathTraverser : public PathTraverser class RecursivePathTraverser : public PathTraverser
@@ -32,7 +32,7 @@ class RecursivePathTraverser : public PathTraverser
virtual ~RecursivePathTraverser(); virtual ~RecursivePathTraverser();
QStringList getImages() const; QStringList getImages() const;
virtual const std::string getImagePath(const std::string image) const; virtual const std::string getImagePath(const std::string image) const;
virtual void UpdateOptionsForImage(const std::string& filename, ImageOptions_t& options) const; virtual void UpdateOptionsForImage(const std::string& filename, ImageDisplayOptions_t& options) const;
}; };
class DefaultPathTraverser : public PathTraverser class DefaultPathTraverser : public PathTraverser
@@ -42,7 +42,7 @@ class DefaultPathTraverser : public PathTraverser
virtual ~DefaultPathTraverser(); virtual ~DefaultPathTraverser();
QStringList getImages() const; QStringList getImages() const;
virtual const std::string getImagePath(const std::string image) const; virtual const std::string getImagePath(const std::string image) const;
virtual void UpdateOptionsForImage(const std::string& filename, ImageOptions_t& options) const; virtual void UpdateOptionsForImage(const std::string& filename, ImageDisplayOptions_t& options) const;
private: private:
QDir directory; QDir directory;
}; };
@@ -54,7 +54,7 @@ class ImageListPathTraverser : public PathTraverser
virtual ~ImageListPathTraverser(); virtual ~ImageListPathTraverser();
QStringList getImages() const; QStringList getImages() const;
virtual const std::string getImagePath(const std::string image) const; virtual const std::string getImagePath(const std::string image) const;
virtual void UpdateOptionsForImage(const std::string& filename, ImageOptions_t& options) const; virtual void UpdateOptionsForImage(const std::string& filename, ImageDisplayOptions_t& options) const;
private: private:
QStringList imageList; QStringList imageList;
}; };