diff --git a/README.md b/README.md index f2880ea..0476258 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ This project is maintained by myself during my spare time. If you like and use i ## Usage ``` -slide [-t rotation_seconds] [-o background_opacity(0..255)] [-b blur_radius] -p image_folder [-r] [-O overlay_string] +slide [-t rotation_seconds] [-a aspect] [-o background_opacity(0..255)] [-b blur_radius] -p image_folder [-r] [-O overlay_string] ``` * `image_folder`: where to search for images (.jpg files) @@ -25,6 +25,7 @@ slide [-t rotation_seconds] [-o background_opacity(0..255)] [-b blur_radius] -p * `-s` for shuffle instead of random image rotation * `-S` for sorted rotation (files ordered by name, first images then subfolders) * `rotation_seconds(default=30)`: time until next random image is chosen from the given folder +* `aspect(default=a)`: the required aspect ratio of the picture to display. Valid values are 'a' (all), 'l' (landscape) and 'p' (portrait) * `background_opacity(default=150)`: opacity of the background filling image between 0 (black background) and 255 * `blur_radius(default=20)`: blur radius of the background filling image * `-O` is used to create a overlay string. diff --git a/src/imageselector.cpp b/src/imageselector.cpp index 3d082d6..3eb3b7d 100644 --- a/src/imageselector.cpp +++ b/src/imageselector.cpp @@ -5,21 +5,86 @@ #include #include #include +#include #include #include /* srand, rand */ #include /* time */ #include // std::shuffle #include // std::default_random_engine -ImageSelector::ImageSelector(std::unique_ptr& pathTraverser): - pathTraverser(pathTraverser) +ImageSelector::ImageSelector(std::unique_ptr& pathTraverser, char aspect): + pathTraverser(pathTraverser), _aspect(aspect) { } ImageSelector::~ImageSelector(){} -RandomImageSelector::RandomImageSelector(std::unique_ptr& pathTraverser): - ImageSelector(pathTraverser) +int ImageSelector::getImageRotation(const std::string &fileName) +{ + int orientation = 0; + ExifData *exifData = exif_data_new_from_file(fileName.c_str()); + if (exifData) + { + ExifByteOrder byteOrder = exif_data_get_byte_order(exifData); + ExifEntry *exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION); + + if (exifEntry) + { + orientation = exif_get_short(exifEntry->data, byteOrder); + } + exif_data_free(exifData); + } + + int degrees = 0; + switch(orientation) { + case 8: + degrees = 270; + break; + case 3: + degrees = 180; + break; + case 6: + degrees = 90; + break; + } + return degrees; +} + +bool ImageSelector::imageValidForAspect(const std::string &fileName) +{ + QPixmap p( fileName.c_str() ); + int imageWidth = p.width(); + int imageHeight = p.height(); + int rotation = getImageRotation(fileName); + if ( rotation == 90 || rotation == 270 ) + { + std::swap(imageWidth,imageHeight); + } + + switch(_aspect) + { + case 'a': + // allow all + break; + case 'l': + if ( imageWidth < imageHeight ) + { + return false; + } + break; + case 'p': + if ( imageHeight < imageWidth ) + { + return false; + } + break; + } + return true; +} + + +RandomImageSelector::RandomImageSelector(std::unique_ptr& pathTraverser, char aspect): + ImageSelector(pathTraverser, aspect) { srand (time(NULL)); } @@ -31,9 +96,17 @@ std::string RandomImageSelector::getNextImage() std:: string filename; try { - QStringList images = pathTraverser->getImages(); - unsigned int selectedImage = selectRandom(images); - filename = pathTraverser->getImagePath(images.at(selectedImage).toStdString()); + while (filename.empty()) + { + QStringList images = pathTraverser->getImages(); + unsigned int selectedImage = selectRandom(images); + filename = pathTraverser->getImagePath(images.at(selectedImage).toStdString()); + if (!imageValidForAspect(filename)) + { + filename.clear(); + } + } + } catch(const std::string& err) { @@ -53,8 +126,8 @@ unsigned int RandomImageSelector::selectRandom(const QStringList& images) const return rand() % images.size(); } -ShuffleImageSelector::ShuffleImageSelector(std::unique_ptr& pathTraverser): - ImageSelector(pathTraverser), +ShuffleImageSelector::ShuffleImageSelector(std::unique_ptr& pathTraverser, char aspect): + ImageSelector(pathTraverser, aspect), current_image_shuffle(-1), images() { @@ -92,8 +165,8 @@ std::string ShuffleImageSelector::getNextImage() return filename; } -SortedImageSelector::SortedImageSelector(std::unique_ptr& pathTraverser): - ImageSelector(pathTraverser), +SortedImageSelector::SortedImageSelector(std::unique_ptr& pathTraverser, char aspect): + ImageSelector(pathTraverser, aspect), images() { srand (time(NULL)); diff --git a/src/imageselector.h b/src/imageselector.h index dc73b83..8f58089 100644 --- a/src/imageselector.h +++ b/src/imageselector.h @@ -11,18 +11,21 @@ class PathTraverser; class ImageSelector { public: - ImageSelector(std::unique_ptr& pathTraverser); + ImageSelector(std::unique_ptr& pathTraverser, char aspect); virtual ~ImageSelector(); virtual std::string getNextImage() = 0; protected: + int getImageRotation(const std::string &fileName); + bool imageValidForAspect(const std::string &fileName); std::unique_ptr& pathTraverser; + char _aspect; }; class RandomImageSelector : public ImageSelector { public: - RandomImageSelector(std::unique_ptr& pathTraverser); + RandomImageSelector(std::unique_ptr& pathTraverser, char aspect); virtual ~RandomImageSelector(); virtual std::string getNextImage(); @@ -33,7 +36,7 @@ private: class ShuffleImageSelector : public ImageSelector { public: - ShuffleImageSelector(std::unique_ptr& pathTraverser); + ShuffleImageSelector(std::unique_ptr& pathTraverser, char aspect); virtual ~ShuffleImageSelector(); virtual std::string getNextImage(); @@ -45,7 +48,7 @@ private: class SortedImageSelector : public ImageSelector { public: - SortedImageSelector(std::unique_ptr& pathTraverser); + SortedImageSelector(std::unique_ptr& pathTraverser, char aspect); virtual ~SortedImageSelector(); virtual std::string getNextImage(); diff --git a/src/main.cpp b/src/main.cpp index 8943b49..e274d30 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,12 +29,22 @@ int main(int argc, char *argv[]) bool recursive = false; bool shuffle = false; bool sorted = false; + char aspect = 'a'; + std::string valid_aspects = "alp"; // all, landscape, portait std::string overlay = ""; - while ((opt = getopt(argc, argv, "b:p:t:o:O:rsS")) != -1) { + while ((opt = getopt(argc, argv, "b:p:t:o:O:a:rsS")) != -1) { switch (opt) { case 'p': path = optarg; break; + case 'a': + aspect = optarg[0]; + if ( valid_aspects.find(aspect) == std::string::npos ) + { + std::cout << "Invalid Aspect option, defaulting to all" << std::endl; + aspect = 'a'; + } + break; case 't': rotationSeconds = atoi(optarg); break; @@ -83,16 +93,17 @@ int main(int argc, char *argv[]) std::unique_ptr selector; if (sorted) { - selector = std::unique_ptr(new SortedImageSelector(pathTraverser)); + selector = std::unique_ptr(new SortedImageSelector(pathTraverser, aspect)); } else if (shuffle) { - selector = std::unique_ptr(new ShuffleImageSelector(pathTraverser)); + selector = std::unique_ptr(new ShuffleImageSelector(pathTraverser, aspect)); } else { - selector = std::unique_ptr(new RandomImageSelector(pathTraverser)); + selector = std::unique_ptr(new RandomImageSelector(pathTraverser, aspect)); } + std::cout << "Rotation Time: " << rotationSeconds << std::endl; std::cout << "Overlay input: " << overlay << std::endl; Overlay o(overlay); w.setOverlay(&o);