August 2005
In this article, expanding epeg to handle a source and
target directory is examined with the bonus of checking to see if a
thumbnail file in the target directory is missing and regenerating
it on the fly.
For those who wish to skip the diatribe, the full source is available.
There is a source directory
called backgrounds/ in the current directory that holds copies
of the original (and larg-ish) images. The target directory is aptly named
thumbcache. The goal is to first, initialize the
thumbcache directory, then update it as needed.
Note: There are some intentional holes left in this program such as getting the full path for example. Call it room for improvement..
Since the make syntax was addressed in the first article,
that will be skipped. In a nutshell, directory handling interfaces
are all that need to be added.
#include <stddef.h> #include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <Epeg.h> #define BACKGROUNDSbackgrounds#define THUMBCACHEthumbcache#define LEN 1024
Of course, the directory names are defined, the LEN
value is not a standard string length - this can also be grokked from
the limits.h file.
After a little iteration, the functions can be broken down into three basic types:
For simplicity, here are the two helper functions:
fullpath()Using the filename and leading directory, develop a full path name,
in the case of this program it is relative, however, tacking the
dir argument to a getcwd() call can develop
an entire path.
char
*fullpath(char *file, char *dir)
{
static char path[LEN];
strcpy(path, dir);
strcat(path, /
);
strcat(path, file);
return (path);
}
create_thumb()... is actually the only part of the program that is e17 specific (which is somewhat ironic). In the function, the exact functions defined in Epeg I article are used with one exception, the filenames (in and out) are predefined and the width, height and quality are hard coded.
void
create_thumb(char *src, char *dst)
{
Epeg_Image * image;
image = epeg_file_open(src);
if (!image) {
printf(Cannot open %s\n
, src);
exit(1);
}
epeg_decode_size_set(image, 128, 96);
epeg_quality_set(image, 75);
epeg_file_output_set(image, dst);
epeg_encode(image);
epeg_close(image);
}
Now it is time for the core functions. These come in two parts, the first
is init_thumbcache. In the next function, there is no thumbcache
directory at all, it simply has to be generated, so all that has to happen
is each background image that is loaded needs to call
create_thumb().
init_thumbcache()
void
init_thumbcache(DIR * backgrounds)
{
int i;
char dst[LEN];
char src[LEN];
DIR *thumbcache;
struct dirent *src_dp, dst_dp;
if (mkdir(THUMBCACHE, 0755)) {
printf(Could not create directory %s\n
, THUMBCACHE);
exit (1);
}
i = 0;
while (src_dp = readdir(backgrounds)) {
if (i > 1) {
strcpy(src, fullpath(src_dp->d_name, BACKGROUNDS));
strcpy(dst, fullpath(src_dp->d_name, THUMBCACHE));
create_thumb(src, dst);
}
i++;
}
(void)closedir(backgrounds);
}
The background directory images are being iterated over and for each one, a new thumbnail is being generated.
update_thumbcache()Next comes the weird one, in the update_thumbcache()
function, there is some definite oddness to deal with.
That certainly sounds neat, but effectively it is a directory search, which is easy enough. Crack open the first directory, and for each item in it, see if there is a matching one in the second.
void
update_thumbcache(DIR * backgrounds, DIR * thumbcache)
{
int i, j, k;
char dst[LEN];
char src[LEN];
struct dirent *src_dp, *dst_dp;
i = 0;
while (src_dp = readdir(backgrounds)) {
if (i > 1) {
j = 0;
k = 0;
while (dst_dp = readdir(thumbcache)) {
if (j > 1)
if (strcmp(src_dp->d_name, dst_dp->d_name) == 0)
k++;
j++;
}
}
if (k == 0) {
strcpy(src, fullpath(src_dp->d_name, BACKGROUNDS));
strcpy(dst, fullpath(src_dp->d_name, THUMBCACHE));
create_thumb(src, dst);
}
i++;
rewinddir(thumbcache);
}
(void)closedir(backgrounds);
(void)closedir(thumbcache);
}
That is a bit to digest, but it is actually relatively easy. Following is a simple step by step which should be obvious when looking at the code:
src_dp).. & ..) then proceed, otherwise count
up.dst_dp).main()Last and not least, the main function. Basically
main does not do a whole lot:
void update_thumbcache (DIR *, DIR *);
void init_thumbcache (DIR *);
void create_thumb (char *, char *);
char *fullpath (char *, char *);
int
main (void)
{
DIR * backgrounds, * thumbcache;
backgrounds = opendir(BACKGROUNDS);
if (backgrounds == NULL) {
printf(Cannot find %s - exiting\n
, BACKGROUNDS);
closedir(backgrounds);
exit (1);
}
thumbcache = opendir(THUMBCACHE);
if (thumbcache == NULL) {
closedir(thumbcache);
init_thumbcache(backgrounds);
return 0;
}
update_thumbcache(backgrounds, thumbcache);
return 0;
}
In a nutshell:
update_thumbcache(), if not, go ahead and
call init_thumbcache().Some obvious, changes should be incorporated into the program, as was noted earlier, there are intentional flaws, the next article will address them:
As always, reader feedback is welcome.
Next: Enlightenment Thumbnailing utility Previous: Epeg I
(based on last 2 months log reports)