July 2005

Using Epeg Part 1

The new software coming out of the Enlightenment project can do some pretty interesting things. A starting example of Epeg will be presented in the text as well as expanded versions in later ones.

What is Epeg?

Per the enlightenment project, Epeg is an incredibly fast library that can be used for creating thumb-nails. There are other programs out there that can do thumbnailing; epeg provides a clear and well documented API at the programmer's disposal.

Makefile

First things first, the Makefile for the ethumber project directory:

CC=gcc

SRC=ethumber.c
PRG=ethumber
EPEG_FLAGS=`epeg-config --libs --cflags`

all: ethumber

ethumber:
        ${CC} ${EPEG_FLAGS} ${SRC} -o ${PRG}

clean:
        rm -f a.out *.core ${PRG}

Pass One

The first pass will simply work like the example that can be found in the epeg doxygen documents.


/* ethumber.c */

#include "Epeg.h"

int
main(int argc, char **argv)
{
        Epeg_Image *image;

        if (argc != 3) {
                printf("Usage: %s input.jpg thumb.jpg\n", argv[0]);
                exit(0);
        }

   image = epeg_file_open(argv[1]);

        if (!image) {
                printf("Cannot open %s\n", argv[1]);
                exit(-1);
        }
   
        epeg_decode_size_set           (image, 128, 96);
        epeg_quality_set               (image, 75);
        epeg_thumbnail_comments_enable (image, 1);
        epeg_file_output_set           (image, argv[2]);
        epeg_encode                    (image);
        epeg_close                     (image);
   
        return 0;
}

The header file provides access to the epeg API. The first variable, image, is an epeg type used to contain the image that will be thumb-nailed. Next a quick check of the input to make sure everything needed is being provided. Following is a brief description of the remaining functions:

  • epeg_file_open() returns a file handle on the image that will be manipulated with a decoded header. If it cannot be opened, error out and exit.
  • epeg_decode_size_set() accepts the file handle pointer, width as integer and height as integer.
  • epeg_thumbnail_comments_enable() will enable/disable the output file to have comments added (0 off, 1 on).
  • epeg_file_output_set() sets where the output file will be saved.
  • epeg_encode() saves the image.
  • epeg_close() closes the file handle.

Some of the calls above should intimate the flexibility of the API, for example, if an option to send the output to another directory was required, it could be created then have the path appended to for the argument in epeg_file_output_set().

Building and Using

For simplicity, assume that a test image that is 1024x768 is in the project directory and it is called test.jpg. To try out the program, run:


./ethumber test.jpg thumb_test.jpg

The new thumbnail of thumb_test.jpg should have been created.

Adding a Little Flexibility

In this first simple draft, the desired additional functionality is:

  • specified dimensions
  • specified quality
  • input filename
  • output filename

In a nutshell, all that is needed are some extra variables and minor changes to the epeg calls.

Additional Includes and Definition

First things first, getopt is needed and for certain print functions, the name of the program:


/* ethumber.c */

#include <stdlib.h>
#include <unistd.h>

#include <Epeg.h>

#define PROGRAM "ethumber"

The Variables and Defaults

Next the variables needed to handle the various arguments:


int
main(int argc, char **argv)
{
    Epeg_Image * image;
    int ch, height, quality, width;
    char *input, *output;

        /* Default values - can be overidden */
    quality     = 75;
    height      = 96;
    width       = 128;
    output      = "thumb.jpg"; 

All that has been added is to create variables for the input switch case, thumb height, quality and width and finally the input and output filenames. Additionally, the above code sets the defaults for everything except the input filename (as ethumber has no knowledge of what it is).

Options Parser

The options parser uses a simple getopt plus a switch case:


    while ((ch = getopt(argc, argv, "h:i:o:q:w:")) != -1) {
        switch (ch) {
        case 'h':
                height = atoi(optarg);
                break;
        case 'i':
                input = optarg;
                break;
        case 'o':
                output = optarg;
                break;
        case 'q':
                quality = atoi(optarg);
                break;
        case 'w':
                width = atoi(optarg);
                break;
        default:
                usage();
                exit (0);
        }
    }

The parser is pretty simple, snag the option and store the argument. It is worth noting here that the program requires the user to use the -i option to specify the input file. It is the one and only forced option.

Changing the Existing Bits

Now that the optional variables have been set, all the program needs is to change the epeg specific parts of it to reflect using the variables after opening the input file:


    image = epeg_file_open(input);

    if (!image) {
        printf("Cannot open %s\n", input);
        exit (0);
    }

    epeg_decode_size_set(image, width, height);
    epeg_quality_set    (image, quality);
    epeg_file_output_set(image, output);
    epeg_encode(image);
    epeg_close(image);

Then the done message and return:


    printf("Done\n");

    return 0;
}

Running the Improved Version

Now with a slew of options and arguments, using the same test file as above with new values for each option:


./ethumber -i test.jpg -o thumb_test.jpg -h 100 -w 200 -q 80

Summary & Next Time

Now the program has reached a point where it is useful right from the command line, but it still lacks some features from within and without. Following are a few examples of what will be tackled.

  • add the capability to process multiple files
  • Better error handling

That just about rounds it out.

Next: Epeg II