Saturday, July 18, 2009

Thumbnail generation algorithm with out losing image aspect ratio

Referred many thumbnail generation algorithms, but many were about to crop most of the available screen area, if the image to be thumbnail'ed is not aligned with the image's aspect ratio.

Algorithm that I figured out to save more area of the original image is:
Assume the thumbnail dimension should be x':y'.
1. Load the image and get original width(w) and hieght(h).
2. Scale the image to X:Y, such that:
a. if h > w, Y = h * aspect_ratio, X=w
b. if h < w, X = w * aspect_ratio, Y=h
3. Crop the scaled image to x':y' calculating the area from center of the picture.

GdkPixbuf functions used for implementing this algorithms are:
gdk_pixbuf_new_from_file(),
gdk_pixbuf_get_width(),
gdk_pixbuf_get_height(),
gdk_pixbuf_scale_simple(),
gdk_pixbuf_new(),
gdk_pixbuf_copy_area()

strcasestr()

The strcasestr() function is defined in libc on '2.6.24-16-generic #1 SMP Thu Apr 10 13:23:42 UTC 2008 i686 GNU/Linux' machine is defined as:
$nm -AC /usr/lib/libc.*|grep strcasestr
/usr/lib/libc.a:strcasestr.o:00000000 W strcasestr
flag 'W' means weakly defined. If it is linked with normal code without defining the function(), compiler error is observed saying 'strcasestr() undefined'. The function's declaration could be found in . To avoid compilation error, I have written my own strcasestr() function, but altered the expected functionality of the function to suit my requirement.

I need to compare whether a given string is a sub-string(case-insensitive) of the given string. But the string could be found only at the word begining. The code fragment for the strcasestr() is pasted below.

static gchar* my_strcasestr(gchar *source, gchar *target) {
gushort i = 0, len = 0; /* assuming search string length won't be greater than sizeof(gushort) */
guchar after_space = 1;

len = strlen(target);
for (; source[i] != '\0'; i++) {

if(!after_space && source[i] != ' ')
continue;
if(source[i] == ' ') {
after_space = 1;
continue;
}
after_space = 0;
if(!strncasecmp((source+i), target, len))
return (source+i);
}
return NULL;
}
If there is any better way of doing this, pls let me know.