- Add a verbose flag and put debugging output being it ("-v" || " --verbose")

- In verbose mode draw a thumbnail of the source image in the bottom left of the window
- Add support for long options in the command line parsing
- Add a "stretch" argument that will stretch the aspect axis to fit the window when set. For example, in landscape mode the drawn picture will be as wide as the window, cropping the top and bottom
This commit is contained in:
Alfred Reynolds
2021-07-29 13:13:38 +12:00
parent bee9a78986
commit a0089db75b
7 changed files with 116 additions and 13 deletions

View File

@@ -118,7 +118,10 @@ std::string RandomImageSelector::getNextImage()
unsigned int RandomImageSelector::selectRandom(const QStringList& images) const unsigned int RandomImageSelector::selectRandom(const QStringList& images) const
{ {
if(_debugMode)
{
std::cout << "images: " << images.size() << std::endl; std::cout << "images: " << images.size() << std::endl;
}
if (images.size() == 0) if (images.size() == 0)
{ {
throw std::string("No jpg images found in given folder"); throw std::string("No jpg images found in given folder");

View File

@@ -14,12 +14,14 @@ public:
ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspect); ImageSelector(std::unique_ptr<PathTraverser>& pathTraverser, char aspect);
virtual ~ImageSelector(); virtual ~ImageSelector();
virtual std::string getNextImage() = 0; virtual std::string getNextImage() = 0;
void setDebugMode(bool debugMode) { _debugMode = debugMode;}
protected: protected:
int getImageRotation(const std::string &fileName); int getImageRotation(const std::string &fileName);
bool imageValidForAspect(const std::string &fileName); bool imageValidForAspect(const std::string &fileName);
std::unique_ptr<PathTraverser>& pathTraverser; std::unique_ptr<PathTraverser>& pathTraverser;
char _aspect; char _aspect;
bool _debugMode = false;
}; };
class RandomImageSelector : public ImageSelector class RandomImageSelector : public ImageSelector

View File

@@ -8,13 +8,14 @@
#include <sys/file.h> #include <sys/file.h>
#include <errno.h> #include <errno.h>
#include <getopt.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <memory> #include <memory>
void usage(std::string programName) { void usage(std::string programName) {
std::cerr << "Usage: " << programName << " [-t rotation_seconds] [-o background_opacity(0..255)] [-b blur_radius] -p image_folder [-r] [-s]" << std::endl; std::cerr << "Usage: " << programName << " [-t rotation_seconds] [-a aspect('l','p','a')] [-o background_opacity(0..255)] [-b blur_radius] -p image_folder [-r] [-s] [-v] [--verbose] [--stretch]" << std::endl;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@@ -29,11 +30,28 @@ int main(int argc, char *argv[])
bool recursive = false; bool recursive = false;
bool shuffle = false; bool shuffle = false;
bool sorted = false; bool sorted = false;
bool debugMode = false;
char aspect = 'a'; char aspect = 'a';
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 = "";
while ((opt = getopt(argc, argv, "b:p:t:o:O:a:rsS")) != -1) { int debugInt = 0;
int stretchInt = 0;
static struct option long_options[] =
{
{"verbose", no_argument, &debugInt, 1},
{"stretch", no_argument, &stretchInt, 1},
};
int option_index = 0;
while ((opt = getopt_long(argc, argv, "b:p:t:o:O:a:rsSv", long_options, &option_index)) != -1) {
switch (opt) { switch (opt) {
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
usage(argv[0]);
return 1;
break;
case 'p': case 'p':
path = optarg; path = optarg;
break; break;
@@ -67,11 +85,22 @@ int main(int argc, char *argv[])
case 'O': case 'O':
overlay = optarg; overlay = optarg;
break; break;
case 'v':
debugMode = true;
break;
default: /* '?' */ default: /* '?' */
usage(argv[0]); usage(argv[0]);
return 1; return 1;
} }
} }
if(debugInt==1)
{
debugMode = true;
}
if(stretchInt==1)
{
fitAspectAxisToWindow = true;
}
if (path.empty()) if (path.empty())
{ {
@@ -103,10 +132,18 @@ int main(int argc, char *argv[])
{ {
selector = std::unique_ptr<ImageSelector>(new RandomImageSelector(pathTraverser, aspect)); selector = std::unique_ptr<ImageSelector>(new RandomImageSelector(pathTraverser, aspect));
} }
selector->setDebugMode(debugMode);
if(debugMode)
{
std::cout << "Rotation Time: " << rotationSeconds << std::endl; std::cout << "Rotation Time: " << rotationSeconds << std::endl;
std::cout << "Overlay input: " << overlay << std::endl; std::cout << "Overlay input: " << overlay << std::endl;
}
Overlay o(overlay); Overlay o(overlay);
o.setDebugMode(debugMode);
w.setOverlay(&o); w.setOverlay(&o);
w.setAspect(aspect);
w.setDebugMode(debugMode);
w.setFitAspectAxisToWindow(fitAspectAxisToWindow);
w.show(); w.show();
ImageSwitcher switcher(w, rotationSeconds * 1000, selector); ImageSwitcher switcher(w, rotationSeconds * 1000, selector);

View File

@@ -109,6 +109,11 @@ void MainWindow::updateImage(bool immediately)
} }
QPixmap p( currentImage.c_str() ); QPixmap p( currentImage.c_str() );
if(_debugMode)
{
std::cout << "size:" << p.width() << "x" << p.height() << std::endl;
}
QPixmap rotated = getRotatedPixmap(p); QPixmap rotated = getRotatedPixmap(p);
QPixmap scaled = getScaledPixmap(rotated); QPixmap scaled = getScaledPixmap(rotated);
QPixmap background = getBlurredBackground(rotated, scaled); QPixmap background = getBlurredBackground(rotated, scaled);
@@ -120,6 +125,21 @@ void MainWindow::updateImage(bool immediately)
drawText(background, overlay->getMarginTopRight(), overlay->getFontsizeTopRight(), overlay->getRenderedTopRight(currentImage).c_str(), Qt::AlignTop|Qt::AlignRight); drawText(background, overlay->getMarginTopRight(), overlay->getFontsizeTopRight(), overlay->getRenderedTopRight(currentImage).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).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).c_str(), Qt::AlignBottom|Qt::AlignRight);
if (_debugMode)
{
// draw a thumbnail version of the source image in the bottom left, to check for cropping issues
QPainter pt(&background);
QBrush brush(QColor(255, 255, 255, 255));
int margin = 10;
QPixmap thumbNail = p.scaledToWidth(200, Qt::SmoothTransformation);
pt.fillRect(background.width() - thumbNail.width() - 2*margin,
background.height()-thumbNail.height() - 2*margin,
thumbNail.width() +2*margin, thumbNail.height()+2*margin, brush);
pt.drawPixmap( background.width() - thumbNail.width() - margin,
background.height()-thumbNail.height() - margin,
thumbNail);
}
} }
label->setPixmap(background); label->setPixmap(background);
@@ -164,13 +184,19 @@ void MainWindow::setOverlay(Overlay* o)
overlay = o; overlay = o;
} }
void MainWindow::setAspect(char aspect)
{
_aspect = aspect;
}
QPixmap MainWindow::getBlurredBackground(const QPixmap& originalSize, const QPixmap& scaled) QPixmap MainWindow::getBlurredBackground(const QPixmap& originalSize, const QPixmap& scaled)
{ {
if (scaled.width() < width()) { if (scaled.width() < width() || _aspect == 'l') {
QPixmap background = blur(originalSize.scaledToWidth(width(), Qt::SmoothTransformation)); QPixmap background = blur(originalSize.scaledToWidth(width(), Qt::SmoothTransformation));
QRect rect(0, (background.height() - height())/2, width(), height()); QRect rect(0, (background.height() - height())/2, width(), height());
return background.copy(rect); return background.copy(rect);
} else { } else {
// aspect 'p' or the image is not as wide as the screen
QPixmap background = blur(originalSize.scaledToHeight(height(), Qt::SmoothTransformation)); QPixmap background = blur(originalSize.scaledToHeight(height(), Qt::SmoothTransformation));
QRect rect((background.width() - width())/2, 0, width(), height()); QRect rect((background.width() - width())/2, 0, width(), height());
return background.copy(rect); return background.copy(rect);
@@ -186,6 +212,25 @@ QPixmap MainWindow::getRotatedPixmap(const QPixmap& p)
QPixmap MainWindow::getScaledPixmap(const QPixmap& p) QPixmap MainWindow::getScaledPixmap(const QPixmap& p)
{ {
if (_fitAspectAxisToWindow)
{
if ( _aspect == 'p')
{
// potrait mode, make height of image fit screen and crop top/bottom
QPixmap pTemp = p.scaledToHeight(height(), Qt::SmoothTransformation);
return pTemp.copy(0,0,width(),height());
}
else if ( _aspect == 'l')
{
// landscape mode, make width of image fit screen and crop top/bottom
QPixmap pTemp = p.scaledToWidth(width(), Qt::SmoothTransformation);
//int imageTempWidth = pTemp.width();
//int imageTempHeight = pTemp.height();
return pTemp.copy(0,0,width(),height());
}
}
// just scale the best we can for the given photo
int w = width(); int w = width();
int h = height(); int h = height();
return p.scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation); return p.scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation);

View File

@@ -25,13 +25,18 @@ public:
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 setAspect(char aspect);
void setDebugMode(bool debugMode) {_debugMode = debugMode;}
void setFitAspectAxisToWindow(bool fitAspectAxisToWindow) { _fitAspectAxisToWindow = fitAspectAxisToWindow; }
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
std::string currentImage; std::string currentImage;
unsigned int blurRadius = 20; unsigned int blurRadius = 20;
unsigned int backgroundOpacity = 150; unsigned int backgroundOpacity = 150;
char _aspect = 'a';
bool _debugMode = false;
bool _fitAspectAxisToWindow = false;
Overlay* overlay; Overlay* overlay;

View File

@@ -50,7 +50,10 @@ void Overlay::parseInput() {
QString Overlay::getTemplate(QStringList components){ QString Overlay::getTemplate(QStringList components){
if (components.size()>3) { if (components.size()>3) {
if(_debugMode)
{
std::cout << "template: " << components[3].toStdString() << std::endl; std::cout << "template: " << components[3].toStdString() << std::endl;
}
return components[3]; return components[3];
} }
return ""; return "";
@@ -58,7 +61,10 @@ QString Overlay::getTemplate(QStringList components){
int Overlay::getMargin(QStringList components){ int Overlay::getMargin(QStringList components){
if (components.size()>1) { if (components.size()>1) {
if(_debugMode)
{
std::cout << "margin: " << components[1].toStdString() << std::endl; std::cout << "margin: " << components[1].toStdString() << std::endl;
}
int num = components[1].toInt(); int num = components[1].toInt();
if (num > 0) { if (num > 0) {
return num; return num;
@@ -70,7 +76,10 @@ int Overlay::getMargin(QStringList components){
int Overlay::getFontsize(QStringList components){ int Overlay::getFontsize(QStringList components){
if (components.size()>2) { if (components.size()>2) {
if(_debugMode)
{
std::cout << "fontsize: " << components[2].toStdString() << std::endl; std::cout << "fontsize: " << components[2].toStdString() << std::endl;
}
int num = components[2].toInt(); int num = components[2].toInt();
if (num > 0) { if (num > 0) {
return num; return num;

View File

@@ -27,11 +27,13 @@ class Overlay
int getMarginBottomRight(); int getMarginBottomRight();
int getFontsizeBottomRight(); int getFontsizeBottomRight();
void setDebugMode(const bool debugMode) { _debugMode = debugMode; }
private: private:
const std::string overlayInput; const std::string overlayInput;
int margin; int margin;
int fontsize; int fontsize;
bool _debugMode = false;
QString topLeftTemplate; QString topLeftTemplate;
QString topRightTemplate; QString topRightTemplate;