libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

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:
MAUTHORS | 2++
MChangeLog | 9+++++++++
MNEWS | 6++++++
MTODO | 3++-
Mconfigure.ac | 24++++++++++++++++++++++--
Mpo/de.po | 53+++++++++++++++++++++++++++++++----------------------
Mpo/libextractor.pot | 53+++++++++++++++++++++++++++++++----------------------
Msrc/include/extractor.h | 3++-
Msrc/main/extract.c | 40+++++++++++++++++++++++-----------------
Msrc/main/extractor.c | 29++++++++++++++++++-----------
Msrc/plugins/Makefile.am | 7++++++-
Msrc/plugins/mp3extractor.c | 2++
Asrc/plugins/thumbnail/Makefile.am | 24++++++++++++++++++++++++
Asrc/plugins/thumbnail/thumbnailextractor.c | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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