Friday, July 31, 2015

Deploying a website to Amazon S3

You've generated a great website that you now want to deploy to Amazon S3 to have hosted as a server. I assume you've set up an S3 bucket and configured it for website hosting. Now you have to transfer the files comprising your site to S3, and keep them up to date. You can do this manually with a GUI tool like CrossFTP or S3 Browser. But perhaps you have a few tweaks you'd like to make before you deploy it. Most importantly you'd like to have clients be able to make use of gzip compression when the site is served, since this can greatly speed up site loading, and also reduce your costs. And you can optimize/minify your images for websites. Finally, you need to set all the custom S3 settings you need (Cache-Control headers, Reduced redundancy storage, etc), in one step, reducing requests (and thus costs) and saving lots of time and hassle. And ideally, if you make changes to an existing site, you should only need to upload the files that have changed, again saving time and money.

Here, I present a script that can do all of this, using the convenient example of a generated Gallerific Web Album. This script takes considerably more technical skill relative to generating an album, since you will need to use a command line in the form of a bash shell to use it (which comes with MacOS, Linux, and you can get it with cygwin in Windows, as I use), but it's worth it!

To use it you'll need several tools:
  • s3cmd which is used for copying to/interacting with your S3 bucket. To install:
    • Linux: normally you can get the package as here.
    • Cygwin: get zip from github, run python setup.py install [which requires python-setuptools and to have run easy_install dateutil]
    • Mac via homebrew: brew update && brew install s3cmd
    • In all cases you must then run s3cmd --configure to provide your S3 access keys.
  • mozjpeg v3.0+ which is now the best tool for compressing jpegs for use on the web (available in binary form here). (Be sure that jpegtran/djpeg/cjpeg on your path is this one, and not the default libjpeg implementation.) Lossless compression rates of 60%+ are achieved on thumbnails, and 8-10% on larger images. (It is now as good or better than common online tools and better than things like jpegrescan and adept.sh by my testing.)
  • gzip, or optionally zopfli, for compressing text files as a traditional web server would do (zopfli produces files that are 4-8% smaller than gzip -9. Note that although 7zip also produces smaller files than gzip, it will not work with this script because the timestamp cannot be excluded and so MD5 signatures for files always change)

If you're curious, here is the script (deploy_to_s3):

#!/bin/bash
##################################################
# Deploys a gallerific gallery to the web server
##################################################
# Usage: deploy_to_s3 [directorytodeploy]
##############CONFIG##############################
S3_BUCKET=s3://mys3bucket
REDUCED_REDUNDANCY=-rr
ADD_HOME_LINK=1 # set 'pathtohome/index.html' as applicable
#GZIP_CMD='gzip -n -9'
GZIP_CMD=zopfli
JPEG_QUALITY=80  # lossless or number (recommend 65-85)
#S3CMD_DEBUG="-v --dry-run" # can use --dry-run on s3cmd to see the effects but not execute, also can use -v for verbose
##################################################

GALLERY_DIR=$1
GALLERY_DIR=${GALLERY_DIR%/} # remove trailing slash
if [ -z "$GALLERY_DIR" ] || [ ! -d "$GALLERY_DIR" ] ; then 
  echo Invalid Parameter. USAGE: deploy_to_s3 [directory to deploy] 
  exit
fi
DEPLOY_DIR=$(mktemp -d)
if [ $JPEG_QUALITY == "lossless" ] ; then 
  JPEG_CMD='jpegtran -outfile {}.tmp {}'
  JPEG_CMD2='mv {}.tmp {}'
else
  JPEG_CMD='djpeg -outfile {}.pnm {}' 
  JPEG_CMD2="cjpeg -quality $JPEG_QUALITY -outfile {} {}.pnm"
fi

cp -Rf $GALLERY_DIR $DEPLOY_DIR

if [ $ADD_HOME_LINK -eq 1 ]; then
  echo ADDING CUSTOM HOME LINK TO INDEX.HTML ...
  sed -i '/<div class="header"[^<]*>/ a <p><a style="color: #548BBF !important;" href="pathtohome/index.html">Home</a></p>' \
      $DEPLOY_DIR/$GALLERY_DIR/index.html 
fi

# compress text files and mark them for direct download by browsers using gzip encoding 
echo COMPRESSING TEXT FILES ...
find $DEPLOY_DIR -regex '.*\.\(html\|js\|css\|xml\|svg\|txt\)' -exec $GZIP_CMD {} \; -exec mv {}.gz {} \;
echo UPLOADING COMPRESSED TEXT FILES ...
s3cmd sync $S3CMD_DEBUG --acl-public $REDUCED_REDUNDANCY --add-header="Content-Encoding":"gzip" \
              --guess-mime-type --exclude='*' --rinclude='.*\.(html|js|css|xml)' --signature-v2 $DEPLOY_DIR/$GALLERY_DIR $S3_BUCKET/
echo
echo

# re-compress jpegs using mozjpeg encoder (https://github.com/mozilla/mozjpeg, http://mozjpeg.codelove.de/binaries.html)
echo IMPROVING COMPRESSION ON JPGS ...
# Note some EXIF/comments may be lost, particularly using lossy compression
#pushd/popd necessary because mozjpeg for windows doesn't handle roots (eg /tmp)
pushd $DEPLOY_DIR/$GALLERY_DIR
find im -regex '.*\.jpg' -exec $JPEG_CMD \; -exec $JPEG_CMD2 \;
find im -regex '.*\.pnm' -exec rm -f {} \; # clean up after lossy compression
popd
echo UPLOADING IMAGES AND REMAINING FILES ...
s3cmd sync $S3CMD_DEBUG --acl-public $REDUCED_REDUNDANCY --add-header="Cache-Control":"public,max-age=86400,no-transform" --guess-mime-type \
                --signature-v2 $DEPLOY_DIR/$GALLERY_DIR $S3_BUCKET/
echo
echo

echo REMOVING DELETED FILES ON S3 SIDE CLEANING UP TEMP FILES ...
s3cmd sync $S3CMD_DEBUG --delete-removed --acl-public $DEPLOY_DIR/$GALLERY_DIR/* $S3_BUCKET/$GALLERY_DIR/
rm -rf $DEPLOY_DIR
echo
echo
echo DONE!


To just use it as is, save the file  deploy_to_s3  and make it executable (chmod +x deploy_to_s3). Next you need to configure it:
  1. Set S3_BUCKET to point to your bucket
  2. If you wish to use gzip, uncomment the first GZIP_CMD line and comment the other.
  3. Before you run for real, I'd recommend uncommenting the S3CMD_DEBUG option to see what the effects would be but not execute them.
  4. I like to add a home link at the top of my pages. to do this set ADD_HOME_LINK=1 and change the path to your homepage in the html code (<p>...</p>) in the sed command.
  5. Choose the jpeg compression quality, either "lossless", or an integer typically 65-80.
  6. If you don't want to use reduced redundancy storage, comment out the REDUCED_REDUNDANCY option.
  7. Change what directories get image compression (currently im/ and subdirs)
To run, go to the parent of your gallerific web album's folder. Then simply execute:
deploy_to_s3 [mygallerificwebalbum]

A few notes/features:
  • If you re-generate the album or make tweaks, but only some files have changed, you can re-run deploy_to_s3 and only the files that have changed will be transferred (saving time and money again).
  • Only jpegs in the im directory will be compressed. Other images in gallerific web albums have already been minified. 
    • For use with gallerific, I recommend using lossy compression with this script, combined with very high quality settings when saving JPGs in Lightroom. This will lead to much smaller jpegs than using a lower quality setting in Lightroom combined with lossless compression here. For example, a full size image that I find to be acceptable quality for the web at 65% quality in Lightroom was 827kb. This can be losslessly compressed to 769k. However if the image is saved at 95% quality in Lightroom (effectively lossless) and compressed at 75% using mozjpeg, it occupies only 580kb and has approximately equivalent image quality. The only downside is potentially lost EXIF/comment data with lossy compression (and your local copy will be quite large - a perhaps more reasonable compromise if that is a concern is LR quality 92, mozjpeg 80). [Note that I've learned that LR jpeg quality for the Web is not the same as that used for normal LR export; it appears to be generally lower.]
  • HTTP headers are added so that browsers will recognize and get the gzip format compressed text files over the internet and use them as normal; you and users save significant time and bandwidth and the page loads faster.
  • The Cache-Control HTTP header is set to allow browsers (and CDNs/proxies) to cache all non-text (html/css/js/xml) files for 24 days, dramatically speeding reducing HTTP requests and subsequent views. But be aware that if you make changes to these binary files, users with cached files may not see them unless you rename the files.
Although it does take a bit of work to set it up, using this tool should save you and users enough time to enjoy a choice beverage, which you now deserve. So do!

Tuesday, July 21, 2015

Gallerific: A Modern HTML5 Lightroom Web Gallery

Latest update May 2016.  
 Also in Español, Français & Deutch.


This post is to announce the release of a powerful new Web Gallery plugin for Adobe Lightroom.

Like many photographers, I use Lightroom to manage my photos and do most of my adjustments, and it's just great. But when it comes to exporting them in an easily viewable way, I was shocked to realize how poor the options were. The included galleries are simply ancient; most of them use Adobe Flash, which is being phased out on the web, is slow and painful to use and is a security headache to boot. The rest use decade-old HTML code and produce web pages that are just plain painful to use. And searching around, I wasn't able to find any third-party web albums that worked reasonably well either, especially for larger sets of photos.

The free Gallerific HTML5 Web Gallery plugin is here to fix all of that and bring Lightroom web exports into the present.




Features:
  • Allows you to create great albums, with captions (or not), from the program you already use to manage your photos and metadata.
  • The entire web site is generated automatically, with multiple customization options. No special expertise is needed, but there are customization options for those wanting more control.
  • Albums are fast, responsive, and support large numbers of images (up to thousands, anyway).
  • Albums are standards-compliant, using Javascript, HTML5 and CSS3 - and no obsolete Flash! They should work well on any modern web browser or device, and have great backward compatibility too. They even work minimally if your browser doesn't support Javascript.
  • Albums follow modern responsive web design principles, automatically adapting to the size of the web browser or mobile display.
  • Images can be navigated by mouse or touch screen (including by swiping), or by using keyboard shortcuts (Left/Right, Page Up/Down, Home, End, Space).
  • For a hands-free experience, you can play a slideshow to flip through photos automatically.
  • The web page uses no server-side scripting, so it can be served very cheaply from a static web server such as Amazon S3 (or any other web server).
  • Lightroom versions 2.0 to 6 (and CC) should all be supported
  • Runs under Windows or MacOS (generated galleries are viewable under any OS)
  • Available in English, Español, Français, & Deutch
  • Totally FREE!

Version 1.0 (22 July 2015, in brief):

Smart image pre-fetching for immediate transitions between images, touch support, responsive design adapts to page size. Thumb navigation. Captions may overlay image or lie below it. Various configuration options, color schemes and example templates. A limited representation of the album is viewable as a preview inside Lightroom. Center-crops images to create aesthetically-pleasing square thumbnails (something Lightroom doesn't support).

New in version 1.1 (23 August 2015):
  • Album loading speed is massively improved, using a variety of techniques.
  • Greatly improved mobile / touch device support:
    • Smaller mobile devices, or tablets in portrait orientation are shown thumbnails on the bottom, with native, re-flow-enabled scrolling. This means that thumbnails scroll totally naturally for touchscreens, without losing any functionality on small window non-touch devices (buttons and mouse-wheel will work in this case).
    • Apple iOS bug causing flickering animations has been addressed.
    • Very small devices like phones are now supported without any quirks.
    • Pinching to zoom will open full size images (when full size image links are provided).
  • Adds options to not include full size images, and to disable ability to right click for saving images.

New in version 1.2 (11 September 2015):
  • Full gallery previews are now available inside Lightroom! Now almost all functionality and styling can be seen when changing settings.
  • Galleries can now be social media sharing enabled. Users can click to share galleries via Facebook, Google, Twitter, and Pinterest.
  • Maps from Google can now be opened for any image with geo-location data (GPS or city/country).
  • The icon scheme has been standardized. High quality, scalable SVG icons are shown in 95% of browsers, with PNG images used as a backup for the rest.
  • Page loading is even faster now, and more robust, using CDNs where possible. It still works when you're running locally (even if offline), or if CDN services are blocked or down.
  • The album is now compatible with Internet Explorer all the way back to 5.5 and other older browsers as well as Opera Mini.
  • Additional customization options.
  • Other minor improvements and bug fixes.


New in version 1.3 (12 January 2016):
  • Much greater control over where to place identity plate (logo), titles, and contact info
  • Allow customization of all text in generated galleries
  • Internationalization - now includes versions in Spanish, French and German
  • Better appearance on low-performance devices
  • Various minor improvements and bug fixes, and additional documentation
New in version 1.3.1 (9 May 2016):
  • New tool to optionally allow downloading all images in the gallery.
  • You can now choose the maximum number of thumbnail columns that will be shown (from 2-4). Also improved the layout and use of screen real estate to allow slightly larger image area.
  • Various minor bug fixes and improvements.
Update to version 1.3.1 (7 September 2017):
  • Minor bugfixes for viewing GPS position and auto-starting slideshows.


Installation:
  • Unzip the "GallerificAlbum.lrwebengine" folder and copy this to the Lightroom Web Galleries folder. This folder can be opened within Lightroom preferences (Win: Edit->Preferences, Mac: Lightroom->Preferences) by clicking on the "Show Lightroom Presets Folder" button then opening the Web Galleries folder.
    • On a Mac this is located under: /Users/username/Library/Application Support/Adobe/Lightroom/Web Galleries/
    • On Windows Vista/7/8, this is normally under: C:\Users\username\AppData\Roaming\Adobe\Lightroom\Web Galleries\ 
    • On Windows XP this is normally under: C:\Documents and Settings\username\Application Data\Adobe\Lightroom\Web Galleries\
  • Recommended but optional: Install the set of templates ("skins") for albums by copying the "Gallerific-Templates" folder into the Web Templates\ folder under the Lightroom presets folder. These will give you a good idea of output options and possible color schemes.
  • (Re-)Start Lightroom; the Gallerific gallery should appear in the list under the Web workflow

Usage:
  • As with any web album, select the images you wish to export using the Library view in Lightroom. Be sure they have all the metadata you want to include in the album. When you're happy with the images and their order, open the Web view.
  • Select the "Gallerific HTML5 Gallery" from the Layout style at the top right.
  • In the Web view, choose the options you want. Enter titles, descriptions, customize your image captions and use a custom logo, and choose where they appear. Customize your color scheme and how images will appear. Choose the size of the gallery image slide and an expanded full size image to be generated, as well as caption metadata and watermark to include. You can use the Preview in Browser button to check out your album’s appearance. And then simply Export to disk or Upload (to a server via FTP/SFTP) the complete album when you’re ready! The resulting HTML pages and supporting files will be generated in the folder or server location you selected. 
    • You can view the gallery on your local computer by opening the file index.html in a web browser.
    • After exporting to disk, the generated folder can be loaded onto a web server for access via the web or just copied to a CD/DVD or shared folder to share with others.
  • More details about creating web albums in general are available from Adobe.

Click here to see an example album - note that galleries are quite customizable and this is just an example.


Download here and get started!


License: This project is open source and released under the MIT License.


Many thanks:
This project couldn't have been done without the galleriffic and jquery history jQuery plugins; these have been extensively modified and improved for this project and have been forked on github. The project also benefits from the touchSwipe and transit plugins, the grunticon toolkit, the mediamatch polyfilljszipfilesaver.js, and fallback.js. Tablet image above is thanks to zanilic.com. Loader icons were generated from spiffygif.com and preloaders.net and compressed with kraken.io. Scalable icon designs are by Elusive, Typicons, Font Awesome, and Icomoon. And thanks to Henriette Donis for invaluable help in translating.


I'd love to hear about any websites that you create using this tool. Feel free to email me or leave a message below to let me know! And if you have any problems, suggestions or requests, leave them here too.


If you find the Gallerific Web plugin useful to you or your business, or if it's saving you time or money, I'd really appreciate a contribution. It's taken me countless hours to set this up and make it work well (now I realize why there are so few other options available!). Every bit counts. And many thanks.


Addendum: If you want to deploy your website onto Amazon S3, I provide an automated approach here (A word of warning that unlike creating an album, it does require somewhat advanced computer skills. An easier, but less efficient, option is to simply drag and drop the album using a GUI tool like S3 Browser or CrossFTP).

HGGIT errors pushing to Github

If you're using the hggit extension of mercurial (hg), and you get the error

pushing to git+https://github.com/username/project.git
http authorization required for https://github.com/username/project.git/info/refs
realm: GitHub
 searching for changes
adding objects
URLError: [Errno 10054] An existing connection was forcibly closed by the remote host

after trying to push to a cloned repository, the problem is probably your URL (even though it seems to connect and authenticate fine). For some reason certain files are inaccessible (In git you'd get: error: The requested URL returned error: 403 Forbidden while accessing https://github.com/username/project.git/info/refs). To fix this you should add your username to the url:

git+https://username@github.com/username/project.git

This would work under git, BUT, this doesn't work with hggit for some reason. It gives:

URLError: [Errno 11003] getaddrinfo failed

That means our only alternative is to use SSH, and with github, you're required to use public/private keys. These need to be generated and can be set here in github. In windows/putty, here's good info on generating them. Then they can be used by default in mercurial by adding an entry in the mercurial config files:

[ui]
ssh = tortoiseplink.exe -ssh -i "C:\Users\UserName\mykey.ppk"

Hopefully you should now be able to connect using SSH and push changes to the repo. The whole thing falls under the category of "should be easy but isn't."