- Simple Picture Viewer
- Hot Simple Image Viewer 1 3 Free
- Image Viewer Free
- Hot Simple Image Viewer 1 3 Download
- Hot Simple Image Viewer 1 3 +
- Simple Photo Viewer Windows 10
Eclipse Corner Article |
One Photo Viewer is a simplistic and intuitive photo viewer. Free with no ads. Designed to be used as Windows 10 default photo viewer app. It has some basic features such as slideshow, color adjustment, crop, resize, rotate, copy/paste clipboard, and more. All accessible by right click menu or keyboard shortcuts. It is also touchscreen compatible.
SummaryThis article shows how to extend SWT
- Simple Image Viewer. Rated 4 out of 5 stars. There are 29 reviews 29. Free Sakura Photo Viewer. Rated 4.5 out of 5 stars. There are 43 reviews 43. Free + One Photo Viewer. Rated 4.5 out of 5 stars. There are 248 reviews 248. Free Duplicate Photos Fixer Pro. Rated 3 out of 5 stars.
- 123 Photo Viewer. 123 Photo Viewer is a light and fast photo viewer for Windows 10 with support for OneDrive. Features: The UI is easy to navigate and it comes with plenty of filters and effects for basic editing. There is a slideshow viewer included for reliving those memories. There is support for batch rename and format change.
- How to Restore Windows Photo Viewer in Windows 10 Usually you could use Windows Photo Viewer to view your image files in a variety of ways. You can also print, order prints, attach pictures to an e‑mail message, burn, or open photos in another app on your PC.
Canvas
to implement a mini image viewer plug-in using Java2Dtransforms. Theextended image canvas can be used to scroll and zoom large images, and can alsobe extended to apply other transforms. The implementation is based on SWT andthe non-UI portions of AWT. The plug-in has been tested on Windows, Linux GTK, and MacOS X Carbon with Eclipse 2.1 or better. By ChengdongLi ([email protected])Research in Computing for Humanities, University of Kentucky
March 15, 2004
March 15, 2004
Contents
- Canvas implementation
- Plug-in implementation
Conventions & Terms
The following typographic conventions are used in this article:
Italic:
Used for references to articles.
Used for references to articles.
Courier New:
Used for code or variable names.
The following terms are used in this article:
client area
Thedrawable area of canvas. Also called the paint area or canvas domain.
source image
The image constructed directly fromthe original image data with the same width and height. Unlike image data, it isdevice dependent. It is the
Thedrawable area of canvas. Also called the paint area or canvas domain.
source image
The image constructed directly fromthe original image data with the same width and height. Unlike image data, it isdevice dependent. It is the
sourceImage
in sourcecode. Also called the original image or image domain.Introduction
The goal of this article is to show you how to implement an image viewer withscrolling and zooming operations using affine transforms.If you are new to graphics in SWT, please read Joe Winchester's article Taking a look at SWT Images.A screenshot of the image viewer is shown in Figure 1:
Figure 1 - Image viewer
The implementation here is different from the implementation of the Image Analyzer examplethat comes with Eclipse. This implementation uses affine transforms for scrolling and zooming.
The advantages of this implementation are :
- it offers unlimited zoom scale
- it works well for large images
In the following sections, we will first review the structure of the packageand relationship of classes,then we will discuss how the image canvas works and how to implement a scrollableand zoom-able image canvas -
SWTImageCanvas
. We will useaffine transforms to selectively render images and to generally simplify the implementation. After that, we will showbriefly how to use the local toolbar to facilitate image manipulation.For the detailed steps on how to implement a view, Dave Springgay's article: Creatingan Eclipse View is the most helpful one.
You can compare this implementation with the Image Analyzer example by running both ofthem:
- To run the example for this article unzip imageviewer.zip into your eclipse/plugins/ subdirectory and restart Eclipse. To open the imageviewer view, choose Window -> Show View -> Other -> Sample Category ->Image Viewer. The source plug-in project is imageviewersrc.zip which is included inside the imageviewer.zip.
- To run the Image Analyzer example that comes with Eclipse, download the ExamplePlug-ins from Eclipse.org,and unzip to the eclipse/plugins/ subdirectory and restart Eclipse. Then choose Window -> ShowView -> Other -> SWT Example Launcher -> Standalone -> ImageAnalyzer.
To compile and run the image viewer from source code, unzip the imageviewersrc.zipfile (inside imageviewer.zip), then import the existing project into the workspace, update theclass path, compile, and run.
Classes Overview
The following diagram (Figure 2) shows all classes in this demo plug-in. The
SWTImageCanvas
is a subclass oforg.eclipse.swt.widgets.Canvas
;it implements image loading, rendering, scrolling, and zooming. The ImageView
class is a subclass oforg.eclipse.ui.part.ViewPart
; it has an SWTImageCanvas
instance. The helper classSWT2Dutil
holds utilityfunctions. PushActionDelegate
implements org.eclipse.ui.IViewActionDelegate
; it delegates the toolbar button actions,and has an ImageView
instance. The ImageViewerPlugin
extends org.eclipse.ui.plugin.AbstractUIPlugin
(this class is PDE-generated).Figure 2 - Class diagram ( The classes without package prefix are implementedin our approach. )
A plug-in manifest file plugin.xml defines the runtime requirements and contributions (view andviewActions extensions) toEclipse. Eclipse will create toolbar buttonsfor
ImageView
and delegate toolbar actions via PushActionDelegate
.Canvas implementation
SWTImageCanvas
handles image loading,painting, scrolling, andzooming. It saves a copy of the original SWT image (the sourceImage
)in memory, and then translates and scalesthe image using java.awt.geom.AffineTransform
. Therendering and transformation are applied only to the portion of the imagevisible on thescreen, allowing it to operate on images of any size with good performance. The AffineTransform
gets applied changes as the user scrolls the window and pushes the toolbar buttons.Loading images
First, let's have a look at how to load an image into memory. There are several ways to load animage:
- load an image from the local file system.
- load an image from the workspace.
- load an image from a website.
In this simple implementation, we only allow the user to choose an image fromthe local filesystem. To improve this, you could contribute to the
org.eclipse.ui.popupMenus
of the Navigator view for image files; that way, whenever an image file is selected, the menu item will be available andthe user can choose to load the imagefrom the workspace (you need add nameFilters
, and you may also need to use workspaceAPI). To see how to load an image from a URL, please refer tothe Image Analyzer of SWTexamples.The image loading process is as following (Figure 3):
Figure 3 - Image-loading diagram
Now let's take a look at the code for loading images.
SWTprovides
ImageLoader
to load an image into memory.Image loading is done by using the Image(Display,String)
constructor. To facilitate image loading, we provides adialog to locate all image files supported by SWT ImageLoader
. We use
currentDir
in and to remember the directory for the file open dialog, so that the user can later open other filesin the same directory.The
loadImage
method (shown above) in disposes the old sourceImage
and creates a new sourceImage
,then it calls the showOriginal()
to notify the canvas topaint new image. If loading fails, the canvas will clear the painting areaand disable the scrollbar. Notice that we cannot see ImageLoader
directly in the code above, however, when we call Image(Display,String)
in, Eclipse will callImageLoader.load()
toload the image into memory. is used to show the image at its original size; we willdiscuss this in more detail later.![Simple windows image viewer Simple windows image viewer](https://danbooru.donmai.us/data/sample/sample-114bc2ffe35ba0036e046d69438bcb6d.jpg)
In fact, the above two functionscould be merged into one method. The reason why we separate them is wemay invoke them separately from other functions; for example, we may get the image filename from the database, then we can reload the image by only calling
loadImage()
.Extending org.eclipse.swt.widgets.Canvas
Now, let's see how to create a canvas to render the image and do sometransformations.
The
org.eclipse.swt.widgets.Canvas
is suitable to be extended for rendering images. SWTImageCanvas
extends it and adds scrollbars. This is done by setting the SWT.V_SCROLL
and SWT.H_SCROLL
style bits at the Canvas
constructor: In order to speed up therendering process and reduce flicker, we set the style to
SWT.NO_BACKGROUND
in (and later we use double buffering to render) so that the background (client area) won't be cleared.The new image will beoverlapped on the background. We need to fill the gaps between the new image andthe background when the new image does not fully cover the background. registers aresize listener to synchronize thesize and position of the scrollbar thumb to the image zoom scale andtranslation; registers a paint listener (here it does
paint(GC gc)
)to render the image whenever the PaintEvent
is fired; registers the SelectionListener
for each scrollbar,the SelectionListener
will notify SWTImageCanvas
to scroll and zoomthe image based on the current selection of scrollbars; another function of the SelectionListener
is to enable or disable the scrollbar based on the image size and zoom scale. Rendering images
Whenever the SWT
PaintEvent
is fired, the paint listener (paint(GCgc)
)will be called to paint thedamaged area. In this article, we simply paint the whole client area of thecanvas (see Figure 4).Since we support scrolling and zooming, we need to figure out which part ofthe original image should be drawn to which part of the client area. The painting process is asfollowing:- Find a rectangle
imageRect
inside the source image (image domain); the image inside this rectangle will be drawn to the client area of canvas (canvas domain). - Map the
imageRect
to the client area and getdestRect
. - Draw the source image within
imageRect
todestRect
(scaling it if the sizes are different). - Fill the gaps (shown as blue and green bands in the picture below) if necessary.
Figure 4 - Rendering scenarios
1) and 2) can be done based on
AffineTransform
, which we will discuss next. 3) draws a part of the source image to the client area using GC's
drawImage
: drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight,int destX, int destY, int destWidth, int destHeight)
which copies a rectangular area from the source image into a destination rectangulararea and automatically scale theimage if the source rectangular area has a different size from the destinationrectangular area.
Mindnode 2 – delightful mind mapping 2 3. If we draw the image directly on the screen, we need to calculate the gaps in4) and fill them. Here we make use of doublebuffering, so the gaps will be filledautomatically.
We use the followingapproach to render the image: We save only the source image. When the canvas needs to update the visible area,it copies the corresponding image area from the source image to the destination area onthe canvas. This approach canoffer a very large zoom scale and save the memory, since it does notneed to save the whole big zoomed image. The drawing process is also speeded up.If the size of canvas is very huge, we could divide the canvas into several smallgrids, and render each grid using our approach; so this approach is to some extent scalable.
The Image Analyzer examplethat comes with Eclipse draws the wholezoomed image, and scrolls the zoomed image (which is saved by system) to the right place based on thescrollbar positions. This implementation works well for small images, or when the zoomscale is notlarge. However,for large-sized images and zoom scale greater than 1, the scrolling becomes veryslow since it has to operate on a very large zoomed image. This can be shown inImage Analyzer.
Now let's look at the code used to find out the corresponding rectangles in thesource image and the client area:
Line 3 to line 10 are used to find a rectangle (
imageRect
) in the source image, the source image insidethis rectangle will be drawn to the canvas. This is done by inversetransforming the canvas's client area to the image domain and intersecting it with the bounds of image. TheimageRect
of line 10 is the exact rectangle we need.Once we have got imageRect
,we transform imageRect
back to the canvas domain inline 11 and get a rectangle destRect
insidethe client area. The source image inside the imageRect
will bedrawn to the client area inside destRect
.After we get the
imageRect
of the sourceimage and the corresponding destRect
of theclient area, we can draw just the part of image to be shown, and draw it in the right place.For convenience, here we use double buffering to ease the drawing process:we first create a screenImage
and draw image tothe screenImage
, then copy the screenImage
to the canvas.Line 30 to line 32 are used to clear the canvas and reset the scrollbar whenever thesource image is set to null.
Line 5 to line 7 are used tofind a better point to start drawing the rectangular image, since the transform may compress orenlarge the size of each pixel. To make the scrolling and zoomingsmoothly, we always draw the image from the beginning of a pixel. This also guaranteethat the image always fills the canvas if it is larger than the canvas.
The flowchart of rendering is as following (Figure 5):
Figure 5 - Rendering flowchart
In the code above, we use
inverseTransformRect()
in line 3 and transformRect()
in line 11 fortransforming rectangles between different domain. We will discuss them in detail inthe next section.Transformations
When we say scrolling in thissection, we mean scrolling the image, not the scrollbar thumb (which actually movesin the opposite direction).
Our primary goal is to develop a canvas with scrolling and zooming functions. Todothat, we must solve the following problems:
- How to save the scrolling and zooming parameters.
- How to change the scrolling and zooming parameters.
- How the scrolling and zooming parameters control the image rendering.
Scrolling and zooming entails two transformations: translation and scaling (seeFigure 6).Translation is used to change the horizontal andvertical position of the image; scrolling involves translating the image in thehorizontal or vertical directions. Scaling is used to change the size of image;scale with a rategreater than 1 to zoom in; scale with a rate less than 1 to zoom out.
Figure 6 - Translation and scaling
SWTImageCanvas
uses an AffineTransform
tosave the parameters of both the translation andthe scaling. In this implementation, only translation and scaling areused. The basic idea of AffineTransform
is to represent the transform as a matrix andthen merge several transforms into one by matrix multiplication. Forexample, a scaling S followed by a translation T can be merged intoa transform like: T*S. By merging first and thentransforming, we can reduce times for transformingand speed up the process.SWTImageCanvas
has an AffineTransform
instance transform:AffineTransform
providesmethods to access the translation and scaling parameters of an affinetransform:To change the
AffineTransform
, we can either reconstruct an AffineTransform
by merging itselfand another transform, or start from scratch. AffineTransform
providespreConcatenate()
and concatenate()
methods, which can merge two AffineTransform
sinto one. Using these two methods, each time the user scrolls orzooms the image, we can create a new transform based on the changes (scrollingchanges translation and zooming changes scaling) and the transform itself. Themerge operation is matrix multiplication. Since 2D AffineTransform
uses a 3x3 matrix, so the computation is very cheap. Forexample, when the user scrolls the image by tx in the x direction andty in the ydirection:
To construct a scaling or translation transform from scratch:
Once you have an
AffineTransform
, the transformation can be easily done.To transform a point:Simple Picture Viewer
To get the inverse transform of a point:
Since we use only translation and scaling in our implementation,transforming a rectangle can be done by first transforming the top-left point,and then scaling the width and height. Albumstomp 1 55 – a powerful album design appealing. To do that, we need to convert an arbitraryrectangle to a rectangle with positive width and length. The following codeshows how to transform an arbitrary rectangle using
AffineTransform
(the inverse transform is almost the same):The
absRect()
function in line 3 is used toconvert an arbitrary rectangle to a rectangle with positive width and height.For more detail about
AffineTransform
, you canread theJava API document from SUN website.AffineTransform
also supports shear and rotation. In thisarticle, we only need translation and scaling. AffineTransform
is widely used in the AWT'simage packages, and it has no relation with UI event loop, so it can be used inSWT. (Even if AffineTransform
were unavailable, we could easily replace or rewrite it since we only use the translation andscaling).Hot Simple Image Viewer 1 3 Free
We have seen how we save the scrolling and scaling parameters in
AffineTransform
,and how we can change them. But how do they control the image rendering?Figure 7 - Scrolling and zooming diagram
The basic idea is shown in Figure 7. When the user interacts with GUI(scrollbars and toolbar buttons), her/his action will be caught by Eclipse, Eclipse willinvoke the listeners (for scrollbars) or delegates (for toolbar buttons) to change the parameters inthe transform,then the canvas will update the status of scrollbars based on the transform,and finally it will notify itself to repaint the image. The painterwill consider the updated transform when itrepaints the image. Forexample, it will use transform to find out the corresponding rectangle in the sourceimage to the visiblearea on the canvas, and copythe source image inside the rectangle to the canvas with scaling.
Let's take a look at some methods which use
AffineTransform
to translate and zoom images.First let's see how to show an image at its original size:
Here we first change transform in (defaults to a scaling rate of 1, and no translation), and then call
syncScrollBars()
to update thescrollbar and repaint the canvas. It's that simple.Now let's try another one - zooming. When we zoom the image, we will zoom it around the center ofthe clientarea (centered zooming). The procedure for centered zooming is:
- Find the center of client area: (x,y).
- Translate the image by (-x,-y), so that (x,y) is at the origin.
- Scale the image.
- Translate the image by (x,y).
The syncScrollBars() (see next section) guarantees that the image will be centered in the clientarea if it is smaller than the client area.
Steps 2-4 can be used to scale images around an arbitrary point (dx,dy).Since the same steps will be used by many other methods, we put them in the method
centerZoom(dx,dy,scale,af)
: Now the code for
zoomIn
is:Here the (
dx
,dy
) is the zooming center, ZOOMIN_RATE
is a constant for incremental zooming in. centerZoom()
will also callsyncScrollBars()
to update the scrollbar and repaint the canvas.Scrollbar synchronization
Each time user zooms or scrolls the image, the scrollbars need to updatethemselves to synchronize with the state of image. This includes adjusting the position and the size of thethumbs,enabling or disabling the scrollbars, changing the range of the scrollbars, andfinally notifying the canvas to repaint the client area. We use
syncScrollBars()
to do this:If there is no image, the paint listener will benotified to clear the client area in .
If there is an image to show, we correct the current translation to make sure it's legal (<=0).Thepoint (
tx
,ty
) in corresponds to the bottom-left corner of the zoomed image (see the right-handimage in Figure 4), so it'sreasonable to make it no larger than zero (the bottom-left corner of the canvasclient area is (0,0)) except if the zoomed image is smaller than the clientarea. In such a situation, we correct the transform in so that it will translate theimage to the center of client area. We change the selection in and the thumb size in ,so that the horizontal scrollbar will show the relative position to the wholeimage exactly.The other lines between and set the GUI parameters for the horizontal scrollbar, you can change them tocontrol the scrolling increment. Theprocess for the vertical scrollbar is exactly the same, so we don't showit here. Lines betweenand create a new transform based on the corrected translation andthe scaling and update the old transform. Finally, line notifies the canvas to repaint itself.Rotation
Joe Winchester's Taking a look at SWT Imagesexplains pixel manipulation ingreat detail. Herewe will show how to rearrange the pixels to get a 900 counter-clockwiserotation. In order to demonstrate how otherclasses can interact with
SWTImageCanvas
, we putthe implementation in the PushActionDelegate
class. The basic steps for our rotation are:- Get image data from
SWTImageCanvas
. - Create new image data and rearrange the pixels.
- Set new image data back to
SWTImageCanvas
.
The code in
PushActionDelegate
for rotation is:The code for
setImageData()
is:Image Viewer Free
Since we won't change the pixel value, we needn't care aboutthe RGB of each pixel. However, we must reconstruct a new
ImageData
object with different dimension. Thisneeds different PaletteData
in and for different image formats. creates a new ImageData
and sets the value of each pixel. setImageData()
in will dispose the previous sourceImage
and reconstruct sourceImage
based on the new ImageData
, then update the scrollbarsand repaint the canvas. We put setImageData()
inside SWTImageCanvas
so it could be usedby other methods in the future.Plug-in Implementation
We have known how the image canvas works. Now, let's talk briefly about how to implement the plug-in.
Step 1. Create view plug-in
Follow the steps 1-3 in Creatingan Eclipse View, we can create a plug-in with asingle view. The plugin.xml is:
The
ImageViewerPlugin
and ImageView
are as following: declares an instance variable
imageCanvas
to point to an instance of SWTImageCanvas
,so that other methods can use it. creates an SWTImageCanvas
to show the image.When the view gets focus, it will set focus to imageCanvas
in .The dispose method of SWTImageCanvas
will be automatically called in whenever the view is disposed.Step 2. Add viewActions extension
The image viewer view has five local toolbar buttons: . Totake the advantage of Eclipse, we contribute to the
org.eclipse.ui.viewActions
extension point by adding the following lines to plugin.xml:Hot Simple Image Viewer 1 3 Download
The delegate class
PushActionDelegate
in will process all the actions from thetoolbar buttons. It is defined as following:Hot Simple Image Viewer 1 3 +
This class implements the
IViewActionDelegate
interface. It has a view instance in .It gets the view instance during the initialization period,and later in it uses the view instance to interact with the SWTImageCanvas
. Summary
We have shown the detail on how to implement a simple image viewer plug-in forEclipse. The
SWTImageCanvas
supports scrollingand zooming functions by using AWT's AffineTransform
. It supports unlimitedzoom scale and smooth scrolling even for large images.Compared with the implementation of Image Analyzer example, this implementation isboth memoryefficient and fast.
The
SWTImageCanvas
can be used as a baseclass for rendering, scrolling, and scaling image.Shortcut keys are a must for usable image viewers. In the interest of space, we did not showthis here; however, they can be easily added.
Acknowledgements
I appreciate the help I received from the Eclipse mailinglist; the Eclipseteam's help in reviewing the article; Pengtao Li's photo picture; andfinally the support from RCH lab at theUniversity of Kentucky.
References
Creatingan Eclipse View. Dave Springgay, 2001
Taking a look at SWTImages. Joe Winchester, 2003
The Java Developer's Guide to ECLIPSE. Sherry Shavor, Jim D'Anjou, ScottFairbrother, Dan Kehn, John Kellerman, Pat McCarthy. Addison-Wesley, 2003
Taking a look at SWTImages. Joe Winchester, 2003
The Java Developer's Guide to ECLIPSE. Sherry Shavor, Jim D'Anjou, ScottFairbrother, Dan Kehn, John Kellerman, Pat McCarthy. Addison-Wesley, 2003
Menu
Introduction
Simple, minimum, yet configurable photo viewer/slideshow/digital signage software for Windows, Linux, and macOS. Inspired by feh.
Download:
Windows version is available at the Microsoft Store.
Feature:
- Multiple viewing styles: 1. Normal window view, 2. “Windowless” view with slideshow, and 3. Fullscreen view with slideshow.
- Full keyboard and mouse playback control.
- Configurable options with command line parameters and popup menus.
- Supports multiple moniters.
Usage:
Image Viewer can be launched by (1) double clicking the executable and selecting image files or (2) selecting image files or folders in the explorer, and using “send to” feature in Windows explorer (create “shortcut” file and place it to “shell:sendto” folder) or (3) command-line.
Screenshots:
Normal View (on Windows)
Normal View (on Ubuntu)
Normal View (on macOS)
Windowless View (with slideshow) on Windows 10
Windowless View (with slideshow) on macOS
Command-line options:
Image Viewer can be also launched via command-line, meaning other applications or scripts can launch Image Viewer with following options.
Simple Photo Viewer Windows 10
- Slideshow interval in seconds (default 4 seconds):
-i 4
or--interval=4
- Slideshow random (default on):
-r on
or--random=on
-r off
or--random=off
- Slideshow repeat (default on):
-e on
or--repeat=on
-e off
or--repeat=off
- Slideshow start fullscreen (default off):
-f on
or--fullscreen=on
-f off
or--fullscreen=off
- Slideshow transitional effect (default on):
-t on
or--effect=on
-t off
or--effect=off
- Picture stretch In (fit to window/screen when the size is bigger than window/screen. default on):
-i on
or--stretchIn=on
-i off
or--stretchIn=off
- Picture stretch Out (fit to window/screen when the size is smaller than window/screen. default off):
-o on
or--stretchOut=on
-o off
or--stretchOut=off
- Load pictures in the sub folders as well when manually open a picture (default on):
-u on
or--includSubFolders=on
-u off
or--includSubFolders=off
- Specify a moniter to show fullscreen slideshow (default 0 is the main moniter):
-m 1
or--moniter=1
- Specify window should stay on top (default off):
-y on
or--stayOnTop=on
-y off
or--stayOnTop=off
- Help shows About dialog.
-h
or--help
Command-line Useage example:
$ ImageViewer -i 2 -f on -o on -e off C:Users<USER>PicturesWallpapers
Compiled and tested on:
- Windows 10 (64bit): Lazarus 1.8.0 r56594 FPC 3.0.4 x86_64-win64-win32/win64
- Ubuntu 17.10 (64bit): Lazarus 1.8.0 rc4+dfsg-1 FPC 3.0.2 x86_64-linux-gtk2
- Ubuntu 16.04 LTS (64bit): Lazarus 1.9.0 trunk, FPC 3.0.4
- macOS 10.13.3 (64bit) High Sierra: Lazarus 1.8.0 rexported FPC 3.0.4 i386-darwin-carbon
- macOS 10.11.6 (64bit) El Capitan: Lazarus 1.9.0 carbon trunk, FPC 3.0.4