Optimize all PNG images recursively

Windows batch file syntax sometimes is a pain compared to UNIX bash/sh. Using optipng I wanted to shrink all the PNG images in a directory and inside its subdirectories as well. Notice that I had to write the command into a .bat batch file, it did not work directly from the command line:

FOR /F "tokens=*" %%G IN ('dir /s /b *.png') DO optipng -nc -nb -o7 -full %%G

The optipng params -nc and -nb prevent any color and color depth changes of the png files. Those may change the appearance, for example in the evil Internet Explorer. -o7 means the best and slowest optimization and -full does a full scan of the IDAT part. Using UNIX the same job may look like:

find . -name *.png | xargs optipng -nc -nb -o7 -full

HDR Panorama Tutorial

Stitching panorama pictures from a series of taken photos is simple, besides of buyable software like Panorama Studio or Autopano there’re even free alternatives like Microsoft ICE. But what if you have three series of pictures for the panorama – each serial taken with a different exposure time? With single images it’s easy to merge the images into an HDR image by using Photoshop or Photomatix for example. But combining both techniques into a HDR panorama is a little tricky, hence I wrote this tutorial with a solution that worked for me.

Autopano Giga and HDRs

The “Giga” version of Autopano supports working with multiple exposure series. So my first idea is to just apply the Autopano workflow to all the pictures that will belong to the panorama. There’re 12 pictures in my case and Autopano automatically sorts them into 4 panorama parts (4 views รก 3 different exposure times).

Now I just apply the detection and change to the editing mode of the resulting panorama. There I choose not to apply any color correction (I want to tone map the HDR later anyway) plus I crop the borders. Notice the layer setting to output only one blended layer.

Now I just render the panorama with one target .hdr file.

So far so good. Next I open the hdr file I just created in Photomatix to do some tone mapping, but what’s this?

Seems like this does not work the way I want to. There’re many ugly blending errors and the light spots are all overspilled!

The workaround

Ok, back to Autopano’s edit panorama mode. In the layer section I now chose “Group by speed” as I want to get a separate panorama image for each exposure serial, but with exactly the same panorama stitching (the three panoramas have to match each other exactly, otherwise the later HDR generation in Photomatix would screw up the .hdr entirely).

Now again I render the panorama but not targeting one .hdr file. Instead I choose the 8Bits TIFF format. To get one TIFF per exposure serial I have to add a “%L” to the file name for the layer name.

Great, after exporting I get three TIFF images with the stitched panorama for each exposure serial.

HDR generation & tone mapping

The next step is as simple as I is with non-panoramic pictures. I just create a new panorama in Photomatix and deactivate the alignment tool (the panorama, taken using a tripod, is already aligned) and activate the ghost reduction for objects and people (this happens quite often with exposures lower than 5 seconds). Really important is to activate the noise reduction – otherwise the hdr will look like a Christmas tree. Finally, after applying the tone mapping and doing some little fixes in GIMP (sharpen, denoise, contrast), it’s a nice HDR panorama.

markt_tonemapped

Spread pages book layout in PDF documents

This week I composed a document with flyleaf and subsequent two-paged layout like in these two examples with Adobe Indesign and Microsoft Word:

But when exporting/printing to a PDF file the PDF document in Acrobat Reader shows only a single page at a time. One may manually select the view option with two-paged layout and flyleaf but I wanted the document to be always shown that way! After Googling I found a solution using Adobe Acrobat Pro where it is possible to set this option and save the changes directly to the PDF file. Unfortunately Acrobat Pro isn’t cheap and I don’t own a copy so I looked for an alternative.

Finally I found BeCyPDFMetaEdit by Benjamin Bentmann which is a small freeware Windows utility for changing the XMP meta data of a PDF document file. The viewer preference actually is just a XMP setting. The program can remove any application or pdf printer metadata as well (like “Created with …foo program” or “Printed using PDF…bar”). The result after opening the PDF document in Adobe Acrobat Reader then looks like (before vs. after):

Ta-da, A book!

Perl -e in Windows batch and Linux shell scripts

Recently I had to extract a partial string from a space-seperated list of names in a loop within a script. There have to be two versions of that script, one for Windows and one for Linux shell. To loop through one such list is quite easy, in Windows:

@echo off
SETLOCAL
set WEBSITES=Test1 Test2 Test3

FOR /D %%A IN (%WEBSITES%) DO (
echo WebsiteName=%%A
)
GOTO :EOF

ENDLOCAL

and in Linux shell:

WEBSITES="Test1 Test2 Test3"

for WEBSITE_ALIAS in $WEBSITES ; do
echo "Website= $WEBSITE_ALIAS ..."
done

But now came a second list of string into play containing the domain names of the website aliases:

WEBSITES="Test1 Test2 Test3"
DOMAINNAMES="www.test1.lan www.test2.lan www.test3.lan"

In a conventional programming language I would just use a for-loop with an index variable and utilize that variable to access both arrays within one loop. But in that batch/shell scripting this turned out to be quite tricky. My solution here was a small inline PERL script. For Windows:

set WEBSITE_UNIT=Unit4
set WEBSITES=Test1 Test2 Test3
set DOMAINNAMES=www.test1.lan www.test2.lan www.test3.lan
perl -e "use strict; die("argv mismatch!") if !@ARGV or scalar(@ARGV) < 2; my @Websites = split(/[s,;|]/, $ARGV[0]); my @Domains = split(/[s,;|]/, $ARGV[1]); die("number of aliases differs from domain names!") if scalar(@Websites) != scalar(@Domains); for(my $i=0; $i<scalar(@Websites); $i++) { system('perl dosomething.pl -user /Root/'.$ENV{'WEBSITE_UNIT'}.'/admin -passwd admin -servername '.$ENV{'SERVER_NAME'}.' -alias '.$Website[$i].''); system('perl doanotherthing.pl -user /Root/'.$ENV{'WEBSITE_UNIT'}.'/admin -passwd admin -alias '.$Website[$i].' DomainName="'.$Domains[$i].'"'); }" "%WEBSITES%" "%DOMAINNAMES%"

And for Linux:

WEBSITE_UNIT=Unit4
WEBSITES="Test1 Test2 Test3"
DOMAINNAMES="www.test1.lan www.test2.lan www.test3.lan"
perl -e 'use strict; die("argv mismatch!") if !@ARGV or scalar(@ARGV) < 2; my @Websites = split(/[s,;|]/, $ARGV[0]); my @Domains = split(/[s,;|]/, $ARGV[1]); die("number of aliases differs from domain names!") if scalar(@Websites) != scalar(@Domains); for(my $i=0; $i<scalar(@Websites); $i++) { system("perl dosomething.pl -user /Root/'${WEBSITE_UNIT}'/admin -passwd admin -servername ".$ENV{"SERVER_NAME"}." -alias ".$Website[$i].""); system("perl doanotherthing.pl -user /Root/'${WEBSITE_UNIT}'/admin -passwd admin -alias ".$Website[$i]." DomainName="".$Domains[$i]."""); }' "$WEBSITES" "$DOMAINNAMES"

Notice the different handling of the ticks and quotes and the different access to external parameters. In Windows there’s no difference in PERL’s $ENV hash whether accessing real environment variables or local variables set by the batch script. Not so under Linux: I can only access my system-wide exported environment variable SERVER_NAME using $ENV but not my local script’s WEBSITE_UNIT variable. When using the exec -e with perl for Windows I had to use quotes to wrap the execution PERL-code but for linux shell, I needed single -ticks which can NOT be used inside the PERL code – not event when escapting them like ‘. The single ticks are “reserved” by the shell script for being able to insert shell variables anywhere.

Disable auto word wrap in nano

Quite annoying when editing source code via console in nano is the automatic word wrap, which often screws up compilation of the edited file. To disable the word wrap, just edit the .nanorc in your home directory and add:

set nowrap

You can also do this when starting nano:

nano -w <file>