Scripting Saturday
Right now as I type this, the windows scripting host and Adobe Photoshop are interacting in the background of my computer making quick work of the 150 or so pictures which will be a part of this years slideshow.
I have used this script for several years now for a variety of purposes. It has always been a huge hack (ok, it still is), and I just kept pasting hard coded data / statements in the script to do what I wanted each year. This was the first year where I decided to edit the script to create a general purpose script that would work for me each time.
Of all things, the first thing I did was that while I was adding proper error codes (yes, in vbscript, you can exit with a correct error code… wscript.quit) to various initial error conditions. In the last 5 years or so, I have learned to get rather picky about my scripting (vbscript / batch) habits. Even at work when I write small scripts for use in automation, I try to follow any coding standards I can which would apply to native development. On a side note, I am now the office wiz at batch development and love using the for command as a general regex substitute in batch.
I have been either using or working on windows for at least 18 years and only in the last year at work have I found the “net helpmsg” command in windows. Currently at work, I need this command almost every day since there are hundreds of different error codes my component produces now with almost no clear way to know what they mean without feeding the error code number into this command. From what I can tell, for the most part, what this command does is translate known and existing errors which are in winerror.h into actual strings. There are other sources which get compiled into this tool however from across windows as well. (On a personal note, when this doesn’t work, I also recommend hrplus.)
I realized though that net helpmsg did not have a reverse function. For instance, I wanted my script to return errors like ‘folder does not exist’ or ‘invalid parameter’ but wanted to look up the standard errors for these. (At this point many of you would ask why I didn’t just search… the answer is because for whatever reason, the first thing I thought of was how to make my own lookup file.) So, beaming idea in my head, that is what I did. I whipped up this VERY short script to create a file with a list of the most common windows errors. (I have added comments to help with the logic. ;))
REM Clear and reset text file
echo Help File>Messages.txt
echo. >>Messages.txtREM Cycle through top 1000 errors
FOR /L %%i in (1,1,1000) do (REM This command is here simply to check
REM whether there is a valid error value
REM or not, errors piped to NUL
net helpmsg %%i 1>NUL 2>NULIF NOT ERRORLEVEL 1 (
REM Assuming we found an error
REM echo that number to the file
echo %%i>>Messages.txtREM Then echo the text matching
REM that number to the file
net helpmsg %%i>>Messages.txt
))
So, file at hand, I was able to find the error codes I needed. Somewhat a waste of time, but honestly its simple, quick, and fun solutions like this which keep me amused both at work and at home a lot. At work, they get way more complicated at times, but honestly, its about finding creative and fun solutions to easy and every day problems.
So after that was out of the way, I headed off to refine my Photoshop script. I should point out that, this script will not adjust the visual quality of your pictures. You could program it to do that for you, but what I have found over the years is that the composition of every image is different and color balance, highlights, noise reduction always takes a hand touch. So each year, I adjust all 100+ images in the slideshow by hand. I don’t make HUGE changes, but just try to clean up any crappy conditions I may have taken the picture in. The purpose of this script though is just to turn each picture into a 16x9 image for the slideshow (since the built-in movement scripts in the slideshow applications work better when all the images are the same size) and to cut them down to a more manageable size. I have found I can crash almost any slideshow app with panoramic pictures that are 70,000 pixels wide. With that said, here is the script I created. (You may re-use however you like, you may repost only with attribution, and this code is released ‘as is’ with no warranty or rights attached.)
Option Explicit
Dim NamedArgCount
NamedArgCount = WScript.Arguments.Named.Count
if ((NamedArgCount < 1) or (Wscript.Arguments.Named.Exists("Folder") <> True)) then
wscript.echo "This script takes a named argument to set the folder location."
wscript.echo "cscript SlideshowImages.vbs /Folder:""c:\Full_Path_To_Images"""'Invalid Parameter
wscript.quit 87end if
Dim FolderPathString
FolderPathString = Wscript.Arguments.Named.Item("Folder")Dim fsoRef, folderRef, outputFolderRef, f
Set fsoRef = CreateObject( "Scripting.FileSystemObject" )
if (fsoRef.FolderExists(FolderPathString) <> True) then
wscript.echo "Input Folder was not found!"
wscript.echo FolderPathString'Path not found
wscript.quit 3end if
Set folderRef = fsoRef.GetFolder( FolderPathString )
if (fsoRef.FolderExists(folderRef.Path & "\OutputImages")) then
wscript.echo "Output folder already exists!"
wscript.echo folderRef.Path & "\OutputImages"
wscript.echo
wscript.echo "Please rename or remove the existing folder."'File Exists
wscript.quit 80end if
wscript.echo "Found " & folderRef.Files.Count & " files in: " & folderRef.Path
wscript.echo
wscript.echo "Creating output path: " & folderRef.Path & "\OutputImages"
wscript.echoset outputFolderRef = fsoRef.CreateFolder (folderRef.Path & "\OutputImages")
wscript.echo "Detecting and Initializing Photoshop..."
wscript.echoDim appRef, startRulerUnits, startTypeUnits, startDisplayDialogs
Set appRef = CreateObject("Photoshop.Application")' Save the current preferences
startRulerUnits = appRef.Preferences.RulerUnits
startTypeUnits = appRef.Preferences.TypeUnits
startDisplayDialogs = appRef.DisplayDialogs
' Set Photoshop CS2 to use pixels and display no dialogs
appRef.Preferences.RulerUnits = 1 'for PsUnits --> 1 (psPixels)
appRef.Preferences.TypeUnits = 1 'for PsTypeUnits --> 1 (psPixels)
appRef.DisplayDialogs = 3 'for PsDialogModes --> 3 (psDisplayNoDialogs)Dim jpgsave
set jpgsave = CreateObject("Photoshop.JPEGSaveOptions")
jpgsave.quality = 9For Each f in folderRef.Files
if (LCase(Right(f.ShortName,3)) <> "jpg") then
wscript.echo "Skipping file:" & f.Name
else
wscript.echo f.path
dim documentset document = appRef.Open(f.Path)
dim h, w, newHeight, newWidth, resave
h = document.Height
w = document.Widthwscript.echo "Resolution: " & w & "x" & h & "(" & CStr(Round(w / h, 6)) & ")"
resave = false
if (Round(w / h,6) <> Round(16/9,6)) then
resave = true
if (Round(w / h,6) > Round(16/9,6)) then
newHeight = Round(w * (9 / 16),0)
newWidth = wwscript.echo "WIDE: " & CStr(newWidth) & "x" & CStr(newHeight)
else
newHeight = h
newWidth = Round(h * (16 / 9),0)wscript.echo "TALL: " & CStr(newWidth) & "x" & CStr(newHeight)
end if
document.ResizeCanvas newWidth, newHeight
else
Wscript.echo "Image is already 16/9, skipping canvas adjustment..."
newHeight = h
newWidth = wend if
if (newWidth > 3840) then
'Since many slideshow software does VERY badly / crashes on images
'which are more than 7000px wide, just cut these down to 4Kwscript.echo "LARGE: 3840x2160"
document.ResizeImage 3840, 2160resave = true
end if
if (resave) then
wscript.echo "Saving as: " & outputFolderRef.Path & "\" & f.Name
document.SaveAs outputFolderRef.Path & "\" & f.Name, jpgsave
end if' 2 == Do not prompt
document.Close(2)end if
wscript.echo
Next' Reset the application preferences
appRef.Preferences.RulerUnits = startRulerUnits
appRef.Preferences.TypeUnits = startTypeUnits
appRef.DisplayDialogs = startDisplayDialogs
Now that the pictures are just about ready to go (they are now all in the right format and ready to get put in the timeline) I need to settle on the soundtrack. My possible song options ballooned in the last few months and I have been re-considering the songs be listening to a playlist over and over again. You can check out the list here. Not all 39 songs can make it. Maybe only the top 6 or 7. They are listed on that page in the order in which I first heard them this year.
Honestly I have so many other topics I could sit down and write about here lately such as the article I want to write about Portland now (similar to my “J.P.’s Guide to Vegas”), but I just have not had the time lately. (Nothing there is new I guess.)
My photos from my recent trips to Phoenix and Portland are both online now. Many more in the later than the former.
I also found that over 90% of the images in this year’s slideshow happened to already be ‘lurking’ in my Flickr photostream from the year as well. So for the hell of it, I corralled them into a preview bucket. Of course EVERY image from all of my slideshows is neatly stored on Flickr still as well in this collection. Not to mention the collections I have specifically dedicated to Travel and Hiking/Biking as well. And as always, my moblog (perma-linked at the top of this page) is hosted on Flickr as well.
Have a very happy holidays everyone. Looked for a finished slideshow “soon” ;).