Automate it!

It's sound human nature to avoid doing repetitive tasks. jAlbum was once developed as I didn't want to manually prepare 120 images for the web and create the needed html. Even if jAlbum has a good number of batch processing features, you may find yourself doing manual repetitive work, for instance deleting 1-star images, looking for broken links, renaming files, changing comments or looking for certain images (panoramas for instance). If there is ANY pattern to the work you're doing, then you can automate it using jAlbum's flexible scripting environment. Your aim might not even be to create a web gallery but simply to give your images more descriptive names than "IMG_6624.JPG". How about letting jAlbum rename such images in the format cameraModel+location for instance? I mean, a file called "iPhone SE-New York-7.JPG" tells me A LOT more than "IMG_6624.JPG", don't you agree?

With jAlbum's scripting environment (Tools->System console), you can automate such tasks with only a few lines of code, preferably in the easy-to-learn Groovy language or JavaScript. Long running tasks will automatically pop up a progress indicator allowing you to abort the task, and most operations (not deletions) can also be undone in one go if you change your mind.

Without further ado, let's go through some examples (Nothing beats learning by example). The following scripts operate on all items of the currently opened project, but they can easily be modified to operate on the current folder only, or selected items/objects only (see further down). To try these scripts, copy and paste them to the upper panel of jAlbum's system console (one at a time), then hit the Execute button (CMD/CTRL+E) to execute them (you can also select a part of a script to execute and hit Execute). The result is printed to the lower panel.

Here are some examples to glance at, explanation follows:

 

Sample scripts (Groovy language, requires jAlbum 22)

// Exclude 1- and 2- star images
Work.on(rootFolder.descendants)
.forEach(ao) -> {
    if (ao.rating == 1 || ao.rating == 2) {
        ao.included = false;
        println ao
    }
}

 


// Change 4-star images to 5 stars
Work.on(rootFolder.descendants)
.forEach(ao) -> {
    if (ao.rating == 4) {
        ao.rating = 5
        println ao
    }
}
 

 

 // Exclude videos
Work.on(rootFolder.descendants)
.forEach(ao) -> {
    if (ao.category == Category.video) {
        ao.included = false;
        println ao
    }
}

 


// Find broken links
Work.on(rootFolder.descendants)
.forEach(ao) -> {
    if (!ao.file.exists()) {
        println ao.file
    }
}

 
I hope you find this fairly intuitive. Let's break it down:

  • "Work" is the Java class that's responsible of most of the "plumbing" in these scripts (boring common code): It handles the processing of multiple objects (of any kind actually) and can even process multiple objects simultaneously. In case processing takes time, it pops up an abortable progress dialog. The executed operations are grouped in "undo groups" so it's enough with one (or a few) undo operations to undo all operations. Finally, "Work" makes it easy to prompt the user before action starts and report results.
  • ".on()" - This method tells Work what objects to work on. It can be either an array, List or Stream of objects (i.e. images, videos etc). Typical arguments are as follows:
    • rootFolder.descendants - All objects in the current project
    • currentFolder.children - All objects in the current folder
    • currentFolder.descendants - All objects under the current folder (i.e. including sub folders)
    • selectedObjects - The selected objects
    • TreeCollection.of(selectedObjects) - Selected objects AND their descendants (sub folders)
Note: Excluded objects are skipped when referring to "descendants". To also include these, refer to the TreeCollection API.

  • forEach(ao) - Code to execute for each encountered object. "ao" is a shorthand for AlbumObject - the API used to interface with objects of a project. Check out the documentation for this API in order to know what operations you can perform on each object.


Let's move on with slightly more complex things. Here's first a script that demonstrates how to pass a filtered stream of objects to Work. In this case 1-star rated objects. This script also prompts the user before proceeding and finally shows a result dialog:


// Delete 1 star images. Prompt user and print result
Work.on(rootFolder.descendants.stream().filter(ao -> ao.rating == 1))
.ask("Ok to delete all 1 star images?")
.forEach(ao) -> {
    ao.delete()
}
.showResult()



// Find links
import se.datadosen.io.LinkFile
Work.on(rootFolder.descendants)
.forEach(ao) -> {
    if (ao.file instanceof LinkFile) {
        println ao.pathFromRoot
    }
}


This following script uses the gotoPath() method to navigate the user to the first object found that has a broken link. It also demonstrates how to abort further processing once this first broken link is found:

 

// Goto first broken link
Work.on(rootFolder.descendants)
.forEach(ao) -> {
    if (!ao.file.exists()) {
        window.albumExplorer.gotoPath(ao.pathFromRoot)
        window.toFront()
        throw new OperationAbortedException()
    }
}

 



// Print images and their sizes
Work.on(rootFolder.descendants)
.forEach(ao) -> {
    if (ao.file.exists() && ao.category == Category.image) {
        println ao.pathFromRoot + ": " + ao.ImageInfo
    }
}



// Find panoramas (i.e. images having a width 2 times the height or more)

Work.on(rootFolder.descendants)
.forEach(ao) -> {
    if (ao.file.exists() && ao.category == Category.image) {
        if (ao.imageInfo.width >= ao.imageInfo.height * 2)
        println ao.pathFromRoot
    }
}



// Replace texts in comments. Look for "Adria" and replace with "Kabe"
Work.on(rootFolder.descendants)
.forEach(ao) -> {
    ao.comment = ao.comment.replaceAll("Adria", "Kabe")
    println ao
}



Here's finally a pretty powerful file renaming script: It uses an online location service to map GPS coordinates embedded within images to rename images to the format cameraModel-Place-number. As looking up locations based on GPS coordinates over an external service may be time consuming, this script uses the parallelStream() call to process objects in parallel, and because of the parallelism, we're using an AtomicInteger as number counter to get truly unique numbers for each file:


// Rename files by camera model and place
import java.util.concurrent.atomic.*
counter = new AtomicInteger(1)

Work.on(rootFolder.descendants.parallelStream())
.forEach(ao) -> {
    if (ao.category == Category.image) {
        PlaceService.Place place = PlaceService.instance.getPlace(ao)
        if (place != null) {
            ao.name = ao.vars.cameraModel + "-" + place.name + "-" + counter.getAndIncrement()
        }
    }
}


 Save scripts as "Tools"

If you've made a handy script that you'd like to execute several times, put it into a text file named "preferred name.groovy" and place that file under a "tools" sub directory of jAlbum's "config" directory (See Tools->Open directories->Config directory). Now this script can be executed under the Tools->External tools menu (requires a restart to show up). You can find more useful "External tools" under the "tools" folder of jAlbum's program directory. Inspect these for more inspiration.


I hope this inspires you to investigate the power that lies within jAlbum's scripting environment. You'll find more developer help in our developer center. If you get stuck, post questions to our forum. If you make an awesome script you think others would appreciate, share it in our forum.

What's new on the skin development front?

While we often communicate what’s new with jAlbum, only a few of you follow the advancements in skin development by reading those hidden skin update logs. Here you are some of the most interesting new skin features.

It all started with Story skin, which made custom pages even more useful, by allowing them holding just any (textual) content. This combined with the ability to mix them into the images allowed authoring complex, blog-like webpages, that barely resembled the conventional, square thumbnail grid galleries.

This change, however, made custom pages look broken after changing skins. I realized this when I made a modern sample album, but it turned ugly playing with skins. I guess this is what most new users do too, and might hit user experience badly.

So I revisited all of the bundled skins and modernized them. Tiger skin is still to be done, but Animatics, Lucid, Photoblogger, Projector and Story has received substancial updates recently. Besides changing the custom page layout a lot of other improvements were implemented. Some of these were deep changes like an organ transplant. Hopefully this will result in up-to-date skins, matching modern browser design, that will be also easier to maintain in the future. Here are some of the highlights:

Instant preview on the User Interface

After discovering small browser windows can be embedded into the user interface, I started adding this component to my skins. This makes the effect of certain skin settings instantly comprehensible, saving a lot of guesswork for users.

Custom pages

Embedding custom pages into the index page is now possible with Photoblogger skin too. In the future this possibility will also be added in Projector and Tiger skins.

Embedded custom pages in Photoblogger (embedded). See the same in Story skin!

New custom pages: Calendar and Newimages are now available with all these skins. Calendar collects all images into a calendar-like layout with links to the original folders, while Newimages collect all images created (or modified) within a timeframe. Let me remind you these custom pages work the best placed at the top level, and instead of renaming the file, it’s much better using Title to provide any text as title, e.g. “New images”, which is grammatically correct.

Calendar custom page (embedded)

New images custom page

Optimizations

Such complex pages are hard to load for the browser, so the new updates brings optimizations for quicker and device-specific loading of gallery pages. For instance the skin now preloads the icon fonts and the folder image, so it loads the page with less “Flash Of Unstyled Content” from now on. The thumbnail layouts got also optimized so they don’t jump aroud while loading in Story and Photoblogger skins. I fixed the progressive load function too, which also makes the page be ready much earlier.

Cross-skin translation tool

In order to have more skins receive the most localizations I made a handy tool that gathers texts from other skins, so it saves time for translators. Also helps me finding all the texts used in the source files.

Comments are welcome,

Laza

Presenting jAlbum 23

jAlbum 23 is here, listing a whopping 17 improvements and 15 bug fixes. As always you'll find the full list in our release notes. Here I'll try to give you an overview of the most notable improvements.

Performance

Don't you just hate it when software grows larger and slower over time? We do. Every now and then we therefore revisit the code to see whether it can be made more performant. It's mainly about two things: Doing less (repetitive) work, and doing more work at the same time. People aren't good at this, but computers should, especially if they have multi-core CPUs. You'll find that jAlbum 23 responds faster when opening projects and navigating folders due to better use of multiple CPU cores. We estimate around 30-50% improvement on a 4 core CPU (MacBook Pro 2015). The album making process has also been revisited to eliminate "warm up" costs when doing repetitive album builds: We now keep the script engine between album builds and also keep cached compiled copies of all scripts. We've also gained around 20% better album making performance due to better parallelism (updating a huge "Tiger" skin project). Finally, image filter processing is now also done in parallel to achieve better performance.

Improved image ordering

One guiding principle in user interface design is to not surprise the user. Here I have to admit that we've failed when it comes to image ordering, especially in relation to drag and drop. jAlbum hasn't always positioned newly dropped items exactly where you dropped them, and after a screen refresh, they might have been reordered to match the folder's sort order, but was this expected? Sometimes jAlbum will change the sort order, but was this expected? jAlbum 23 tries to behave in a more predicable manner and give you more control at the same time.

Before explaining further, let me just quickly explain how image ordering in jAlbum works: Historically, jAlbum provided one type of sort order for the whole album (by camera date, alphabetically etc). This is controlled under Settings->Pages and is referred to as "jAlbum ordering". Later, we added folder specific ordering. This ordering can either be in accordance to the global "jAlbum ordering" or something else, like "Camera date ordering". There's also "Custom ordering" which simply means "You decide by drag and drop". Folder specific ordering is controlled under View->Order by.

 So what's new? Apart from fixing bugs, jAlbum now introduces two methods of dropping new files onto a folder. The first method, the "specific drop" positions the newly dropped files exactly where the caret so indicates. This also switches the sort order to "Custom ordering" in order to respect your choice. The switch will be hinted with an animated text so you shouldn't be surprised that the sort order changed. The second way of dropping positions the newly dropped files in accordance with the folder's current sort order. You'll get this behavior if you either drop files onto a folder (either in the folder tree or in the Explorer area) OR if you drop files into the margin area of the Explorer view. This mode is indicated by a "drop rectangle" appearing over the Explorer area instead of a caret. This is actually better explained by this short video. View it!

Click to view video

Specific location drop vs folder order drop

Last used tool

Among the new features of v23 I'd like to highlight the "Last used" tool. This little efficiency enhancer remembers the tool you last executed and binds it to the CTRL/CMD+L keyboard shortcut or Tools->Last tool menu. If you find yourself repeatedly executing a certain tool over a range of images, say straightening several images or adjusting the camera date of several images, then this is a time saver!

 

Bug fixes

Fixing bugs is as (if not more) important as introducing new features. v23 has over 15 fixes. The most notable one being support for Mac OS "Big Sur". I'm also particularly happy that we spotted an ancient bug that caused occasional script errors during album making, typically triggered by instantly making an album after switching skin, which happens if you keep jAlbum's preview window open while switching skin.

 

I hope you're eager to install jAlbum 23. We've arranged 30 new trial days to everyone so you have a good chance to evaluate it. Also remember that this is a free update to anyone who is on a current support & update plan (See Help->About). Download jAlbum 23 today!

 

8 reasons to update to jAlbum 22

In the past 18 years we have never stopped improving jAlbum. The last two years are no exceptions. Here we present what we think are the top 8 reasons to update jAlbum based on recent improvements.

1

Be compatible

The world around us is changing, so are web standards and the use of mobile devices. Today, more than 50% of jAlbum galleries are viewed from mobile devices. Ensure your galleries play well on mobile devices too by using current skins like Tiger, PhotoBlogger, Lucid, Animatics or Projector.

2

Look good

Design evolve too. Ensure your gorgeous images are presented using modern sleek design. Add styling to your image descriptions without HTML knowledge using jAlbum’s embedded visual HTML editor.

3

Save work

Don’t get lost among hundreds of settings. Find the right setting, project or image in a snap using jAlbum’s Search Bar. Enjoy the instant preview offered in our latest skins. Use the new Project Gallery to visually browse web preview thumbnails of your projects.

4

Save time

jAlbum has a Rewritten upload engine providing faster and more robust uploads. We’ve made performance enhancements to both the user interface as well as album making. jAlbum can also make and upload multiple album projects in the background while you continue working with it.

5

Work better

jAlbum’s improved review mode helps you select, compare and rate your top images. The new Details editor gives you better overview of and allows edits to the metadata of your choice

6

Get it right

Use jAlbum’s integrated Multilingual spell checker so your image descriptions are free from typos

7

Save frustration

Don’t fight old bugs or user interface quirks. Update jAlbum to have them fixed. If you still encounter one, write us so we can fix it. jAlbum’s user interface has undergone many small, but important changes over the years that also saves you time and frustration.

8

Save money

Well, almost ;-). We just lowered the prices 20%. On top of that, you get an additional 30% discount for being an existing licensed user. Now’s a good time to upgrade to jAlbum 22!

Check out our new prices!

jAlbum 22 highlights

Syntax highlighting and the new Multi Maker

jAlbum 22 is here and comes with 17 improvements and bug fixes. Here are 3 improvements I think are especially welcome:

The new Multi maker

Ever wanted to be able to continue using jAlbum while making albums in the background? Ever wanted to make and upload several albums in one go? This has actually been possible via the rather hidden “Batch make album” external tool, but with jAlbum 22, this functionality is now improved and added as an integral part of jAlbum. Just open it via Tools → Multi maker and select the projects to make and possibly upload too, then hit the “Make selected” button. You can now minimize this window while jAlbum is working and continue using jAlbum.

Syntax highlighting

The album- and image descriptions you enter don’t need to be plain text. They can be formatted in html to get the styling you want, or perhaps add a link? jAlbum 22 now assists you getting the html syntax right by colouring various elements for you as you type. If you don’t know any html, just use the new embedded visual html editor (click the eye button in the top-right corner of description fields).

Updated html editor

Talking about the embedded html editor. With v21 we added visual html editor to assist styling your description texts. This editor did however not play well with existing html text, so with v22 we’ve listened to critisism and replaced the underlying code library with one that respects whatever html formatting you’ve already added (Squire). Enjoy

 

Try jAlbum 22!