UK

Mark Easterbrook - Personal Website 

at easterbrook.f2s.com 

Navigation


Home

Software Development

Telecoms

Computer HowTos

Hosting

Credits


External Links

Canon.co.uk Compact Digital Cameras.


Valid HTML 4.01 Transitional
 

Processing images from Canon Digital Cameras on Linux

This page describes how to process photographs and videos from a Canon digital camera and display them on a web page. I use SuSE Linux, which comes with all these utilities as standard, but they are available for Windows with a little more work.

Cameras

I have a Canon Powershot A75 and my wife has a Canon Powershot A510.
Canon A75 camera Canon A510 camera

Canon Powershot A75

Canon Powershot A510

They are both 3.2 Megapixel cameras generating 2048x1536 images. The A510 is more compact and lighter, taking only two AA batteries compared with the A75's four, but otherwise the cameras are very similar and have almost identical controls.

The tools and procedures described here will probably work for other Canon digital cameras, and may be useful for non-Canon cameras.

I have not described how to get the data from the camera because I use the supplied Canon utilities on a Windows XP machine.

Still images

Meta Information

The uploaded still images are JPEG files with a filename like IMG_0108.JPG. The camera includes information about the picture in the file which can be viewed using the jhead program:
$jhead IMG_0108.JPG
sh: jhead: command not found

This information can be useful to automatically process the images, the two most useful are:

  • The date and time that the photograph was taken (assuming you have set the date/time correctly on the camera) to, for example, sort the images into the order they were taken:
$jhead IMG_0108.JPG | awk '/^Date/ {print $3 " " $4}'
sh: jhead: command not found
  • The resolution:
$jhead IMG_0108.JPG | awk '/^Resolution/ {print $3 $4 $5}'
sh: jhead: command not found

jhead can do much more, look at the man page or Matthias Wandel's documentation page.

Rotating the image

My Powershot A75 detects the orientation of the camera and encodes this in the JPEG file so that pictures taken sideways (portrait mode) are displayed correctly. Unfortunately my wife's Powershot A510 does not, so the images are sideways. This can easily be fixed without losing any of the metadata by using the convert program:
$mv IMG_9115.JPG IMG_9115_sideways.JPG
$convert -rotate 270 IMG_9115_sideways.JPG IMG_9115.JPG

Use -rotate 90 if the camera was tilted left instead of right.

Re-sizing the image

The size of the original images, 2048x1536, are too big for displaying on a normal web page so it is neccesary to scale them down. It is normal practice to only put thumbnail pictures on the main page but make them clickable to show a larger image.

The convert utility can be used to generate scaled images, for example, to produce a "large" thumbnail:

$convert -size 256x192 IMG_0108.JPG -resize 256x192 IMG_0108_256x192.JPG
Of course, if you have more than a few images to process, this is a bit tedious and error prone, so it is better to automate it with a short bash script.

It is better (no interpolation of pixels) to generate scaled images that are binary fraction of the original, so let's produce a set of scaled images based on the size of the original.

$cat scale.sh
#!/bin/bash
#
# Generate scaled images from canon photograph images
#
for image in IMG_????.JPG; do
        #Obtain the x and y sizes of the original image
        x_size=`jhead $image | awk '/Resolution/ {print $3}'`
        y_size=`jhead $image | awk '/Resolution/ {print $5}'`
        #Generate half size scaled images until we have a thumbnail image
        while test $x_size -gt 100 -a $y_size -gt 100; do
                x_size=$((x_size/2))
                y_size=$((y_size/2))
                size=${x_size}x${y_size}
                fname=${image/.JPG/}_${size}.JPG
                echo Generating $fname
                convert -size $size $image -resize $size $fname
        done
done
If we run this on the two images already mentioned, we end up with the files: Compare them all on one page.

Note that the scaled images are only a fraction of the size of the original, so there is little overhead in storing all the scaled images along with the original.

Generating HTML

With a little more bash scripting, it is possible to automatically generate a web page displaying a thumbnail image, links to view the images in various sizes, and the image metadata. I have chosen to format it like:
ThumbnailFormatsStatistics
256x192 Camera model : Canon PowerShot A510
Date/Time : 2005:07:10 08:46:03
Flash used : No (auto)
Focal length : 23.2mm (35mm equivalent: 147mm)
CCD width : 5.69mm
Exposure time: 0.0100 s (1/100)
Aperture : f/5.5
Whitebalance : Auto
Metering Mode: matrix


but the bash script can easily be hacked to generate any format you wish.
$cat generate.sh
#!/bin/bash
#
# Generate HTML web pages of all canon images.
#
#Generate HTML header and start table
echo "<html><head><TITLE>My Photographs</TITLE></head><body>" >index.html
echo "<H1>My Photographs</H1>" >>index.html
echo "<TABLE border=0><TR><TH>Thumbnail<TH>Formats<TH><TH>Statistics</TR>" >>index.html
#Generate list of: timestamp of photo and image filename
for image in `ls IMG_????.JPG | grep -v _edit.JPG`; do
        echo `jhead $image | awk '/^Date/ {print $3 $4}'` $image >>imagelist
done
#Sort the list in time order and process each file
for image in `sort imagelist | cut -d' ' -f2`; do
	name=${image/.JPG/}
	echo $name
        x=`jhead $image | awk '/Resolution/ {print $3}'`
        y=`jhead $image | awk '/Resolution/ {print $5}'`
        origres=${x}x${y}
	ref=${name}_$((x/2))x$((y/2)).JPG
        #Generate scaled images down to thumbnail
	size_list=""
        while test $x -gt 200 -a $y -gt 200; do
                x=$((x/2))
                y=$((y/2))
                size=${x}x${y}
                size_list="$size_list $size"
                echo convert -size $size $image -resize $size ${name}_${size}.JPG
        done
        echo "<TR><TD><A HREF=$ref><img src=${name}_$size.JPG></A></TD><TD>" >>index.html
        echo "<UL><LI><A HREF=$image>Original</A>($origres)" >>index.html
        for size in $size_list; do
                echo "<LI><A HREF=${name}_${size}.JPG>$size</A>" >>index.html
        done
        echo "</UL></TD><TD></TD><TD><SMALL>" >>index.html
        jhead $image | grep -v "^File" | grep -v "^Camera make" | grep -v "^Resolution" | sed "s/$/<BR>/" >>index.html
        echo "</SMALL>" >>index.html
        echo "</TD><TD>" >>index.html
        echo "</TD></TR><TR></TR>" >>index.html
done
rm imagelist
echo "</TABLE>" >>index.html
echo "</body></html>" >>index.html

Commentary:

  • The images are sorted by time extracted from the original JPEG because they may originate from two cameras. If sorted purely on filename order then all the pictures from one camera would appear before the other (the cameras are configured so that they don't have overlapping sequence numbers and the time and date are correct).
  • A thumbnail size of 256x192 or 192x256 is sufficiently small for this application so the loop condition is different to the scale.sh version above.
  • Some lines are removed from the jhead information as the information is duplicated elsewhere.
  • The script only works for original images from the camera. This is a simplified version of my full script that does not deal with Stitched Panoramic or Enhanced/Edited images.
The result can be viewed here. (Use your browser's "View Source" option to see the raw HTML.)

Other useful information

If the camera is put into panoramic mode, it takes a sequence of overlapping photographs that can be stitched together using the supplied Canon application (assuming you have access to a Windows machine). The files are named STA_0110.JPG, STB_0111.JPG, STC_0112.JPG, etc. As stitching is a manual and visual process it cannot be easily automated, but the final result can be included in the HTML by making a few tweaks to the above bash script:
  • The stitched images will not contain the jhead information from the camera, but it is in the original unstitched images, so retain these and add a conditional to the script to jhead from the original and not the stitched image.
  • Panoramic shots have one dimension much larger than the other so depending on how you display your thumbnails you may need to adjust the thumbnail size logic.
I have found the camera takes excellent photographs that rarely need post-processing. However, by saving the edited images with a filename such as IMG_0108_cropped.JPG, they can be added to the list of scaled images with a simple additional foreach loop in the bash script.

It is possible to display thumbnail images by referencing the original image and specifying the width and height in the <IMG> tag instead of producing a scaled version. This is a bad idea, especially when there are more than a few on the page, because this forces the browser to fetch the full size image which could be 10 or even 100 times the size of a properly scaled thumbnail.

Video

Processing the still images from the camera is trivial compared with dealing with the moving images. Whereas the still images are already in the best format for displaying on a web page (JPEG) and just need scaling, there are a number of complications to processing the videos:
  • The original API videos use a file format that produces very large files that are not practical for a web site.
  • Video files consist of a video stream, one or more audio streams (the canon produces mono audio so there is just one audio stream present) and a file format that allows the video and audio streams to be packaged and synchronised on playback.
  • Unlike JPEG with still images, there is no "one size fits all" video format suitable for putting on a web site.
  • Both Canon cameras do not encode the camera orientation in the video file, so that videos taken in portrait mode appear sideways when viewed.
  • Video files are large compared with other web resources such as images and the web page itself. The size can be reduced by using a codec with better compression (and possibly reducing the number of video players supported), or by trading quality for size. There is no usually no "right" answer and the choice will depend on your circumstances.
The aim of this section is to re-encode the video files to formats suitable for a web site and to correct the orientation.

Brief Video Format Primer

A video file consists of 3 components:
  1. A file format. This packages the video and audio streams. Common formats are Microsoft's AVI (Audio Video Interleave) and ASF (Advanced Streaming Format), Apple's Quicktime, MPEG and RealMedia's RealVideo. For further information see Eleanora L Smith's comparison (cached) or Wikipedia. Most file formats are enable to contain any of the video or audio streams, although most containers are usually associated with only one type. Also, most video players now support more than just one video and audio type so that it is rarely required to install more than one player.
  2. The video stream. Typical encodings are MPEG, Sorenson (Quicktime), and RealVideo. The ability to view a video stream depends on the codecs installed.
  3. Audio streams. Multiple streams allow stereo or surround sound. The ability to hear the video streams depends on the codecs (and the number of speakers) you have. Fortunately there are a lot less audio formats in common use.
Just to confuse matters, MPEG is used to refer to a file format (actually MPEG-4 Part 14, or MP4), a video encoding (MPEG4 Part 2), and an audio encoding (e.g. MPEG-1 Part 3 Layer 3).

mencoder

mencoder is part of the MPlayer package so should be present in most Linux distributions. MPlayer/mencoder are able to use a large number of codecs, of which many are optional installs. Some of the codecs are not open-source so will not be present on true open source distributions, but there are sufficient open codecs to support most types of video.

Re-encoding

First, to check that mencoder is installed correctly and to find out the format of the AVI files uploaded from the camera, run mencoder in copy mode. By specifying "copy" as the audio and video codec, the input is just copies to the output.
$mencoder MVI_0018.AVI -o MVI_0018-copy.avi -of avi -ovc copy -oac copy
Commentary
  • -o sets the output file name. I have decided to include the encoding in the filename as a reminder (the file extension usually refers to the container file type rather than the encoding).
  • -of set the output file type, in this case avi.
  • -ovc specifies the video codec to be copy.
  • -oac and the same for audio.
mencoder is fairly verbose about what it does (only first part of output shown):

This results in an output file the same size as the input, which is too big to put on a website. An obvious next step is to retain the MJPEG encoding but apply compression.

$mencoder MVI_0018.AVI -o MVI_0018-mjpeg.avi -of avi -ovc lavc -lavcopts vcodec=mjpeg:mbd=1:vbitrate=800 -oac copy
Which produces:

To be continued...


Last Updated: Site 2010-01-16 Page 2010-01-16

© Copyright Mark Easterbrook 2005-2006.