- 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:
@@ -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");
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
41
src/main.cpp
41
src/main.cpp
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user