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