commit ef4898090e95138fc3530ae2ff37b9b1361f09ac
parent 1b558eb11a992b1cf506910f9ed8cb93c768f5d0
Author: Christian Grothoff <christian@grothoff.org>
Date: Thu, 24 Feb 2005 06:59:42 +0000
libextractor 0.4.2 release
Diffstat:
14 files changed, 431 insertions(+), 77 deletions(-)
diff --git a/AUTHORS b/AUTHORS
@@ -28,6 +28,7 @@ man - core team using zlib (for man.gz)
id3v2 - core team with Milan <milan@skoid.org>
hash - core team using GNU coreutils/textutils and GPL'ed RMD160 code.
translit - Nils Durner <n.durner@t-online.de>
+thumbnail - core team using ImageMagick
General contributors:
Yuri N. Sedunov <aris@altlinux.ru>
@@ -56,3 +57,4 @@ libz -
ogg-vorbis -
glib -
libltdl -
+ImageMagick-
diff --git a/ChangeLog b/ChangeLog
@@ -1,3 +1,12 @@
+Thu Feb 24 00:32:44 EST 2005
+ Added extractor that extracts binary (!) thumbnails from
+ images using ImageMagick. Decoder function for the binary
+ string is in the thumbnailextractor.c source.
+ Releasing libextractor 0.4.2.
+
+Wed Feb 23 22:42:08 EST 2005
+ Comment tag was not extracted from ID3 tags. Fixed.
+
Sun Feb 20 16:36:17 EST 2005
Fixed similar problem in REAL extractor. Added support
for new Helix/Real format to REAL extractor.
diff --git a/NEWS b/NEWS
@@ -1,3 +1,9 @@
+Thu Feb 24 00:34:15 EST 2005
+ Thumbnails work.
+
+Sun Feb 20 16:36:17 EST 2005
+ Helix works (new Real format).
+
Fri Oct 22 19:18:38 EST 2004
id3v2.3 and id3v2.4 work.
diff --git a/TODO b/TODO
@@ -25,6 +25,8 @@ Desirable missing formats:
* EXE
* APEv2 (MPC file format, www.personal.uni-jena.de/~pfk/mpp/sv8/apetag.html)
* PRC (Palm module, http://web.mit.edu/tytso/www/pilot/prc-format.html)
+* KOffice
+* TGA
==============
@@ -43,4 +45,3 @@ UTF-8 conversion (only listing what is left to do):
* HTML: to be done
* OLE2: to be done
* OO: to be done
-* PDF: to be done
diff --git a/configure.ac b/configure.ac
@@ -1,8 +1,8 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
-AC_INIT([libextractor], [0.4.1-cvs], [libextractor@cs.purdue.edu])
+AC_INIT([libextractor], [0.4.2], [libextractor@cs.purdue.edu])
AC_REVISION($Revision: 1.67 $)
-AM_INIT_AUTOMAKE([libextractor], [0.4.1-cvs])
+AM_INIT_AUTOMAKE([libextractor], [0.4.2])
AM_CONFIG_HEADER(src/include/config.h)
# Checks for programs.
@@ -147,6 +147,25 @@ AC_CHECK_HEADERS([ltdl.h iconv.h])
AC_CHECK_HEADERS([jni.h])
# jni.h is purely optional! But if not present => no Java support!
+AC_CHECK_HEADERS([wand/magick-wand.h])
+
+AC_PATH_PROG(WAND_CONFIG, Wand-config, no)
+if test "$WAND_CONFIG" = "no" ; then
+ AC_MSG_RESULT([*** All Imagemagick dependent parts will be disabled, Wand-config not found. ***])
+else
+ WAND_CFLAGS=`$WAND_CONFIG --cflags`
+ WAND_LDFLAGS=`$WAND_CONFIG --ldflags`
+ WAND_LIBS=`$WAND_CONFIG --libs`
+ have_imagemagick="yes"
+ AC_DEFINE(HAVE_WAND,1,[Define this if you have Imagemagick])
+fi
+
+AM_CONDITIONAL(HAVE_WAND, test x"$have_imagemagick" = "xyes" )
+AC_SUBST(WAND_CFLAGS)
+AC_SUBST(WAND_LDFLAGS)
+AC_SUBST(WAND_LIBS)
+
+
##AC_PYTHON_DEVEL
##AC_CHECK_HEADERS([python/Python.h])
@@ -223,6 +242,7 @@ src/plugins/pdf/Makefile
src/plugins/rpm/Makefile
src/plugins/printable/Makefile
src/plugins/hash/Makefile
+src/plugins/thumbnail/Makefile
src/test/Makefile
])
diff --git a/po/de.po b/po/de.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: libextractor 0.4.0\n"
"Report-Msgid-Bugs-To: libextractor@cs.purdue.edu\n"
-"POT-Creation-Date: 2005-01-26 19:50-0500\n"
+"POT-Creation-Date: 2005-02-24 01:28-0500\n"
"PO-Revision-Date: 2004-12-29 15:40+0100\n"
"Last-Translator: Karl Eichwalder <ke@gnu.franken.de>\n"
"Language-Team: German <de@li.org>\n"
@@ -118,77 +118,82 @@ msgstr "extract [OPTIONEN] [DATEINAME]*"
msgid "Extract metadata from files."
msgstr "Metadaten aus den Dateien extrahieren."
-#: src/main/extract.c:242 src/main/extractor.c:781
+#: src/main/extract.c:208 src/main/extractor.c:755
+#, c-format
+msgid "%s - (binary)\n"
+msgstr ""
+
+#: src/main/extract.c:214 src/main/extractor.c:760
#, c-format
msgid "INVALID TYPE - %s\n"
msgstr "UNGÜLTIGE ART - %s\n"
-#: src/main/extract.c:307 src/main/extractor.c:44
+#: src/main/extract.c:280 src/main/extractor.c:44
msgid "title"
msgstr "Titel"
-#: src/main/extract.c:309 src/main/extractor.c:42
+#: src/main/extract.c:282 src/main/extractor.c:42
msgid "filename"
msgstr "Dateiname"
-#: src/main/extract.c:314 src/main/extractor.c:45
+#: src/main/extract.c:287 src/main/extractor.c:45
msgid "author"
msgstr "Autor"
-#: src/main/extract.c:318 src/main/extractor.c:47
+#: src/main/extract.c:291 src/main/extractor.c:47
msgid "description"
msgstr "Beschreibung"
-#: src/main/extract.c:320 src/main/extractor.c:59
+#: src/main/extract.c:293 src/main/extractor.c:59
msgid "keywords"
msgstr "Schlüsselwörter"
-#: src/main/extract.c:322 src/main/extractor.c:48
+#: src/main/extract.c:295 src/main/extractor.c:48
msgid "comment"
msgstr "Kommentar"
-#: src/main/extract.c:326 src/main/extractor.c:49
+#: src/main/extract.c:299 src/main/extractor.c:49
msgid "date"
msgstr "Datum"
-#: src/main/extract.c:328 src/main/extractor.c:71
+#: src/main/extract.c:301 src/main/extractor.c:71
msgid "creation date"
msgstr "Datum der Erstellung"
-#: src/main/extract.c:356 src/main/extractor.c:50
+#: src/main/extract.c:329 src/main/extractor.c:50
msgid "publisher"
msgstr "Herausgeber"
-#: src/main/extract.c:360 src/main/extractor.c:56
+#: src/main/extract.c:333 src/main/extractor.c:56
msgid "organization"
msgstr "Organisation"
-#: src/main/extract.c:364 src/main/extractor.c:58
+#: src/main/extract.c:337 src/main/extractor.c:58
msgid "subject"
msgstr "Gegenstand"
-#: src/main/extract.c:368 src/main/extractor.c:75
+#: src/main/extract.c:341 src/main/extractor.c:75
msgid "page count"
msgstr "Seitenanzahl"
-#: src/main/extract.c:502
+#: src/main/extract.c:475
#, c-format
msgid "You must specify an argument for the '%s' option (option ignored).\n"
msgstr ""
"Sie müssen ein Argument für die Option »%s« angeben (Option wird "
"ignoriert).\n"
-#: src/main/extract.c:566
+#: src/main/extract.c:539
#, c-format
msgid "Use --help to get a list of options.\n"
msgstr "Verwenden Sie --help, um eine Liste aller Optionen zu sehen.\n"
-#: src/main/extract.c:620
+#: src/main/extract.c:593
#, c-format
msgid "%% BiBTeX file\n"
msgstr "%% BibTeX Datei\n"
-#: src/main/extract.c:627
+#: src/main/extract.c:600
#, c-format
msgid "Keywords for file %s:\n"
msgstr "Schlüsserwörter für die Datei %s:\n"
@@ -425,24 +430,28 @@ msgstr "Medien-Art"
msgid "contact"
msgstr "Kontakt"
-#: src/main/extractor.c:206
+#: src/main/extractor.c:111
+msgid "binary thumbnail data"
+msgstr ""
+
+#: src/main/extractor.c:207
#, c-format
msgid "Initialization of plugin mechanism failed: %s!\n"
msgstr "Initialisierung des Plugin-Mechanismus' ist fehlgeschlagen: %s.\n"
-#: src/main/extractor.c:392
+#: src/main/extractor.c:393
#, c-format
msgid ""
"Resolving symbol '%s' in library '%s' failed, so I tried '%s', but that "
"failed also. Errors are: '%s' and '%s'.\n"
msgstr ""
-#: src/main/extractor.c:421
+#: src/main/extractor.c:422
#, c-format
msgid "Loading '%s' plugin failed: %s\n"
msgstr "Laden des »%s«-Plugins ist fehlgeschlagen: %s\n"
-#: src/main/extractor.c:526
+#: src/main/extractor.c:527
#, c-format
msgid "Unloading plugin '%s' failed!\n"
msgstr "Entladen des »%s«-Erweiterung ist fehlgeschlagen.\n"
diff --git a/po/libextractor.pot b/po/libextractor.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: libextractor@cs.purdue.edu\n"
-"POT-Creation-Date: 2005-01-26 19:50-0500\n"
+"POT-Creation-Date: 2005-02-24 01:28-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -104,75 +104,80 @@ msgstr ""
msgid "Extract metadata from files."
msgstr ""
-#: src/main/extract.c:242 src/main/extractor.c:781
+#: src/main/extract.c:208 src/main/extractor.c:755
+#, c-format
+msgid "%s - (binary)\n"
+msgstr ""
+
+#: src/main/extract.c:214 src/main/extractor.c:760
#, c-format
msgid "INVALID TYPE - %s\n"
msgstr ""
-#: src/main/extract.c:307 src/main/extractor.c:44
+#: src/main/extract.c:280 src/main/extractor.c:44
msgid "title"
msgstr ""
-#: src/main/extract.c:309 src/main/extractor.c:42
+#: src/main/extract.c:282 src/main/extractor.c:42
msgid "filename"
msgstr ""
-#: src/main/extract.c:314 src/main/extractor.c:45
+#: src/main/extract.c:287 src/main/extractor.c:45
msgid "author"
msgstr ""
-#: src/main/extract.c:318 src/main/extractor.c:47
+#: src/main/extract.c:291 src/main/extractor.c:47
msgid "description"
msgstr ""
-#: src/main/extract.c:320 src/main/extractor.c:59
+#: src/main/extract.c:293 src/main/extractor.c:59
msgid "keywords"
msgstr ""
-#: src/main/extract.c:322 src/main/extractor.c:48
+#: src/main/extract.c:295 src/main/extractor.c:48
msgid "comment"
msgstr ""
-#: src/main/extract.c:326 src/main/extractor.c:49
+#: src/main/extract.c:299 src/main/extractor.c:49
msgid "date"
msgstr ""
-#: src/main/extract.c:328 src/main/extractor.c:71
+#: src/main/extract.c:301 src/main/extractor.c:71
msgid "creation date"
msgstr ""
-#: src/main/extract.c:356 src/main/extractor.c:50
+#: src/main/extract.c:329 src/main/extractor.c:50
msgid "publisher"
msgstr ""
-#: src/main/extract.c:360 src/main/extractor.c:56
+#: src/main/extract.c:333 src/main/extractor.c:56
msgid "organization"
msgstr ""
-#: src/main/extract.c:364 src/main/extractor.c:58
+#: src/main/extract.c:337 src/main/extractor.c:58
msgid "subject"
msgstr ""
-#: src/main/extract.c:368 src/main/extractor.c:75
+#: src/main/extract.c:341 src/main/extractor.c:75
msgid "page count"
msgstr ""
-#: src/main/extract.c:502
+#: src/main/extract.c:475
#, c-format
msgid "You must specify an argument for the '%s' option (option ignored).\n"
msgstr ""
-#: src/main/extract.c:566
+#: src/main/extract.c:539
#, c-format
msgid "Use --help to get a list of options.\n"
msgstr ""
-#: src/main/extract.c:620
+#: src/main/extract.c:593
#, c-format
msgid "%% BiBTeX file\n"
msgstr ""
-#: src/main/extract.c:627
+#: src/main/extract.c:600
#, c-format
msgid "Keywords for file %s:\n"
msgstr ""
@@ -409,24 +414,28 @@ msgstr ""
msgid "contact"
msgstr ""
-#: src/main/extractor.c:206
+#: src/main/extractor.c:111
+msgid "binary thumbnail data"
+msgstr ""
+
+#: src/main/extractor.c:207
#, c-format
msgid "Initialization of plugin mechanism failed: %s!\n"
msgstr ""
-#: src/main/extractor.c:392
+#: src/main/extractor.c:393
#, c-format
msgid ""
"Resolving symbol '%s' in library '%s' failed, so I tried '%s', but that "
"failed also. Errors are: '%s' and '%s'.\n"
msgstr ""
-#: src/main/extractor.c:421
+#: src/main/extractor.c:422
#, c-format
msgid "Loading '%s' plugin failed: %s\n"
msgstr ""
-#: src/main/extractor.c:526
+#: src/main/extractor.c:527
#, c-format
msgid "Unloading plugin '%s' failed!\n"
msgstr ""
diff --git a/src/include/extractor.h b/src/include/extractor.h
@@ -29,7 +29,7 @@ extern "C" {
* 0.2.6-1 => 0x00020601
* 4.5.2-0 => 0x04050200
*/
-#define EXTRACTOR_VERSION 0x00040100
+#define EXTRACTOR_VERSION 0x00040200
#include <stdio.h>
@@ -120,6 +120,7 @@ typedef enum {
EXTRACTOR_LYRICS = 67,
EXTRACTOR_MEDIA_TYPE = 68,
EXTRACTOR_CONTACT = 69,
+ EXTRACTOR_THUMBNAIL_DATA = 70,
} EXTRACTOR_KeywordType;
/**
diff --git a/src/main/extract.c b/src/main/extract.c
@@ -23,10 +23,10 @@
#include "getopt.h"
#include <locale.h>
-#include <iconv.h>
+#include <iconv.h>
#ifndef MINGW
#include <langinfo.h>
-#endif
+#endif
#define YES 1
#define NO 0
@@ -179,10 +179,10 @@ printHelp ()
* @param print array indicating which types to print
*/
static void
-printSelectedKeywords (FILE * handle,
- EXTRACTOR_KeywordList * keywords,
- const int * print,
- const int verbose)
+printSelectedKeywords(FILE * handle,
+ EXTRACTOR_KeywordList * keywords,
+ const int * print,
+ const int verbose)
{
char * keyword;
iconv_t cd;
@@ -202,18 +202,24 @@ printSelectedKeywords (FILE * handle,
keywords->keyword);
else
keyword = strdup(keywords->keyword);
-
- if (NULL == EXTRACTOR_getKeywordTypeAsString (keywords->keywordType)) {
- if (verbose == YES) {
- fprintf(handle,
- _("INVALID TYPE - %s\n"),
- keyword);
- }
- } else if (print[keywords->keywordType] == YES)
+
+ if (keywords->keywordType == EXTRACTOR_THUMBNAIL_DATA) {
fprintf (handle,
- "%s - %s\n",
- EXTRACTOR_getKeywordTypeAsString(keywords->keywordType),
- keyword);
+ _("%s - (binary)\n"),
+ EXTRACTOR_getKeywordTypeAsString(keywords->keywordType));
+ } else {
+ if (NULL == EXTRACTOR_getKeywordTypeAsString(keywords->keywordType)) {
+ if (verbose == YES) {
+ fprintf(handle,
+ _("INVALID TYPE - %s\n"),
+ keyword);
+ }
+ } else if (print[keywords->keywordType] == YES)
+ fprintf (handle,
+ "%s - %s\n",
+ EXTRACTOR_getKeywordTypeAsString(keywords->keywordType),
+ keyword);
+ }
free(keyword);
keywords = keywords->next;
}
diff --git a/src/main/extractor.c b/src/main/extractor.c
@@ -108,11 +108,12 @@ static const char *keywordTypes[] = {
gettext_noop("lyrics"),
gettext_noop("media type"),
gettext_noop("contact"),
+ gettext_noop("binary thumbnail data"),
NULL,
};
/* the number of keyword types (for bounds-checking) */
-#define HIGHEST_TYPE_NUMBER 70
+#define HIGHEST_TYPE_NUMBER 71
#ifdef HAVE_LIBOGG
#if HAVE_VORBIS
@@ -729,8 +730,8 @@ EXTRACTOR_removeEmptyKeywords (EXTRACTOR_KeywordList * list)
* @param keywords the list of keywords to print, may be NULL
*/
void
-EXTRACTOR_printKeywords (FILE * handle,
- EXTRACTOR_KeywordList * keywords)
+EXTRACTOR_printKeywords(FILE * handle,
+ EXTRACTOR_KeywordList * keywords)
{
iconv_t cd;
char * buf;
@@ -749,15 +750,21 @@ EXTRACTOR_printKeywords (FILE * handle,
else
buf = iconvHelper(cd,
keywords->keyword);
- if (keywords->keywordType >= HIGHEST_TYPE_NUMBER)
- fprintf(handle,
- _("INVALID TYPE - %s\n"),
- buf);
- else
+ if (keywords->keywordType == EXTRACTOR_THUMBNAIL_DATA) {
fprintf(handle,
- "%s - %s\n",
- gettext(keywordTypes[keywords->keywordType]),
- buf);
+ _("%s - (binary)\n"),
+ gettext(keywordTypes[keywords->keywordType]));
+ } else {
+ if (keywords->keywordType >= HIGHEST_TYPE_NUMBER)
+ fprintf(handle,
+ _("INVALID TYPE - %s\n"),
+ buf);
+ else
+ fprintf(handle,
+ "%s - %s\n",
+ gettext(keywordTypes[keywords->keywordType]),
+ buf);
+ }
free(buf);
keywords = keywords->next;
}
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
@@ -10,10 +10,15 @@ if HAVE_GLIB
oledir=ole2
endif
-SUBDIRS = . oo printable hash $(oledir) rpm pdf
+if HAVE_WAND
+ thumbdir=thumbnail
+endif
+
+SUBDIRS = . oo printable hash $(oledir) rpm pdf $(thumbdir)
PLUGINFLAGS = -export-dynamic -avoid-version -module
+
if HAVE_VORBISFILE
extraogg = libextractor_ogg.la
endif
diff --git a/src/plugins/mp3extractor.c b/src/plugins/mp3extractor.c
@@ -467,6 +467,8 @@ libextractor_mp3_extract(char * filename,
klist = addkword(klist, info.year, EXTRACTOR_DATE);
if (strlen(info.genre) > 0)
klist = addkword(klist, info.genre, EXTRACTOR_GENRE);
+ if (strlen(info.genre) > 0)
+ klist = addkword(klist, info.comment, EXTRACTOR_COMMENT);
/* A keyword that has all of the information together) */
diff --git a/src/plugins/thumbnail/Makefile.am b/src/plugins/thumbnail/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+LIBS = \
+ @LTLIBINTL@ @LIBS@
+
+# install plugins under:
+plugindir = $(libdir)/libextractor
+
+SUBDIRS = .
+
+plugin_LTLIBRARIES = \
+ libextractor_thumbnail.la
+
+libextractor_thumbnail_la_SOURCES = \
+ thumbnailextractor.c
+
+libextractor_thumbnail_la_LDFLAGS = \
+ -export-dynamic -avoid-version -module @WAND_LDFLAGS@
+
+libextractor_thumbnail_la_CFLAGS = \
+ @WAND_CFLAGS@ @CFLAGS@
+
+libextractor_thumbnail_la_LIBADD = \
+ @WAND_LIBS@
diff --git a/src/plugins/thumbnail/thumbnailextractor.c b/src/plugins/thumbnail/thumbnailextractor.c
@@ -0,0 +1,253 @@
+/*
+ This file is part of libextractor.
+ (C) 2005 Vidyut Samanta and Christian Grothoff
+
+ libextractor is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ libextractor is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libextractor; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file thumbnailextractor.c
+ * @author Christian Grothoff
+ * @brief this extractor produces a binary (!) encoded
+ * thumbnail of images (using imagemagick). The bottom
+ * of the file includes a decoder method that can be used
+ * to reproduce the 128x128 PNG thumbnails.
+ */
+
+#include "platform.h"
+#include "extractor.h"
+#include <wand/magick_wand.h>
+
+#define THUMBSIZE 128
+
+static EXTRACTOR_KeywordList * addKeyword(EXTRACTOR_KeywordType type,
+ char * keyword,
+ EXTRACTOR_KeywordList * next) {
+ EXTRACTOR_KeywordList * result;
+
+ if (keyword == NULL)
+ return next;
+ result = malloc(sizeof(EXTRACTOR_KeywordList));
+ result->next = next;
+ result->keyword = keyword;
+ result->keywordType = type;
+ return result;
+}
+
+
+/* which mime-types maybe subjected to
+ the thumbnail extractor (ImageMagick
+ crashes and/or prints errors for bad
+ formats, so we need to be rather
+ conservative here) */
+static char * whitelist[] = {
+ "image/jpeg",
+ "image/gif",
+ "image/miff",
+ "image/mng",
+ "image/png",
+ "image/tiff",
+ "image/x-bmp",
+ "image/x-mng",
+ "image/x-png",
+ "image/x-xpm",
+ "image/xcf",
+ NULL,
+};
+
+struct EXTRACTOR_Keywords * libextractor_thumbnail_extract(const char * filename,
+ const char * data,
+ size_t size,
+ struct EXTRACTOR_Keywords * prev) {
+ MagickBooleanType status;
+ MagickWand * magick_wand;
+ size_t length;
+ char * thumb;
+ unsigned long width;
+ unsigned long height;
+ char * binary;
+ size_t pos;
+ size_t end;
+ size_t wpos;
+ size_t i;
+ unsigned int markers[8]; /* 256 bits */
+ unsigned char marker;
+ const char * mime;
+ int j;
+
+ /* if the mime-type of the file is not whitelisted
+ do not run the thumbnail extactor! */
+ mime = EXTRACTOR_extractLast(EXTRACTOR_MIMETYPE,
+ prev);
+ if (mime == NULL)
+ return prev;
+ j = 0;
+ while (whitelist[j] != NULL) {
+ if (0 == strcmp(whitelist[j], mime))
+ break;
+ j++;
+ }
+ if (whitelist[j] == NULL)
+ return prev;
+
+ magick_wand = NewMagickWand();
+ status = MagickReadImageBlob(magick_wand, data, size);
+ if (status == MagickFalse) {
+ DestroyMagickWand(magick_wand);
+ return prev;
+ }
+ MagickResetIterator(magick_wand);
+ if (MagickNextImage(magick_wand) == MagickFalse)
+ return prev;
+
+ height = MagickGetImageHeight(magick_wand);
+ width = MagickGetImageWidth(magick_wand);
+ if (height == 0)
+ height = 1;
+ if (width == 0)
+ width = 1;
+ if ( (height <= THUMBSIZE) &&
+ (width <= THUMBSIZE) ) {
+ DestroyMagickWand(magick_wand);
+ return prev;
+ }
+
+
+ if (height > THUMBSIZE) {
+ width = width * THUMBSIZE / height;
+ height = THUMBSIZE;
+ }
+ if (width > THUMBSIZE) {
+ height = height * THUMBSIZE / width;
+ width = THUMBSIZE;
+ }
+ MagickResizeImage(magick_wand, height, width, LanczosFilter, 1.0);
+ MagickSetImageDepth(magick_wand,
+ 8);
+ MagickSetImageChannelDepth(magick_wand,
+ RedChannel,
+ 2);
+ MagickCommentImage(magick_wand, "");
+ MagickSetImageChannelDepth(magick_wand,
+ GreenChannel,
+ 2);
+ MagickSetImageChannelDepth(magick_wand,
+ BlueChannel,
+ 2);
+ MagickSetImageChannelDepth(magick_wand,
+ OpacityChannel,
+ 2);
+ MagickSetImageInterlaceScheme(magick_wand,
+ NoInterlace);
+
+ if (MagickFalse == MagickSetImageFormat(magick_wand, "png")) {
+ DestroyMagickWand(magick_wand);
+ return prev;
+ }
+ thumb = MagickGetImageBlob(magick_wand, &length);
+ DestroyMagickWand(magick_wand);
+ if (thumb == NULL)
+ return prev;
+
+
+ /* encode! */
+ binary = malloc(2 + length + (length+256) / 254);
+ if (binary == NULL)
+ return prev;
+
+ pos = 0;
+ wpos = 0;
+ while (pos < length) {
+ /* find unused value between 1 and 255 in
+ the next 254 bytes */
+ end = pos + 254;
+ if (end < pos)
+ break; /* integer overflow! */
+ if (end > length)
+ end = length;
+ memset(markers, 0, sizeof(markers));
+ for (i=pos;i<end;i++)
+ markers[thumb[i]&7] |= 1 << (thumb[i] >> 3);
+ marker = 1;
+ while (markers[marker&7] & (1 << (marker >> 3))) {
+ marker++;
+ if (marker == 0) {
+ /* assertion failed... */
+ free(binary);
+ free(thumb);
+ return prev;
+ }
+ }
+ /* recode */
+ binary[wpos++] = marker;
+ for (i=pos;i<end;i++)
+ binary[wpos++] = thumb[i] == 0 ? marker : thumb[i];
+ pos = end;
+ }
+ binary[wpos++] = 0; /* 0-termination! */
+ free(thumb);
+ return addKeyword(EXTRACTOR_THUMBNAIL_DATA,
+ binary,
+ prev);
+}
+
+#if 0
+
+/**
+ * This function can be used to decode the binary data
+ * stream produced by the thumbnailextractor.
+ *
+ * @param in 0-terminated string from the meta-data
+ * @return 1 on error, 0 on success
+ */
+int decodeThumbnail(const unsigned char * in,
+ unsigned char ** out,
+ size_t * outSize) {
+ unsigned char * buf;
+ size_t pos;
+ size_t wpos;
+ unsigned char marker;
+ size_t i;
+ size_t end;
+ size_t inSize;
+
+ inSize = strlen(in);
+ if (inSize == 0) {
+ *out = NULL;
+ *outSize = 0;
+ return 1;
+ }
+
+ buf = malloc(inSize); /* slightly more than needed ;-) */
+ *out = buf;
+
+ pos = 0;
+ wpos = 0;
+ while (pos < inSize) {
+ end = pos + 255; /* 255 here: count the marker! */
+ if (end > inSize)
+ end = inSize;
+ marker = in[pos++];
+ for (i=pos;i<end;i++)
+ buf[wpos++] = (in[i] == marker) ? 0 : in[i];
+ pos = end;
+ }
+ *outSize = wpos;
+ return 0;
+}
+
+
+#endif