From 9d0a7b06104a79f7dfdaf2d332e8acdf05a9b256 Mon Sep 17 00:00:00 2001 From: Andreas Huggel Date: Sat, 9 Dec 2006 12:13:10 +0000 Subject: [PATCH] Implemented conversion function to display Windows tags 0x9c9b-0x9c9f. Added configure magic to find iconv. Fixes bug #460. --- config/config.h.in | 9 ++++ config/config.mk.in | 2 +- config/configure.ac | 17 ++++---- src/tags.cpp | 80 +++++++++++++++++++++++++++++++++++- src/tags.hpp | 2 + test/bugfixes-test.sh | 4 ++ test/data/bugfixes-test.out | 6 +++ test/data/exiv2-bug460.jpg | Bin 0 -> 5364 bytes 8 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 test/data/exiv2-bug460.jpg diff --git a/config/config.h.in b/config/config.h.in index f71f5556..1a918e98 100644 --- a/config/config.h.in +++ b/config/config.h.in @@ -37,6 +37,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIBINTL_H +/* Define to 1 if you have the `iconv' function. */ +#undef HAVE_ICONV + +/* Define to `const' or to empty, depending on the second argument of `iconv'. */ +#undef ICONV_CONST + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBINTL_H + /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC diff --git a/config/config.mk.in b/config/config.mk.in index f7d5a57b..fdf8b98b 100644 --- a/config/config.mk.in +++ b/config/config.mk.in @@ -55,7 +55,7 @@ CPPFLAGS = -I. @CPPFLAGS@ -DEXV_LOCALEDIR=\"$(localedir)\" # Linker flags and libraries LDFLAGS = @LDFLAGS@ -LIBS = @LTLIBINTL@ @LIBS@ +LIBS = @LTLIBINTL@ @LTLIBICONV@ @LIBS@ # Suffix of executables EXEEXT := @EXEEXT@ diff --git a/config/configure.ac b/config/configure.ac index bb6b279c..4a553a72 100644 --- a/config/configure.ac +++ b/config/configure.ac @@ -30,14 +30,6 @@ AC_PROG_RANLIB # --------------------------------------------------------------------------- AM_GNU_GETTEXT([external]) -#dnl We cannot use AC_DEFINE_UNQUOTED() for these definitions, as -#dnl we require make to do insert the proper $(datadir) value -#localedir="\$(datadir)/locale" -#AC_SUBST(localedir) -#AM_CPPFLAGS="$CPPFLAGS" -#AM_CPPFLAGS="$AM_CPPFLAGS -DLOCALEDIR=\\\"${localedir}\\\"" -#AC_SUBST(AM_CPPFLAGS) - # --------------------------------------------------------------------------- # Libtool support # --------------------------------------------------------------------------- @@ -50,12 +42,13 @@ AC_CHECK_LIBM() LIBS="$LIBS $LIBM" CHECK_ZLIB() AC_SUBST(HAVE_LIBZ,$HAVE_LIBZ) +AM_ICONV # --------------------------------------------------------------------------- # Checks for header files. # --------------------------------------------------------------------------- AC_HEADER_STDC -AC_CHECK_HEADERS([libintl.h malloc.h stdint.h stdlib.h string.h unistd.h wchar.h sys/mman.h]) +AC_CHECK_HEADERS([libintl.h locale.h malloc.h stdint.h stdlib.h string.h unistd.h sys/mman.h utime.h]) # --------------------------------------------------------------------------- # Checks for typedefs, structures, and compiler characteristics. @@ -66,6 +59,11 @@ AC_C_INLINE AC_TYPE_PID_T AC_TYPE_SIZE_T AC_STRUCT_TM +AC_TYPE_UINT8_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_INT16_T +AC_TYPE_INT32_T # --------------------------------------------------------------------------- # Checks for library functions. @@ -74,6 +72,7 @@ AC_FUNC_ALLOCA AC_FUNC_MALLOC AC_FUNC_MEMCMP AC_FUNC_MKTIME +AC_FUNC_MMAP AC_FUNC_REALLOC AC_FUNC_STAT AC_FUNC_STRERROR_R diff --git a/src/tags.cpp b/src/tags.cpp index f1d3b4a7..d133b2a6 100644 --- a/src/tags.cpp +++ b/src/tags.cpp @@ -32,9 +32,10 @@ EXIV2_RCSID("@(#) $Id$") // ***************************************************************************** // included header files +#include "types.hpp" #include "tags.hpp" #include "error.hpp" -#include "types.hpp" +#include "futils.hpp" #include "ifd.hpp" #include "value.hpp" #include "makernote.hpp" @@ -49,6 +50,10 @@ EXIV2_RCSID("@(#) $Id$") #include #include +#ifdef EXV_HAVE_ICONV +# include +#endif + // ***************************************************************************** // class member definitions namespace Exiv2 { @@ -459,6 +464,21 @@ namespace Exiv2 { N_("Contains four ASCII characters representing the TIFF/EP standard " "version of a TIFF/EP file, eg '1', '0', '0', '0'"), ifd0Id, otherTags, unsignedByte, printValue), // TIFF/EP Tag + TagInfo(0x9c9b, "XPTitle", N_("Windows Title"), + N_("Title tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag + TagInfo(0x9c9c, "XPComment", N_("Windows Comment"), + N_("Comment tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag + TagInfo(0x9c9d, "XPAuthor", N_("Windows Author"), + N_("Author tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag + TagInfo(0x9c9e, "XPKeywords", N_("Windows Keywords"), + N_("Keywords tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag + TagInfo(0x9c9f, "XPSubject", N_("Windows Subject"), + N_("Subject tag used by Windows, encoded in UCS2"), + ifd0Id, otherTags, unsignedByte, printUcs2), // Windows Tag // End of list marker TagInfo(0xffff, "(UnknownIfdTag)", N_("Unknown IFD tag"), N_("Unknown IFD tag"), @@ -1645,6 +1665,64 @@ namespace Exiv2 { return os; } // printDegrees + std::ostream& printUcs2(std::ostream& os, const Value& value) + { +#ifdef EXV_HAVE_ICONV + bool go = true; + iconv_t cd = (iconv_t)(-1); + if (value.typeId() != unsignedByte) { + go = false; + } + if (go) { + cd = iconv_open("UTF-8", "UCS-2LE"); + if (cd == (iconv_t)(-1)) { +#ifndef SUPPRESS_WARNINGS + std::cerr << "Warning: iconv_open: " << strError() << "\n"; +#endif + go = false; + } + } + if (go) { + DataBuf ib(value.size()); + value.copy(ib.pData_, invalidByteOrder); + DataBuf ob(value.size()); + char* outptr = reinterpret_cast(ob.pData_); + const char* outbuf = outptr; + size_t outbytesleft = ob.size_; + EXV_ICONV_CONST char* inbuf + = reinterpret_cast(ib.pData_); + size_t inbytesleft = ib.size_; + size_t rc = iconv(cd, + &inbuf, + &inbytesleft, + &outptr, + &outbytesleft); + if (rc == size_t(-1)) { +#ifndef SUPPRESS_WARNINGS + std::cerr << "Warning: iconv: " + << strError() + << " inbytesleft = " << inbytesleft << "\n"; +#endif + go = false; + } + if (go) { + // Todo: What if outbytesleft == 0 + os << std::string(outbuf, outptr-outbuf); + } + } + if (cd != (iconv_t)(-1)) { + iconv_close(cd); + } + if (!go) { + os << value; + } +#else // !EXV_HAVE_ICONV + os << value; +#endif // EXV_HAVE_ICONV + return os; + + } // printUcs2 + std::ostream& print0x0006(std::ostream& os, const Value& value) { std::ostringstream oss; diff --git a/src/tags.hpp b/src/tags.hpp index a1df4b37..b7c1ee56 100644 --- a/src/tags.hpp +++ b/src/tags.hpp @@ -442,6 +442,8 @@ namespace Exiv2 { std::ostream& printFloat(std::ostream& os, const Value& value); //! Print a longitude or latitude value std::ostream& printDegrees(std::ostream& os, const Value& value); + //! Print function converting from UCS-2LE to UTF-8 + std::ostream& printUcs2(std::ostream& os, const Value& value); //! Print GPS altitude std::ostream& print0x0006(std::ostream& os, const Value& value); diff --git a/test/bugfixes-test.sh b/test/bugfixes-test.sh index b47b11ef..05bcfc1b 100755 --- a/test/bugfixes-test.sh +++ b/test/bugfixes-test.sh @@ -54,6 +54,10 @@ num=447 # Problem only visible in Valgrind filename=`prep_file $num` $binpath/exiv2 -pi $filename +num=460 +filename=`prep_file $num` +$binpath/exiv2 -pt $filename + num=479 filename=`prep_file $num` $binpath/exiv2 -pt $filename diff --git a/test/data/bugfixes-test.out b/test/data/bugfixes-test.out index f1b3286f..3e9451f2 100644 --- a/test/data/bugfixes-test.out +++ b/test/data/bugfixes-test.out @@ -210,6 +210,12 @@ Warning: Exif tag 0x9286 has invalid Exif type 14; using 7 (undefined). Iptc.Application2.Caption String 0 Iptc.Application2.DateCreated Date 8 2005-08-09 Iptc.Application2.TimeCreated Time 11 01:28:31-07:00 +------> Bug 460 <------- +Exif.Image.XPTitle Byte 40 Titel und ähnliches +Exif.Image.XPComment Byte 46 And a standard comment +Exif.Image.XPAuthor Byte 44 Українська (Russian?) +Exif.Image.XPKeywords Byte 30 עברית (Hebrew) +Exif.Image.XPSubject Byte 32 తెలుగు (Telugu) ------> Bug 479 <------- Warning: IFD0: Pointer to next IFD is out of bounds; ignored. Exif.Image.ImageWidth Short 1 3173 diff --git a/test/data/exiv2-bug460.jpg b/test/data/exiv2-bug460.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d205de80363270d5a37fad3c16e2796f6d817c4f GIT binary patch literal 5364 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 Uc%G^1