From 641cedccd33e4ed368fcab5ec910a9176b204989 Mon Sep 17 00:00:00 2001 From: Pascal Massimino Date: Thu, 2 Mar 2017 08:45:42 -0800 Subject: [PATCH] imagedec: support metadata reading for WebP image decoding Needs to link imagedec.a to demux/libwebpdemux.a Change-Id: Id8f4068718b0e4a1e84607bccd5af5419120c231 --- CMakeLists.txt | 3 ++- Makefile.vc | 11 +++++++--- build.gradle | 4 ++++ configure.ac | 11 +++++----- examples/Android.mk | 8 +++---- examples/Makefile.am | 5 ++++- extras/Makefile.am | 5 ++++- imageio/Makefile.am | 5 ++++- imageio/webpdec.c | 51 ++++++++++++++++++++++++++++++++++++++------ makefile.unix | 8 ++++++- 10 files changed, 88 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c5d81de..79477a45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,7 +192,8 @@ if(WEBP_BUILD_CWEBP OR WEBP_BUILD_DWEBP OR parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS" "imagedec_[^ ]*") add_library(imagedec ${IMAGEDEC_SRCS}) - target_link_libraries(imagedec imageioutil webp ${WEBP_DEP_IMG_LIBRARIES}) + target_link_libraries(imagedec imageioutil webpdemux webp + ${WEBP_DEP_IMG_LIBRARIES}) # Image-encoding utility library. parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEENC_SRCS" diff --git a/Makefile.vc b/Makefile.vc index 31038e37..5d1bf865 100644 --- a/Makefile.vc +++ b/Makefile.vc @@ -368,9 +368,11 @@ $(DIRBIN)\anim_dump.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP) $(DIRBIN)\anim_dump.exe: $(IMAGEIO_ENC_OBJS) $(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(IMAGEIO_DEC_OBJS) $(DIRBIN)\cwebp.exe: $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\cwebp.exe: $(LIBWEBPDEMUX) $(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS) $(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS) $(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\dwebp.exe: $(LIBWEBPDEMUX) $(DIRBIN)\gif2webp.exe: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS) $(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX) $(DIRBIN)\gif2webp.exe: $(LIBWEBP) @@ -383,15 +385,18 @@ $(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX) $(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) $(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX) $(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS) -$(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) +$(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP) $(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj -$(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) +$(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\get_disto.exe: $(LIBWEBPDEMUX) $(LIBWEBP) $(DIRBIN)\webp_quality.exe: $(DIROBJ)\extras\webp_quality.obj $(DIRBIN)\webp_quality.exe: $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\webp_quality.exe: $(EXTRAS_OBJS) $(LIBWEBP) $(DIRBIN)\webpinfo.exe: $(DIROBJ)\examples\webpinfo.obj $(DIRBIN)\webpinfo.exe: $(IMAGEIO_DEC_OBJS) -$(DIRBIN)\webpinfo.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) +$(DIRBIN)\webpinfo.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) +$(DIRBIN)\webpinfo.exe: $(LIBWEBPDEMUX) $(LIBWEBP) $(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP) $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS): $(OUTPUT_DIRS) diff --git a/build.gradle b/build.gradle index 02c13e9c..88ad1290 100644 --- a/build.gradle +++ b/build.gradle @@ -289,6 +289,7 @@ model { imagedec(NativeLibrarySpec) { binaries { all { + lib library: "webpdemux", linkage: "static" lib library: "webp", linkage: "static" } } @@ -331,6 +332,7 @@ model { lib library: "example_util", linkage: "static" lib library: "imagedec", linkage: "static" lib library: "imageio_util", linkage: "static" + lib library: "webpdemux", linkage: "static" lib library: "webp", linkage: "static" } } @@ -351,6 +353,7 @@ model { lib library: "imagedec", linkage: "static" lib library: "imageenc", linkage: "static" lib library: "imageio_util", linkage: "static" + lib library: "webpdemux", linkage: "static" lib library: "webp" } } @@ -390,6 +393,7 @@ model { lib library: "imagedec", linkage: "static" lib library: "imageio_util", linkage: "static" lib library: "webpmux", linkage: "static" + lib library: "webpdemux", linkage: "static" lib library: "webp" } } diff --git a/configure.ac b/configure.ac index 757d1da3..ce38d6d2 100644 --- a/configure.ac +++ b/configure.ac @@ -601,7 +601,7 @@ AS_IF([test "x$enable_gif" != "xno"], [ AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_anim_diff}" = "yes"]) AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"]) -if test "$enable_libwebpmux" = "yes"; then +if test "$enable_libwebpdemux" = "yes" -a "$enable_libwebpmux" = "yes"; then build_img2webp=yes fi AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"]) @@ -702,8 +702,9 @@ AM_CONDITIONAL([WANT_MUX], [test "$enable_libwebpmux" = "yes"]) dnl === Check whether libwebpdemux should be built AC_MSG_CHECKING(whether libwebpdemux is to be built) AC_ARG_ENABLE([libwebpdemux], - AS_HELP_STRING([--enable-libwebpdemux], - [Build libwebpdemux @<:@default=no@:>@])) + AS_HELP_STRING([--disable-libwebpdemux], + [Disable libwebpdemux @<:@default=no@:>@]), + [], [enable_libwebpdemux=yes]) AC_MSG_RESULT(${enable_libwebpdemux-no}) AM_CONDITIONAL([WANT_DEMUX], [test "$enable_libwebpdemux" = "yes"]) @@ -752,14 +753,14 @@ libwebpmux: ${enable_libwebpmux-no} libwebpextras: ${enable_libwebpextras-no} Tools: -cwebp : yes +cwebp : ${enable_libwebpdemux-no} Input format support ==================== JPEG : ${jpeg_support-no} PNG : ${png_support-no} TIFF : ${tiff_support-no} WIC : ${wic_support-no} -dwebp : yes +dwebp : ${enable_libwebpdemux-no} Output format support ===================== PNG : ${png_support-no} diff --git a/examples/Android.mk b/examples/Android.mk index dd7364f5..486b8b80 100644 --- a/examples/Android.mk +++ b/examples/Android.mk @@ -27,7 +27,7 @@ LOCAL_SRC_FILES := \ LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src -LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webp +LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpdemux webp LOCAL_MODULE := cwebp @@ -43,8 +43,7 @@ LOCAL_SRC_FILES := \ LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src -LOCAL_STATIC_LIBRARIES := example_util imagedec imageenc webp - +LOCAL_STATIC_LIBRARIES := example_util imagedec imageenc webpdemux webp LOCAL_MODULE := dwebp include $(BUILD_EXECUTABLE) @@ -75,7 +74,8 @@ LOCAL_SRC_FILES := \ LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src -LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpmux webp +LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpmux webpdemux \ + webp LOCAL_MODULE := img2webp_example diff --git a/examples/Makefile.am b/examples/Makefile.am index 9bda97d3..e10872fd 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,6 +1,9 @@ AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src -bin_PROGRAMS = dwebp cwebp +bin_PROGRAMS = +if WANT_DEMUX + bin_PROGRAMS += dwebp cwebp +endif if BUILD_ANIMDIFF noinst_PROGRAMS = anim_diff anim_dump endif diff --git a/extras/Makefile.am b/extras/Makefile.am index 4123dbff..14d567a3 100644 --- a/extras/Makefile.am +++ b/extras/Makefile.am @@ -13,7 +13,10 @@ libwebpextras_la_LDFLAGS = -lm libwebpextras_la_LIBADD = ../src/libwebp.la noinst_PROGRAMS = -noinst_PROGRAMS += get_disto webp_quality +noinst_PROGRAMS += webp_quality +if WANT_DEMUX + noinst_PROGRAMS += get_disto +endif if BUILD_VWEBP_SDL noinst_PROGRAMS += vwebp_sdl endif diff --git a/imageio/Makefile.am b/imageio/Makefile.am index 14080689..b0e6d8e8 100644 --- a/imageio/Makefile.am +++ b/imageio/Makefile.am @@ -1,7 +1,9 @@ AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src noinst_LTLIBRARIES = noinst_LTLIBRARIES += libimageio_util.la -noinst_LTLIBRARIES += libimagedec.la +if WANT_DEMUX + noinst_LTLIBRARIES += libimagedec.la +endif noinst_LTLIBRARIES += libimageenc.la noinst_HEADERS = @@ -22,6 +24,7 @@ libimagedec_la_SOURCES += webpdec.c webpdec.h libimagedec_la_SOURCES += wicdec.c wicdec.h libimagedec_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES) libimagedec_la_CPPFLAGS += $(AM_CPPFLAGS) +libimagedec_la_LIBADD = ../src/demux/libwebpdemux.la libimageenc_la_SOURCES = libimageenc_la_SOURCES += image_enc.c image_enc.h diff --git a/imageio/webpdec.c b/imageio/webpdec.c index 82f646db..a9d06548 100644 --- a/imageio/webpdec.c +++ b/imageio/webpdec.c @@ -15,10 +15,12 @@ #include "./webpdec.h" +#include #include #include #include "webp/decode.h" +#include "webp/demux.h" #include "webp/encode.h" #include "./imageio_util.h" #include "./metadata.h" @@ -102,6 +104,40 @@ VP8StatusCode DecodeWebPIncremental( return status; } +// ----------------------------------------------------------------------------- +// Metadata + +static int ExtractMetadata(const uint8_t* const data, size_t data_size, + Metadata* const metadata) { + WebPData webp_data = { data, data_size }; + WebPDemuxer* const demux = WebPDemux(&webp_data); + WebPChunkIterator chunk_iter; + uint32_t flags; + + if (demux == NULL) return 0; + assert(metadata != NULL); + + flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); + + if ((flags & ICCP_FLAG) && WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter)) { + MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size, + &metadata->iccp); + WebPDemuxReleaseChunkIterator(&chunk_iter); + } + if ((flags & EXIF_FLAG) && WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter)) { + MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size, + &metadata->exif); + WebPDemuxReleaseChunkIterator(&chunk_iter); + } + if ((flags & XMP_FLAG) && WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter)) { + MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size, + &metadata->xmp); + WebPDemuxReleaseChunkIterator(&chunk_iter); + } + WebPDemuxDelete(demux); + return 1; +} + // ----------------------------------------------------------------------------- int ReadWebP(const uint8_t* const data, size_t data_size, @@ -115,11 +151,6 @@ int ReadWebP(const uint8_t* const data, size_t data_size, if (data == NULL || data_size == 0 || pic == NULL) return 0; - // TODO(jzern): add Exif/XMP/ICC extraction. - if (metadata != NULL) { - fprintf(stderr, "Warning: metadata extraction from WebP is unsupported.\n"); - } - if (!WebPInitDecoderConfig(&config)) { fprintf(stderr, "Library version mismatch!\n"); return 0; @@ -181,7 +212,6 @@ int ReadWebP(const uint8_t* const data, size_t data_size, status = DecodeWebP(data, data_size, &config); ok = (status == VP8_STATUS_OK); - if (!ok) WebPPictureFree(pic); if (ok && !keep_alpha && pic->use_argb) { // Need to wipe out the alpha value, as requested. int x, y; @@ -195,9 +225,18 @@ int ReadWebP(const uint8_t* const data, size_t data_size, if (status != VP8_STATUS_OK) { PrintWebPError("input data", status); + ok = 0; } WebPFreeDecBuffer(output_buffer); + + if (ok && metadata != NULL) { + ok = ExtractMetadata(data, data_size, metadata); + if (!ok) { + PrintWebPError("metadata", VP8_STATUS_BITSTREAM_ERROR); + } + } + if (!ok) WebPPictureFree(pic); return ok; } diff --git a/makefile.unix b/makefile.unix index 3cfb74c8..057b63ec 100644 --- a/makefile.unix +++ b/makefile.unix @@ -409,11 +409,13 @@ examples/anim_dump: src/libwebp.a examples/anim_dump: EXTRA_LIBS += $(GIF_LIBS) $(DWEBP_LIBS) examples/cwebp: examples/libexample_util.a examples/cwebp: imageio/libimagedec.a +examples/cwebp: src/demux/libwebpdemux.a examples/cwebp: imageio/libimageio_util.a examples/cwebp: src/libwebp.a examples/cwebp: EXTRA_LIBS += $(CWEBP_LIBS) examples/dwebp: examples/libexample_util.a examples/dwebp: imageio/libimagedec.a +examples/dwebp: src/demux/libwebpdemux.a examples/dwebp: imageio/libimageenc.a examples/dwebp: imageio/libimageio_util.a examples/dwebp: src/libwebp.a @@ -430,13 +432,17 @@ examples/webpmux: examples/libexample_util.a imageio/libimageio_util.a examples/webpmux: src/mux/libwebpmux.a src/libwebpdecoder.a examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a examples/img2webp: imageio/libimagedec.a +examples/img2webp: src/demux/libwebpdemux.a examples/img2webp: src/mux/libwebpmux.a src/libwebp.a examples/img2webp: EXTRA_LIBS += $(CWEBP_LIBS) examples/webpinfo: examples/libexample_util.a imageio/libimageio_util.a examples/webpinfo: src/libwebpdecoder.a extras/get_disto: extras/get_disto.o -extras/get_disto: imageio/libimagedec.a imageio/libimageio_util.a src/libwebp.a +extras/get_disto: imageio/libimagedec.a +extras/get_disto: src/demux/libwebpdemux.a +extras/get_disto: imageio/libimageio_util.a +extras/get_disto: src/libwebp.a extras/get_disto: EXTRA_LIBS += $(CWEBP_LIBS) extras/webp_quality: extras/webp_quality.o