Click here to Skip to main content
13,555,158 members
Click here to Skip to main content
Add your own
alternative version


122 bookmarked
Posted 24 Feb 2010
Licenced CPOL


, 4 Jan 2013
Rate this:
Please Sign up or sign in to vote.
A lightweight image viewer for .NET 2.0, supporting multi-core processing


ImageFan is a lightweight image viewer for .NET 2.0, supporting multi-core processing.


I have always wanted to exploit the capabilities of .NET to create an image viewer offering a managed (possibly portable due to Mono) counterpart to the existing C / C++ solutions. Also, the lack of 64 bit image viewers has enticed me to pursue a .NET solution that would implicitly run as a 64 bit application, hardware and software platform permitting.

Visual Layout and Functionality

The application is designed in the traditional style of contemporary image viewers as follows:

  • A drives list and corresponding directories tree on the left-hand side of the window
  • A thumbnails list on the right-hand side, revealing thumbnails to the images contained in the selected drive and directory

Selecting a drive refreshes the list of directories and reveals the thumbnails of the images contained on the root drive. Selecting a specific directory fills the thumbnails list with the appropriate thumbnails. The thumbnails list can be navigated on by using the arrow keys and the scroll bar.

When the left mouse button is clicked or the Enter key pressed, while on a thumbnail, a new window is opened, containing the image in full size, scrollable if at least one dimension of the image is greater than the corresponding screen size dimension. The user can traverse the images list using this window, by employing the Space and Backspace keys and the arrow keys. The window can be closed by pressing the Esc key or the closing button on the window.

If the image window is clicked on again or pressed Enter upon, it will set the image to full screen view, resizing it if necessary to fit on the screen. In the full screen mode, the thumbnails list is navigable with the Space and Backspace keys, the arrow keys and the mouse wheel. The user can exit this mode by pressing the Esc key or the left mouse button.

Implementation Challenges and Constraints

The project structure is revealed in the diagram below. I will explain each relevant source code artifact in turn.

Class TasksDispatcher 

This class is a general tasks dispatcher that partitions an array of tasks on the number of available processor cores. In the previous versions, the class used raw threads. In this release, it relies on the ThreadPool class of .NET and, thus, on pooled threads, minimizing thread creation and destruction costs.

For the problem at hand, I use the tasks dispatcher class to partition (by their indexes) the collection of image thumbnails, which is to be displayed asynchronously when the user selects a directory.

using System;
using System.Threading;

namespace ImageFan.Auxiliary
    internal class TasksDispatcher
        public TasksDispatcher(WaitCallback globalTask, WaitCallback individualTask, int tasksCount)
            _globalTask = globalTask;
            _individualTask = individualTask;
            _tasksCount = tasksCount;

            _isStopped = true;

        public void Start()
            _dispatcherIsActive = true;

        public void Stop()
            _dispatcherIsActive = false;

        public bool IsStopped
            get { return _isStopped; }

        #region Private

        private static readonly int ProcessorCount;
        private static AutoResetEvent[] IndividualTaskEvents;

        private WaitCallback _globalTask;
        private WaitCallback _individualTask;
        private int _tasksCount;

        private volatile bool _dispatcherIsActive;
        private volatile bool _isStopped;

        private void WorkerThreadLoopMethod(object state)
                _isStopped = false;
                for (var i = 0; (i < _tasksCount) && (_dispatcherIsActive); i += ProcessorCount)
                    int j;

                    for (j = 0; (j < ProcessorCount) && (i + j < _tasksCount) && (_dispatcherIsActive); j++)
                        _globalTask(i + j);

                    for (j = 0; (j < ProcessorCount) && (i + j < _tasksCount) && (_dispatcherIsActive); j++)
                        ThreadPool.QueueUserWorkItem(IndividualTaskWrapper, new TaskParameter(i + j, j));

                    for (j = 0; (j < ProcessorCount) && (i + j < _tasksCount) && (_dispatcherIsActive); j++)
                _isStopped = true;

        private void IndividualTaskWrapper(object state)
                TaskParameter taskParam = ((TaskParameter)state);



        static TasksDispatcher()
            ProcessorCount = Environment.ProcessorCount;

            IndividualTaskEvents = new AutoResetEvent[ProcessorCount];
            for (var i = 0; i < ProcessorCount; i++)
                IndividualTaskEvents[i] = new AutoResetEvent(false);

Class FolderTreeView

This class is a Windows Form custom control, extending the TreeView control. It displays the folders (directories) on the selected drive in a tree-like manner and, when a directory node is selected, triggers the display of thumbnails in the ThumbnailsSequence control.

Class ThumbnailBox

This type is a Windows Form custom control, inheriting from the UserControl class. It is a variable-size control that displays an image thumbnail box, containing the image thumbnail itself, decorated with the image file name. Its largest dimension, whether width or height, is scaled to ThumbnailSize (200 pixels), while the other dimension is scaled proportionally.

Class ThumbnailsSequence

The class ThumbnailsSequence is derived from a FlowLayout panel and used as a container for the thumbnails generated for the selected directory on the disc.

Class ImageForm

ImageForm is a Windows Form that is shown as a dialog, when the user clicks on a particular image thumbnail, as the current image, when keyboard-navigating on the images inside the directory, or after escaping the full screen mode. The form preserves the image size, enabling scrolling in case the image exceeds the screen size.

Class FullScreenImage

This class is a Windows Form shown as a dialog without a Form border, occupying the full screen size and having a black background. As such, it gives the optical illusion of being an unusual GUI artifact featuring a full screen mode. It also resizes the image, if it is larger than the full screen dimensions available, while maintaining the initial aspect ratio.

Class ImageFile

ImageFile is a flyweight-pattern class, having the image thumbnail stored as its intrinsic state and the full-sized image as its extrinsic state, retrieved only on demand.

Class ImageFolder

This class extracts and manages the image files within a given folder (directory).

Class ImageResizer

This type features two operations: resizing an image extracted from a file (for the generation of thumbnails) and resizing an image taken from memory (for the full-screen mode).

Class GlobalData

This class contains references to the resource images LoadingImage and InvalidImage, as well as to their respective thumbnails.

Lessons Learned

Although this image viewer is a managed application, there is no disparity in browsing or viewing speed (besides specific optimizations) between this solution and native executable ones, such as IrfanView, XnView and AcdSee. This is because the .NET System.Drawing and System.Windows.Forms classes are rather tight wrappers over the WinAPI functionality.

The Image class, inherited by the Bitmap class, implements the IDisposable interface, making the flyweight design pattern implementation straightforward, due to being able to manage the image memory footprint in a deterministic manner.

The improved presence of 64 bit operating systems makes managed programming runtimes truly shine. This is because the applications written in managed languages (such as .NET CLS compliant ones) inherently support a 32 to 64 bit switch using the same binary package, while offering the full advantages of the running platform.

Source Code and Application Download

The complete source code of the ImageFan application (a Google Code project) can be accessed here. If one is only interested in the binaries, they can be downloaded from this link.

I would gladly welcome contributions and feedback to this ImageFan open-source (GPL v3) project.


  • [1] The Microsoft Developer Network (MSDN) pages


  • Version 0.1 - Initial submission - 24/02/2010
  • Version 0.2 - Added download links at the head of the article - 28/02/2010
  • Version 0.3 - Code optimizations and bug-fixes - 18/04/2010
  • Version 0.4 - Updated content, sources and binaries - 21/09/2011
  • Version 0.5 - Reengineered code with significant bug fixes - 09/04/2012
  • Version 0.6 - Many code changes and enhancements. Removed some of the code samples from the article, as they have become bloated and, thus, distracting. Cleaned up the article text - 04/01/2013
  • Version 0.7 - Some bug fixes. Made the thumbnail box variable-size to increase the number of thumbnails on the screen - 09/04/2013
  • Version 0.8 - Minor code and text consistency improvements - 25/02/2015


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Mihnea Rădulescu
Software Developer (Senior)
Switzerland Switzerland
My name is Mihnea Rădulescu and I am a Senior Software Engineer located in Zurich, Switzerland.

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
DVL Patel20-Aug-15 22:19
professionalDVL Patel20-Aug-15 22:19 
GeneralMy vote of 5 Pin
Prasad Khandekar30-Apr-13 0:15
memberPrasad Khandekar30-Apr-13 0:15 
GeneralMy vote of 5 Pin
deepinsd12-Mar-13 5:06
memberdeepinsd12-Mar-13 5:06 
GeneralMy vote of 5 Pin
MarkB1235-Jan-13 0:25
memberMarkB1235-Jan-13 0:25 
QuestionMy vote of 5 Pin
KendoTM16-Apr-12 19:39
memberKendoTM16-Apr-12 19:39 
AnswerRe: My vote of 5 Pin
Mihnea Rădulescu17-Apr-12 5:16
memberMihnea Rădulescu17-Apr-12 5:16 
GeneralMy vote of 5 Pin
Sergio Andrés Gutiérrez Rojas21-Sep-11 8:26
memberSergio Andrés Gutiérrez Rojas21-Sep-11 8:26 
GeneralI like images, and I wrote something like this some time ago for my Msc Pin
Sacha Barber18-Apr-10 23:11
mvpSacha Barber18-Apr-10 23:11 
GeneralRe: I like images, and I wrote something like this some time ago for my Msc Pin
Mihnea Radulescu19-Apr-10 0:59
memberMihnea Radulescu19-Apr-10 0:59 
GeneralRe: I like images, and I wrote something like this some time ago for my Msc Pin
rctaubert10-Apr-12 12:55
memberrctaubert10-Apr-12 12:55 
GeneralRe: I like images, and I wrote something like this some time ago for my Msc Pin
Sacha Barber10-Apr-12 20:18
mvpSacha Barber10-Apr-12 20:18 
GeneralRe: I like images, and I wrote something like this some time ago for my Msc Pin
rctaubert11-Apr-12 2:14
memberrctaubert11-Apr-12 2:14 
GeneralRe: I like images, and I wrote something like this some time ago for my Msc Pin
Marcus Kramer4-Jan-13 10:41
memberMarcus Kramer4-Jan-13 10:41 
GeneralRe: I like images, and I wrote something like this some time ago for my Msc Pin
Sacha Barber4-Jan-13 11:48
mvpSacha Barber4-Jan-13 11:48 
GeneralRe: I like images, and I wrote something like this some time ago for my Msc Pin
Marcus Kramer7-Jan-13 3:05
mvpMarcus Kramer7-Jan-13 3:05 
Generalmy vote of 3 Pin
MP3Observer3-Mar-10 0:02
memberMP3Observer3-Mar-10 0:02 
GeneralRe: my vote of 3 Pin
Mihnea Radulescu3-Mar-10 1:36
memberMihnea Radulescu3-Mar-10 1:36 
GeneralRe: my vote of 3 Pin
hardsoft18-Apr-10 9:07
memberhardsoft18-Apr-10 9:07 
GeneralRe: my vote of 3 Pin
Eddy Vluggen16-May-10 14:51
mvpEddy Vluggen16-May-10 14:51 
GeneralMy vote of 2 Pin
Paradoxon10128-Feb-10 8:23
memberParadoxon10128-Feb-10 8:23 
GeneralRe: My vote of 2 Pin
Mihnea Radulescu3-Mar-10 1:42
memberMihnea Radulescu3-Mar-10 1:42 
GeneralCode... Pin
Gary Noble24-Feb-10 6:19
memberGary Noble24-Feb-10 6:19 
GeneralRe: Code... Pin
Mihnea Radulescu24-Feb-10 9:32
memberMihnea Radulescu24-Feb-10 9:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02-2016 | 2.8.180515.1 | Last Updated 4 Jan 2013
Article Copyright 2010 by Mihnea Rădulescu
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid