Skip to content

Commit

Permalink
Add random slideshow feature
Browse files Browse the repository at this point in the history
  • Loading branch information
macote committed Jul 12, 2017
1 parent 0f79e50 commit 7883e13
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 28 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## 1.3.0 (xxxx-xx-xx)
## 1.3.0 (2017-07-12)

- Slideshow
- Browse to first and last with Home and End
Expand Down
55 changes: 52 additions & 3 deletions ImgBrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ void ImgBrowser::CollectFile(std::wstring filepath)
{
EnterCriticalSection(&browsecriticalsection_);
files_.insert(filepath);
randomlist_.push_back(filepath);
cache_.Add(filepath, targetwidth_, targetheight_);
loader_.LoadAsync(cache_.Get(filepath).get());
if (currentfileiterator_ == files_.end())
Expand Down Expand Up @@ -45,7 +46,8 @@ DWORD ImgBrowser::CollectFolder(std::wstring folderpath)
CollectFile(currentfile);
}
}
} while (FindNextFile(hFind, &findfiledata) && !cancellationflag_);
}
while (FindNextFile(hFind, &findfiledata) && !cancellationflag_);

FindClose(hFind);
}
Expand Down Expand Up @@ -148,6 +150,8 @@ void ImgBrowser::StopBrowsing()

void ImgBrowser::Reset()
{
randomlist_.clear();
currentrandomindex_ = 0x80000000;
files_.clear();
currentfileiterator_ = files_.end();
}
Expand Down Expand Up @@ -244,6 +248,50 @@ BOOL ImgBrowser::MoveToLast()
return moveSuccess;
}

BOOL ImgBrowser::MoveToItem(std::wstring filepath)
{
BOOL moveSuccess = FALSE;
EnterCriticalSection(&browsecriticalsection_);
currentfileiterator_ = files_.find(filepath);
moveSuccess = currentfileiterator_ != files_.end();
LeaveCriticalSection(&browsecriticalsection_);
return moveSuccess;
}

BOOL ImgBrowser::MoveToRandom()
{
BOOL moveSuccess = FALSE;
EnterCriticalSection(&browsecriticalsection_);
if (currentrandomindex_ >= randomlist_.size())
{
std::wstring last;
if (currentrandomindex_ != kIndexPark)
{
last = randomlist_[currentrandomindex_ - 1];
}

std::shuffle(std::begin(randomlist_), std::end(randomlist_), rnge_);
if (last == *randomlist_.begin() && randomlist_.size() > 1)
{
do
{
std::shuffle(std::begin(randomlist_), std::end(randomlist_), rnge_);
}
while (last == *randomlist_.begin());
}

currentrandomindex_ = 0;
}

auto filepath = randomlist_[currentrandomindex_];
++currentrandomindex_;

moveSuccess = MoveToItem(filepath);

LeaveCriticalSection(&browsecriticalsection_);
return moveSuccess;
}

void ImgBrowser::RemoveCurrentItem()
{
EnterCriticalSection(&browsecriticalsection_);
Expand All @@ -267,7 +315,7 @@ void ImgBrowser::InitializeTempPath()
TCHAR temppathbuffer[MAX_PATH];

auto pathlen = GetTempPath(MAX_PATH, temppathbuffer);
if (pathlen > MAX_PATH || (pathlen == 0))
if (pathlen > MAX_PATH || pathlen == 0)
{
// TODO: handle error.
}
Expand Down Expand Up @@ -308,7 +356,8 @@ void ImgBrowser::InitializeTempPath()
{
FindClose(find);
}
} while (folderexists);
}
while (folderexists);
}

void ImgBrowser::DeleteTempPath()
Expand Down
11 changes: 11 additions & 0 deletions ImgBrowser.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
#include "ImgLoader.h"
#include <Windows.h>
#include <set>
#include <vector>
#include <iterator>
#include <limits>
#include <random>

class ImgBrowser
{
public:
static const DWORD kIndexPark = 0x80000000;
public:
ImgBrowser()
{
Expand Down Expand Up @@ -37,6 +42,8 @@ class ImgBrowser
BOOL MoveToPrevious();
BOOL MoveToFirst();
BOOL MoveToLast();
BOOL MoveToItem(std::wstring filepath);
BOOL MoveToRandom();
void RemoveCurrentItem();
private:
ImgCache cache_;
Expand All @@ -46,6 +53,10 @@ class ImgBrowser
std::wstring temppath_;
std::set<std::wstring>::iterator currentfileiterator_;
std::set<std::wstring> files_;
std::vector<std::wstring> randomlist_;
DWORD currentrandomindex_{ kIndexPark };
std::random_device rd_;
std::mt19937 rnge_{ rd_() };
HANDLE collectorthread_{ NULL };
CRITICAL_SECTION browsecriticalsection_;
INT targetwidth_{};
Expand Down
2 changes: 1 addition & 1 deletion ImgItemHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class ImgItemHelper
static void ResizeAndRotateImage(ImgItem& imgitem, Gdiplus::Bitmap* bitmap, INT targetwidth, INT targetheight,
Gdiplus::RotateFlipType rotateflip);
static void RotateImage(ImgItem& imgitem, Gdiplus::Bitmap* bitmap, Gdiplus::RotateFlipType rotateflip);
private:
static std::unique_ptr<Gdiplus::Bitmap> Get24bppRGBBitmap(INT width, INT height, PBYTE buffer);
private:
static void HandleBuffer(ImgItem& imgitem, Gdiplus::Bitmap* bitmap);
static const INT kGDIOperationSemaphoreCount = 1;
static CountingSemaphore kGDIOperationSemaphore;
Expand Down
18 changes: 13 additions & 5 deletions ImgJPEGItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ void ImgJPEGItem::Load()
{
status_ = Status::Loading;
tjhandle jpegdecompressor = NULL;
INT pixelformat = TJPF_BGR;
INT decompressflags{ TJFLAG_FASTDCT };
INT targetwidth, targetheight;
PBYTE buffer = NULL;
Expand Down Expand Up @@ -53,15 +54,14 @@ void ImgJPEGItem::Load()
INT jpegSubsamp, jpegColorspace;
if (tjDecompressHeader3(jpegdecompressor, jpegfilemap.view(), jpegfilemap.filesize().LowPart, &width_, &height_, &jpegSubsamp, &jpegColorspace))
{
errorstring_ = tjGetErrorStr();
status_ = Status::Error;
goto done;
}

if (jpegColorspace == TJCS::TJCS_CMYK || jpegColorspace == TJCS::TJCS_YCCK)
{
// TODO: determine if it should be supported
status_ = Status::Error;
goto done;
pixelformat = TJPF_CMYK;
}

if (rotateflip == Gdiplus::Rotate90FlipNone || rotateflip == Gdiplus::Rotate270FlipNone)
Expand Down Expand Up @@ -108,7 +108,7 @@ void ImgJPEGItem::Load()
displayheight_ = height_;
}

stride_ = TJPAD(displaywidth_ * tjPixelSize[TJPF_RGB]);
stride_ = TJPAD(displaywidth_ * tjPixelSize[pixelformat]);
buffersize_ = stride_ * displayheight_;

buffer = (PBYTE)HeapAlloc(heap_, 0, buffersize_);
Expand All @@ -118,8 +118,16 @@ void ImgJPEGItem::Load()
decompressflags |= TJFLAG_BOTTOMUP;
}

if (tjDecompress2(jpegdecompressor, jpegfilemap.view(), jpegfilemap.filesize().LowPart, buffer, displaywidth_, stride_, displayheight_, TJPF_BGR, decompressflags))
if (tjDecompress2(jpegdecompressor, jpegfilemap.view(), jpegfilemap.filesize().LowPart, buffer, displaywidth_, stride_, displayheight_, pixelformat, decompressflags))
{
errorstring_ = tjGetErrorStr();
status_ = Status::Error;
goto done;
}

if (pixelformat == TJPF_CMYK)
{
// TODO: support CMYK JPEG images
status_ = Status::Error;
goto done;
}
Expand Down
1 change: 1 addition & 0 deletions ImgJPEGItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ class ImgJPEGItem : public ImgItem
private:
INT scalingfactorcount_{};
tjscalingfactor* scalingfactors_{ nullptr };
std::string errorstring_;
INT GetScalingFactorIndex(INT width, INT height, INT targetwidth, INT targetheight);
};
23 changes: 12 additions & 11 deletions ImgVw.rc
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,18 @@ END
IDC_IMGVW ACCELERATORS
BEGIN
"A", IDM_ABOUT, VIRTKEY, SHIFT, CONTROL, NOINVERT
"Q", IDM_EXIT, VIRTKEY, CONTROL, NOINVERT
VK_ESCAPE, IDR_ESCAPE, VIRTKEY
VK_LEFT, IDR_PREVIOUS, VIRTKEY
VK_RIGHT, IDR_NEXT, VIRTKEY
VK_DELETE, IDR_RECYCLE, VIRTKEY
VK_DELETE, IDR_DELETE, VIRTKEY, SHIFT
VK_HOME, IDR_FIRST, VIRTKEY
VK_END, IDR_LAST, VIRTKEY
VK_F5, IDR_TOGGLESS, VIRTKEY
VK_F6, IDR_INCSSS, VIRTKEY
VK_F7, IDR_DECSSS, VIRTKEY
"Q", IDM_EXIT, VIRTKEY, CONTROL, NOINVERT
VK_ESCAPE, IDR_ESCAPE, VIRTKEY
VK_LEFT, IDR_PREVIOUS, VIRTKEY
VK_RIGHT, IDR_NEXT, VIRTKEY
VK_DELETE, IDR_RECYCLE, VIRTKEY
VK_DELETE, IDR_DELETE, VIRTKEY, SHIFT
VK_HOME, IDR_FIRST, VIRTKEY
VK_END, IDR_LAST, VIRTKEY
VK_F5, IDR_TOGGLESS, VIRTKEY
VK_F5, IDR_TOGGLESSR, VIRTKEY, SHIFT
VK_F6, IDR_INCSSS, VIRTKEY
VK_F7, IDR_DECSSS, VIRTKEY
END


Expand Down
14 changes: 9 additions & 5 deletions ImgVwWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ImgVwWindow* ImgVwWindow::Create(HINSTANCE hInst, std::vector<std::wstring> args
self->backgroundbrush_ = CreateSolidBrush(RGB(0, 0, 0));
self->manualcursor_ = TRUE;
self->dontfillbackground_ = TRUE;
if (self->WinCreateWindow(WS_EX_APPWINDOW, L"ImgVw", WS_POPUP, 0, 0,
if (self->WinCreateWindow(WS_EX_APPWINDOW, L"ImgVw", WS_POPUP, 0, 0,
GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL))
{
return self;
Expand Down Expand Up @@ -169,8 +169,9 @@ void ImgVwWindow::HandleMouseWheel(WORD distance)
}
}

void ImgVwWindow::ToggleSlideShow()
void ImgVwWindow::ToggleSlideShow(BOOL slideshowrandom)
{
slideshowrandom_ = slideshowrandom;
if (!slideshowrunning_)
{
StartSlideShow();
Expand Down Expand Up @@ -228,8 +229,8 @@ void ImgVwWindow::DecreaseSlideShowSpeed()

void ImgVwWindow::HandleSlideShow()
{
if (browser_.MoveToNext() || browser_.MoveToFirst())
{
if ((slideshowrandom_ && browser_.MoveToRandom()) || browser_.MoveToNext() || browser_.MoveToFirst())
{
InvalidateScreen();
}
}
Expand Down Expand Up @@ -349,7 +350,10 @@ LRESULT ImgVwWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
DeleteCurrentItem(LOWORD(wParam) == IDR_RECYCLE);
break;
case IDR_TOGGLESS:
ToggleSlideShow();
ToggleSlideShow(FALSE);
break;
case IDR_TOGGLESSR:
ToggleSlideShow(TRUE);
break;
case IDR_INCSSS:
IncreaseSlideShowSpeed();
Expand Down
5 changes: 3 additions & 2 deletions ImgVwWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
class ImgVwWindow : public Window
{
public:
static const INT kInitialSlideShowIntervalInMilliseconds = 5000;
static const INT kInitialSlideShowIntervalInMilliseconds = 4000;
static const INT kMinimumSlideShowIntervalInMilliseconds = 500;
static const INT kMaximumSlideShowIntervalInMilliseconds = 10000;
static const INT kSlideShowIntervalIncrementStepInMilliseconds = 500;
Expand Down Expand Up @@ -46,7 +46,7 @@ class ImgVwWindow : public Window
void BrowseFirst();
void BrowseLast();
void HandleMouseWheel(WORD distance);
void ToggleSlideShow();
void ToggleSlideShow(BOOL slideshowrandom);
void StartSlideShow();
void StopSlideShow();
void RestartSlideShowTimer();
Expand All @@ -66,6 +66,7 @@ class ImgVwWindow : public Window
HFONT captionfont_{ nullptr };
LARGE_INTEGER frequency_{};
BOOL slideshowrunning_{};
BOOL slideshowrandom_{};
UINT slideshowinterval_{ kInitialSlideShowIntervalInMilliseconds };
#if _DEBUG && LOGIMGVWWINDOW
TimestampLogger logger_;
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Pass a file or folder as an argument.
| Home | Go to first |
| End | Go to last |
| F5 | Toggle slideshow |
| Shift + F5 | Toggle slideshow (random mode) |
| F6 | Increase slideshow speed |
| F7 | Decrease slideshow speed |
| Delete | Move to recycle bin if possible or delete |
Expand Down
1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## High Priority

- Support CMYK JPEG images
- Review error handling
- Storage management
- Check remaining temp space, use page file, use memory, etc.
Expand Down
1 change: 1 addition & 0 deletions resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define IDR_INCSSS 117
#define IDR_DECSSS 118
#define IDT_SLIDESHOW 119
#define IDR_TOGGLESSR 120
#define IDC_STATIC -1

#define WM_PROGRESS_EVENT_DATA WM_USER + 1
Expand Down

0 comments on commit 7883e13

Please sign in to comment.