Image Viewer
I have an old laptop at home, which over the years has taken quite a beating and has everything (including the kitchen sink) installed on it. As a result, it now takes the best part of 30 minutes just to boot up. I don't want to re-format the drive and re-install windows as there is a bunch of files and applications that I may need in the future and as I only really use it now for web-browsing and looking at photos, I decided to use Puppy Linux, a small, live CD linux distro, to breath new life into the machine.
However, there is no simple image browser installed in puppy‚ you know the kind of thing, file tree at one side, thumbnails the other and a big image view in the middle.
"Now here is a good 20 minute project for LiveCode"
I thought, so I set about writing such an application.
The basic application
What I wanted to create was a simple way to browse my photo collection, something that supported thumbnails (with a thumbnail cache for speed), folder navigation and was simple to use.
And this is what I came up with.
The code is very heavily commented, so that you can take it apart for yourself and see how each part works. Just open it in LiveCode, bring up the Application Browser, and study the scripts for each part of the Image Browser.
Rather than dissecting this application bit by bit I want to draw your attention to some of the concepts that are used.
* The use of templateImage.
* The creation of self-contained re-useable object groups
* Creating a thumbnail using import snapshot
* Using a "send " loop to allow responsiveness throughout the application.
The use of templateImage
Sometimes it is very useful to set up a set of default values that you wish any newly created object to inherit – for example to set some default width or heights. LiveCode allows you to do this by the use of the template objects.
Setting up the defaults on the templateImage (or any of the template LiveCode objects) allows you to specify default properties and behaviours for any newly created images.
set the width of the templateImage to 100
set the height of the templateImage to 100
set the showBorder of the templateImage to true
set the threeD of the templateImage to false
set the borderwidth of the templateImage to 1
set the locklocation of the templateImage to true
For more information about using template objects in LiveCode, see the Dictionary entries for templateImage, templateCard, templateGroup, and a number of other objects that have this property.
Creation of self-contained object groups
One of the most powerful aspects of LiveCode is the way that you can code self contained objects or groups of objects. In this application the thumbnail group on the right hand side is a good example.
The group itself contains all the scripting you need to manage thumbnails and provides a simple interface of two calls:
resetImages - Clears all the images from the thumbnails view
reloadThumbnails - Generates thumbnail images for any JPG, GIF or PNG image files it finds in the current folder, using any cached thumbnails if available
Designing an application in this manner means you can copy the thumbnail group onto a fresh stack and simply call those two methods and the group will manage everything else for you. You will also need to copy the "status" group which provides the status bar etc. To look at the entire script for this group, click on the group called "thumbnailView" in the Application Browser, and bring up the script by clicking on "Script" in the toolbar.
Creating a thumbnail using Import Snapshot
As you know, it is very easy to load images and resize them, and you would be forgiven for thinking that this is all that is required to create a thumbnail view of an image file. However, when you resize an image in LiveCode you still retain all the data that was in the original file. Although this will work, you will very quickly run out of memory if you try and load in thumbnails of a folder containing several hundred large images.
What we actually want to achieve is to create a thumbnail that just contains that actual data of the smaller, resized image. This file can then be written out to disk to create a thumbnail cache.
The easiest way to achieve this is to use the import snapshot command. Below you will find the main steps to achieve this.
1. Set the paintCompression. This specifies the compression format used for storing an image. By default, the global paintCompression property is set to "rle" in standalones and "png" in the development environment but we want it to be "png" in standalones too.
set the paintCompression to "png"
2. Create the new empty thumbnail image
create image in group "thumbnailView"
3. Create a temporary blank image of the correct size for the thumbnail
create invisible image "Foo"
4. Set the filename of the temporary image to the image on disk
set the filename of image "Foo" to tFile
5. The image will be automatically resized to fit the new temporary image
6. Create a snapshot of the temporary (resized) image
import snapshot from rect (the rect of image "Foo") of image "Foo"
7. Put the data of the snapshot into our thumbnail
set the text of image id tID to the text of the last image
8. Clean up after ourselves
delete the last image delete image "Foo"
9. Optionally, save the thumbnail image to disk cache
You can see exactly how I used this in the Image Browser, the script is at the bottom of the "thumbnailView" group script, in the function called "processImage". Again, you can look up import snapshot in the Dictionary for more information on how to use this versatile command.
Send message loops
When it came to processing the list of image files into thumbnails I did it first using a simple loop
repeat with line tFile in tFileList
However, doing things this way means that the application is locked up and unresponsive until all images have been processed – there is no-way to change folder, view an image or even cancel the listing until all files have been processed.
Luckily, LiveCode provides a simple way to loop through the list while still allowing responsiveness to other events, the "Send" message loop.
Firstly, the reloadThumbnails function starts the processing loop up by sending itself the "processImage" message right away, tFiles contains the list of image files
send "processImage tFiles" to me in 0 millisecs
The "processImage" handler processes a single image file into a thumbnail (as outlined in the section above). The last thing the "processImage" handler does is call itself using the "send" command but with a small delay. This delay allows LiveCode to process any other events that may have occurred, mouse clicks on the folder tree for example.
if pImageList is not empty then
send "processImage pImageList" to me in 25 millisecs
end if
Carles B.
I downloaded the demo of this lesson and it only shows the name of the folders.
Elanor Buchanan
Hi Carles,
There seems to be an issue using relative filenames for images, I have reported a bug and updated the example stack so it should now show the images.
Thank you for bringing this to our attention.
Elanor
Carles B.
Hi Elanor,
I downloaded the new version and on my Mac I continued without seeing the images. It recognizes the images that I have in the Desktop, 2 jpg and 1 png, but it does not show them.
Status: Updating the thumbnails - On item 3 of 3
Elanor Buchanan
Hi Carles
Looking at the code it only makes a new thumbnail if it can't find a thumbnail file. You might have some left from when the thumbnails were not being created correctly. Try deleting any hidden thumbnails, they will be in the same folder as the image file and will be named
._thumb
I also missed one place in the code where a relative filename was still being used for these existing thumbnails so I have uploaded a new example stack.
Thanks for bringing that to our attention.
Kind regards
Elanor
Chris Norman
When I build this out to a Mac standalone Application the thumbnails do not show up. Not sure if this is just a Mac thing, or the application's fault. Also I'd love to learn how to make these images show up with their correct aspect ratio. Right now (again, on a Mac) most images show up as squished or stretched.
Elanor Buchanan
Hi Chris
I just tested with a Mac standalone and it seems to work as expected. Can you see that the thumbnail files have been created? They will be in the same folder as the image file and will be named
._thumb
To maintain the aspect ration of the thumbnails you can add some code to the reloadThumbnails handler. At the moment the width and height of the templateImage are both set to 100, you can add some code to set work out the original aspect ratio of the image and set the width and height of the thumbnail to reflect this.
I hope that helps.
Kind regards
Elanor
Jon Adams
Hello, I was just utilizing this great tutorial to build something similar. It works great for me in Livecode but no thumbnails show up in a standalone Mac or PC. So I thought to download the stack and build it as a standalone and I'm getting the same results Livecode 9.5.1 Indy. It generates the _thumb file but there is no information in it 0kb on disk. Is this possibly something I'm doing wrong in the standalone? Has something changed in Livecode that broke this system of making thumbnails? Is there another way of making thumbnails that is as efficient as this? Thanks so much!
Elanor Buchanan
Hi Jon,
Thanks for noticing this. This is happening because the default value of the paintCompression property is different in the development environment and standalones. Adding the line
set the paintCompression to "png"
At the start of the processImage handler should make the standalone work correctly. I have updated the lesson and the sample stack with this correction.
Kind regards
Elanor
Alan Perks
Win 10 with LC 9.5.1
The thumbnails displayed once. Then the selection of the photos location locked up. Closed LC and restarted, but although I can navigate to the photo location, the thumbnail column remains blank. The thumbnails are there though because the vertical slider appears and where the thumbnail should be, I can click and load the full photo.
Perhaps the coding is too smart for its own good.
For newcomers, it needs to be very simple, with buttons, and avoid hard to find routines buried somewhere in the stack.
Thank you for the insight.
tom H.
Your 'processImage' handler contains the statement "put tImageData into URL tCacheFile". You never set the variable, so your thumbnail files contain the text 'tImageData'. The second time your stack visits a folder, it builds a list of blank images.
If you change the statement to "put image id tID ...", you will create the real thumb files.
Panos Merakos
@tom
Thank you for spotting this. I have updated the sample stack attached to this lesson.
Kind regards,
Panos