-/* $Id: thumb.js,v 1.3 2006/11/05 11:55:40 mmondor Exp $ */
+/* $Id: thumb.js,v 1.4 2006/11/05 13:00:16 mmondor Exp $ */
/*
* Copyright (c) 2006, Matthew Mondor
function thumbnail(from, to, xmax, ymax)
{
- var ofh, oimg, ox, oy, timg, tfh;
+ var ofh, tfd, nfd, oimg, ox, oy, timg, tfh;
var ret = false;
var type = undefined;
var i, to;
- /* Set load and save functions relative to image file type */
+ /*
+ * Set load and save functions relative to image file type.
+ */
if (from.match(/\.jpg$|\.jpeg$/)) {
GD.load = GD.createFromJpeg;
GDImage.prototype.save = thumbnail_jpeg;
*/
for (;;) {
try {
- ofh = new File(from, 'r');
+ var otime, tstat;
+
+ /*
+ * First open descriptors so that we may fstat(2)
+ * to determine if the thumbnail is more recent than
+ * the original image, in which case we don't avoid to
+ * create a thumb for nothing. We'll use File's
+ * fdopen(3) functionality afterwards if need be.
+ * We do this because image resizing is a rather CPU
+ * intensive operation.
+ */
+ ofd = new FD();
+ ofd.open(from, FD.O_RDONLY);
+ otime = (ofd.fstat()).st_mtime;
+
+ tfd = new FD();
+ tfd.open(to, FD.O_WRONLY | FD.O_CREAT);
+ tstat = tfd.fstat();
+
+ if (otime <= tstat.st_mtime && tstat.st_size != 0) {
+ ofd.close();
+ tfd.close();
+ return true;
+ }
+
+ /*
+ * Load original image and determine thumb size.
+ */
+ ofh = new File(ofd.fd, 'r');
oimg = GD.load(ofh);
ox = oimg.imageSX();
ty = Math.round((ymax / ox) * oy);
}
+ /*
+ * Create and save new thumbnail. It's important to
+ * first truncate the file to zero length which
+ * fopen(3) would have done for us but which fdopen(3)
+ * won't.
+ */
+ tfd.ftruncate(0);
+ tfh = new File(tfd.fd, 'w');
+
timg = GD.createTrueColor(tx, ty);
//oimg.copyResampled(timg, 0, 0, 0, 0, tx, ty, ox, oy);
oimg.copyResized(timg, 0, 0, 0, 0, tx, ty, ox, oy);
- tfh = new File(to, 'w');
timg.save(tfh);
} catch (x) {
Syslog.log(Syslog.LOG_NOTICE, x + ' (' + from + ')');
try {
ofh.close();
oimg.destroy();
- timg.destroy();
tfh.close();
+ timg.destroy();
} catch (x) {}
delete GD.load;