Compare commits

..

1 Commits

Author SHA1 Message Date
86c756929c rescaler_mips32: disable ImportRowShrink
this function is failing the 'accum == 0' assert on skia bots for
rescaling to 13x13

BUG=skia:6682

Change-Id: I9f9f3adf28cec63ad6e38ed3128f18825d5b70cc
2017-06-02 19:58:33 -07:00
274 changed files with 8979 additions and 24225 deletions

1
.gitattributes vendored
View File

@ -1,6 +1,5 @@
.gitattributes export-ignore .gitattributes export-ignore
.gitignore export-ignore .gitignore export-ignore
.mailmap export-ignore .mailmap export-ignore
*.bat text eol=crlf
*.pdf -text -diff *.pdf -text -diff
*.ppm -text -diff *.ppm -text -diff

15
.gitignore vendored
View File

@ -1,7 +1,6 @@
*.l[ao] *.l[ao]
*.[ao] *.[ao]
*.pc *.pc
.DS_Store
.deps .deps
.libs .libs
/aclocal.m4 /aclocal.m4
@ -21,11 +20,9 @@
Makefile Makefile
Makefile.in Makefile.in
examples/anim_diff examples/anim_diff
examples/anim_dump
examples/[cdv]webp examples/[cdv]webp
examples/gif2webp examples/gif2webp
examples/img2webp examples/img2webp
examples/webpinfo
examples/webpmux examples/webpmux
src/webp/config.h* src/webp/config.h*
src/webp/stamp-h1 src/webp/stamp-h1
@ -34,21 +31,11 @@ src/webp/stamp-h1
*.idb *.idb
*.pdb *.pdb
/iosbuild /iosbuild
/xcframeworkbuild /WebP.framework
/WebP*.*framework
CMakeCache.txt CMakeCache.txt
CMakeFiles/ CMakeFiles/
cmake_install.cmake cmake_install.cmake
.gradle .gradle
/build /build
extras/get_disto extras/get_disto
extras/vwebp_sdl
extras/webp_quality extras/webp_quality
tests/fuzzer/advanced_api_fuzzer
tests/fuzzer/animation_api_fuzzer
tests/fuzzer/animdecoder_fuzzer
tests/fuzzer/animencoder_fuzzer
tests/fuzzer/demux_api_fuzzer
tests/fuzzer/enc_dec_fuzzer
tests/fuzzer/mux_demux_api_fuzzer
tests/fuzzer/simple_api_fuzzer

View File

@ -1,8 +1,7 @@
Johann Koenig <johann.koenig@duck.com> <johann.koenig@duck.com> <johannkoenig@google.com>
Johann Koenig <johann.koenig@duck.com> <johannkoenig@google.com>
Mikołaj Zalewski <mikolajz@google.com> Mikołaj Zalewski <mikolajz@google.com>
Pascal Massimino <pascal.massimino@gmail.com> Pascal Massimino <pascal.massimino@gmail.com>
Pascal Massimino <pascal.massimino@gmail.com> <skal@google.com> <pascal.massimino@gmail.com> <skal@google.com>
Vikas Arora <vikasa@google.com> Vikas Arora <vikasa@google.com>
<vikasa@google.com> <vikasa@gmail.com> <vikasa@google.com> <vikasa@gmail.com>
<vikasa@google.com> <vikaas.arora@gmail.com> <vikasa@google.com> <vikaas.arora@gmail.com>

11
AUTHORS
View File

@ -1,19 +1,14 @@
Contributors: Contributors:
- Aidan O'Loan (aidanol at gmail dot com)
- Alan Browning (browning at google dot com)
- Charles Munger (clm at google dot com) - Charles Munger (clm at google dot com)
- Cheng Yi (cyi at google dot com)
- Christian Duvivier (cduvivier at google dot com) - Christian Duvivier (cduvivier at google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com) - Djordje Pesut (djordje dot pesut at imgtec dot com)
- Hui Su (huisu at google dot com) - Hui Su (huisu at google dot com)
- Ingvar Stepanyan (rreverser at google dot com)
- James Zern (jzern at google dot com) - James Zern (jzern at google dot com)
- Jan Engelhardt (jengelh at medozas dot de) - Jan Engelhardt (jengelh at medozas dot de)
- Jehan (jehan at girinstud dot io) - Jehan (jehan at girinstud dot io)
- Johann Koenig (johann dot koenig at duck dot com) - Johann (johann dot koenig at duck dot com)
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com) - Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
- Jyrki Alakuijala (jyrki at google dot com) - Jyrki Alakuijala (jyrki at google dot com)
- Konstantin Ivlev (tomskside at gmail dot com)
- Lode Vandevenne (lode at google dot com) - Lode Vandevenne (lode at google dot com)
- Lou Quillio (louquillio at google dot com) - Lou Quillio (louquillio at google dot com)
- Mans Rullgard (mans at mansr dot com) - Mans Rullgard (mans at mansr dot com)
@ -23,7 +18,6 @@ Contributors:
- Mislav Bradac (mislavm at google dot com) - Mislav Bradac (mislavm at google dot com)
- Nico Weber (thakis at chromium dot org) - Nico Weber (thakis at chromium dot org)
- Noel Chromium (noel at chromium dot org) - Noel Chromium (noel at chromium dot org)
- Oliver Wolff (oliver dot wolff at qt dot io)
- Owen Rodley (orodley at google dot com) - Owen Rodley (orodley at google dot com)
- Parag Salasakar (img dot mips1 at gmail dot com) - Parag Salasakar (img dot mips1 at gmail dot com)
- Pascal Massimino (pascal dot massimino at gmail dot com) - Pascal Massimino (pascal dot massimino at gmail dot com)
@ -41,7 +35,4 @@ Contributors:
- Urvang Joshi (urvang at google dot com) - Urvang Joshi (urvang at google dot com)
- Vikas Arora (vikasa at google dot com) - Vikas Arora (vikasa at google dot com)
- Vincent Rabaud (vrabaud at google dot com) - Vincent Rabaud (vrabaud at google dot com)
- Vlad Tsyrklevich (vtsyrklevich at chromium dot org)
- Wan-Teh Chang (wtc at google dot com)
- Yang Zhang (yang dot zhang at arm dot com) - Yang Zhang (yang dot zhang at arm dot com)
- Yannis Guyon (yguyon at google dot com)

View File

@ -11,24 +11,12 @@ ifeq ($(APP_OPTIM),release)
endif endif
endif endif
# mips32 fails to build with clang from r14b
# https://bugs.chromium.org/p/webp/issues/detail?id=343
ifeq ($(findstring clang,$(NDK_TOOLCHAIN_VERSION)),clang)
ifeq ($(TARGET_ARCH),mips)
clang_version := $(shell $(TARGET_CC) --version)
ifneq ($(findstring clang version 3,$(clang_version)),)
WEBP_CFLAGS += -no-integrated-as
endif
endif
endif
ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),) ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),)
# Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal # Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal
# instructions to be generated for armv7a code. Instead target the neon code # instructions to be generated for armv7a code. Instead target the neon code
# specifically. # specifically.
NEON := c.neon NEON := c.neon
USE_CPUFEATURES := yes USE_CPUFEATURES := yes
WEBP_CFLAGS += -DHAVE_CPU_FEATURES_H
else else
NEON := c NEON := c
endif endif
@ -55,6 +43,9 @@ dsp_dec_srcs := \
src/dsp/alpha_processing_neon.$(NEON) \ src/dsp/alpha_processing_neon.$(NEON) \
src/dsp/alpha_processing_sse2.c \ src/dsp/alpha_processing_sse2.c \
src/dsp/alpha_processing_sse41.c \ src/dsp/alpha_processing_sse41.c \
src/dsp/argb.c \
src/dsp/argb_mips_dsp_r2.c \
src/dsp/argb_sse2.c \
src/dsp/cpu.c \ src/dsp/cpu.c \
src/dsp/dec.c \ src/dsp/dec.c \
src/dsp/dec_clip_tables.c \ src/dsp/dec_clip_tables.c \
@ -85,21 +76,18 @@ dsp_dec_srcs := \
src/dsp/upsampling_msa.c \ src/dsp/upsampling_msa.c \
src/dsp/upsampling_neon.$(NEON) \ src/dsp/upsampling_neon.$(NEON) \
src/dsp/upsampling_sse2.c \ src/dsp/upsampling_sse2.c \
src/dsp/upsampling_sse41.c \
src/dsp/yuv.c \ src/dsp/yuv.c \
src/dsp/yuv_mips32.c \ src/dsp/yuv_mips32.c \
src/dsp/yuv_mips_dsp_r2.c \ src/dsp/yuv_mips_dsp_r2.c \
src/dsp/yuv_neon.$(NEON) \
src/dsp/yuv_sse2.c \ src/dsp/yuv_sse2.c \
src/dsp/yuv_sse41.c \
dsp_enc_srcs := \ dsp_enc_srcs := \
src/dsp/cost.c \ src/dsp/cost.c \
src/dsp/cost_mips32.c \ src/dsp/cost_mips32.c \
src/dsp/cost_mips_dsp_r2.c \ src/dsp/cost_mips_dsp_r2.c \
src/dsp/cost_neon.$(NEON) \
src/dsp/cost_sse2.c \ src/dsp/cost_sse2.c \
src/dsp/enc.c \ src/dsp/enc.c \
src/dsp/enc_avx2.c \
src/dsp/enc_mips32.c \ src/dsp/enc_mips32.c \
src/dsp/enc_mips_dsp_r2.c \ src/dsp/enc_mips_dsp_r2.c \
src/dsp/enc_msa.c \ src/dsp/enc_msa.c \
@ -113,16 +101,14 @@ dsp_enc_srcs := \
src/dsp/lossless_enc_neon.$(NEON) \ src/dsp/lossless_enc_neon.$(NEON) \
src/dsp/lossless_enc_sse2.c \ src/dsp/lossless_enc_sse2.c \
src/dsp/lossless_enc_sse41.c \ src/dsp/lossless_enc_sse41.c \
src/dsp/ssim.c \
src/dsp/ssim_sse2.c \
enc_srcs := \ enc_srcs := \
src/enc/alpha_enc.c \ src/enc/alpha_enc.c \
src/enc/analysis_enc.c \ src/enc/analysis_enc.c \
src/enc/backward_references_cost_enc.c \
src/enc/backward_references_enc.c \ src/enc/backward_references_enc.c \
src/enc/config_enc.c \ src/enc/config_enc.c \
src/enc/cost_enc.c \ src/enc/cost_enc.c \
src/enc/delta_palettization_enc.c \
src/enc/filter_enc.c \ src/enc/filter_enc.c \
src/enc/frame_enc.c \ src/enc/frame_enc.c \
src/enc/histogram_enc.c \ src/enc/histogram_enc.c \
@ -174,7 +160,7 @@ LOCAL_SRC_FILES := \
$(utils_dec_srcs) \ $(utils_dec_srcs) \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
# prefer arm over thumb mode for performance gains # prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm
@ -208,7 +194,7 @@ LOCAL_SRC_FILES := \
$(utils_enc_srcs) \ $(utils_enc_srcs) \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
# prefer arm over thumb mode for performance gains # prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm
@ -231,7 +217,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(demux_srcs) LOCAL_SRC_FILES := $(demux_srcs)
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
# prefer arm over thumb mode for performance gains # prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm
@ -254,7 +240,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(mux_srcs) LOCAL_SRC_FILES := $(mux_srcs)
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
# prefer arm over thumb mode for performance gains # prefer arm over thumb mode for performance gains
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm

View File

@ -1,724 +1,189 @@
## cmake_minimum_required(VERSION 2.8.7)
## Copyright (c) 2020 Google LLC.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
cmake_minimum_required(VERSION 3.5) project(libwebp C)
project(WebP C)
# Options for coder / decoder executables. # Options for coder / decoder executables.
if(NOT EMSCRIPTEN) option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." OFF)
# Disable SIMD on Emscripten by default, as it's a new unstable Wasm feature. option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." OFF)
# Users can still explicitly opt-in to make a SIMD-enabled build. option(WEBP_BUILD_GIF2WEBP "Build the gif2webp conversion tool." OFF)
set(WEBP_ENABLE_SIMD_DEFAULT ON) option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." OFF)
endif() option(WEBP_EXPERIMENTAL_FEATURES "Build with experimental features." OFF)
option(WEBP_ENABLE_SIMD "Enable any SIMD optimization." option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces." OFF)
${WEBP_ENABLE_SIMD_DEFAULT})
option(WEBP_BUILD_ANIM_UTILS "Build animation utilities." ON)
option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." ON)
option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." ON)
option(WEBP_BUILD_GIF2WEBP "Build the gif2webp conversion tool." ON)
option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." ON)
option(WEBP_BUILD_VWEBP "Build the vwebp viewer tool." ON)
option(WEBP_BUILD_WEBPINFO "Build the webpinfo command line tool." ON)
option(WEBP_BUILD_WEBPMUX "Build the webpmux command line tool." ON)
option(WEBP_BUILD_EXTRAS "Build extras." ON)
option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF)
option(WEBP_NEAR_LOSSLESS "Enable near-lossless encoding" ON)
option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces."
OFF)
set(WEBP_BITTRACE "0" CACHE STRING "Bit trace mode (0=none, 1=bit, 2=bytes)")
set_property(CACHE WEBP_BITTRACE PROPERTY STRINGS 0 1 2)
# Option needed for handling Unicode file names on Windows.
if(WIN32)
option(WEBP_UNICODE "Build Unicode executables." ON)
endif()
if(WEBP_BUILD_WEBP_JS)
set(WEBP_BUILD_ANIM_UTILS OFF)
set(WEBP_BUILD_CWEBP OFF)
set(WEBP_BUILD_DWEBP OFF)
set(WEBP_BUILD_GIF2WEBP OFF)
set(WEBP_BUILD_IMG2WEBP OFF)
set(WEBP_BUILD_VWEBP OFF)
set(WEBP_BUILD_WEBPINFO OFF)
set(WEBP_BUILD_WEBPMUX OFF)
set(WEBP_BUILD_EXTRAS OFF)
if(WEBP_ENABLE_SIMD)
message("wasm2js does not support SIMD, disabling webp.js generation.")
endif()
endif()
set(WEBP_DEP_LIBRARIES) set(WEBP_DEP_LIBRARIES)
set(WEBP_DEP_INCLUDE_DIRS) set(WEBP_DEP_INCLUDE_DIRS)
if(NOT CMAKE_BUILD_TYPE) if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" set(CMAKE_BUILD_TYPE "Release" CACHE
CACHE STRING "Build type: Release, Debug, MinSizeRel or RelWithDebInfo" "Build type: Release, Debug or RelWithDebInfo" STRING FORCE
FORCE) )
endif() endif()
# Include dependencies. include(cmake/config.h.cmake)
include(cmake/deps.cmake)
include(GNUInstallDirs)
# ############################################################################## ################################################################################
# Options. # Options.
if(WEBP_ENABLE_SWAP_16BIT_CSP) if(WEBP_ENABLE_SWAP_16BIT_CSP)
add_definitions(-DWEBP_SWAP_16BIT_CSP=1) add_definitions(-DWEBP_SWAP_16BIT_CSP)
endif() endif()
if(NOT WEBP_BITTRACE STREQUAL "0") ################################################################################
add_definitions(-DBITTRACE=${WEBP_BITTRACE})
endif()
if(WEBP_UNICODE)
# Windows recommends setting both UNICODE and _UNICODE.
add_definitions(-DUNICODE -D_UNICODE)
endif()
set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix "\$\{prefix\}")
set(libdir "\$\{prefix\}/lib")
set(includedir "\$\{prefix\}/include")
set(PTHREAD_LIBS ${CMAKE_THREAD_LIBS_INIT})
set(INSTALLED_LIBRARIES)
# ##############################################################################
# Android only. # Android only.
if(ANDROID) if(ANDROID)
include_directories(${ANDROID_NDK}/sources/android/cpufeatures) include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
add_library(cpufeatures STATIC add_library(cpufeatures STATIC
${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c) ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c
list(APPEND INSTALLED_LIBRARIES cpufeatures) )
target_link_libraries(cpufeatures dl) target_link_libraries(cpufeatures dl)
set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures) set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures)
set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS} set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS}
${ANDROID_NDK}/sources/android/cpufeatures) ${ANDROID_NDK}/sources/android/cpufeatures
add_definitions(-DHAVE_CPU_FEATURES_H=1) )
set(HAVE_CPU_FEATURES_H 1)
else()
set(HAVE_CPU_FEATURES_H 0)
endif() endif()
function(configure_pkg_config FILE) ################################################################################
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.in" # WebP source files.
"${CMAKE_CURRENT_BINARY_DIR}/${FILE}") # Read the Makefile.am to get the source files.
if(HAVE_MATH_LIBRARY) function(parse_Makefile_am FOLDER VAR)
# MSVC doesn't have libm
file(READ ${CMAKE_CURRENT_BINARY_DIR}/${FILE} data)
string(REPLACE "-lm" "" data ${data})
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${FILE} ${data})
endif()
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/${FILE}"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
endfunction()
# ##############################################################################
# WebP source files. Read the Makefile.am to get the source files.
# We expect the Makefiles to define the sources as defined in the first regex.
# E.g.: libimagedec_la_SOURCES = image_dec.c image_dec.h
function(parse_Makefile_am FOLDER VAR SRC_REGEX)
file(READ ${FOLDER}/Makefile.am MAKEFILE_AM) file(READ ${FOLDER}/Makefile.am MAKEFILE_AM)
string(REGEX MATCHALL string(REGEX MATCHALL "_SOURCES \\+= [^\n]*"
"${SRC_REGEX}_SOURCES[ ]*\\+?=[ ]+[0-9a-z\\._ ]*" FILES_PER_LINE ${MAKEFILE_AM}
FILES_PER_LINE )
${MAKEFILE_AM})
set(SRCS ${${VAR}}) set(SRCS ${${VAR}})
foreach(FILES ${FILES_PER_LINE}) foreach(FILES ${FILES_PER_LINE})
string(FIND ${FILES} "=" OFFSET) string(SUBSTRING ${FILES} 12 -1 FILES)
math(EXPR OFFSET "${OFFSET} + 2") string(REGEX MATCHALL "[0-9a-z\\._]+"
string(SUBSTRING ${FILES} FILES ${FILES}
${OFFSET} )
-1 foreach(FILE ${FILES})
FILES) list(APPEND SRCS ${FOLDER}/${FILE})
if(FILES) endforeach()
string(REGEX MATCHALL
"[0-9a-z\\._]+"
FILES
${FILES})
foreach(FILE ${FILES})
list(APPEND SRCS ${FOLDER}/${FILE})
endforeach()
endif()
endforeach() endforeach()
set(${VAR} ${SRCS} PARENT_SCOPE) set(${VAR} ${SRCS} PARENT_SCOPE)
endfunction() endfunction()
set(WEBP_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) set(WEBP_SRCS)
parse_makefile_am(${WEBP_SRC_DIR}/dec "WEBP_DEC_SRCS" "") parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/dec "WEBP_SRCS")
parse_makefile_am(${WEBP_SRC_DIR}/demux "WEBP_DEMUX_SRCS" "") parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/demux "WEBP_SRCS")
parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_COMMON_SRCS" "COMMON") parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/dsp "WEBP_SRCS")
parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "ENC") parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/enc "WEBP_SRCS")
parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "dsp_[^ ]*") parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/utils "WEBP_SRCS")
parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_DEC_SRCS" "decode_[^ ]*")
parse_makefile_am(${WEBP_SRC_DIR}/enc "WEBP_ENC_SRCS" "")
parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_COMMON_SRCS" "COMMON")
parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_ENC_SRCS" "ENC")
parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_DEC_SRCS" "decode_[^ ]*")
# Remove the files specific to SIMD we don't use. # Remove the files specific to SIMD we don't use.
foreach(FILE ${WEBP_SIMD_FILES_NOT_TO_INCLUDE}) foreach(FILE ${WEBP_SIMD_FILES_NOT_TO_INCLUDE})
list(REMOVE_ITEM WEBP_DSP_ENC_SRCS ${FILE}) list(REMOVE_ITEM WEBP_SRCS ${FILE})
list(REMOVE_ITEM WEBP_DSP_DEC_SRCS ${FILE})
endforeach() endforeach()
# Generate the config.h file. # Build the library.
configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in add_definitions(-Wall)
${CMAKE_CURRENT_BINARY_DIR}/src/webp/config.h) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/ ${WEBP_DEP_INCLUDE_DIRS})
add_definitions(-DHAVE_CONFIG_H) add_library(webp ${WEBP_SRCS})
# ##############################################################################
# Build the webpdecoder library.
# Creates a source file with an unused stub function in $CMAKE_BINARY_DIR and
# adds it to the specified target. Currently used only with Xcode.
#
# See also:
# https://cmake.org/cmake/help/v3.18/command/add_library.html#object-libraries
# "Some native build systems (such as Xcode) may not like targets that have
# only object files, so consider adding at least one real source file to any
# target that references $<TARGET_OBJECTS:objlib>."
function(libwebp_add_stub_file TARGET)
set(stub_source_dir "${CMAKE_BINARY_DIR}")
set(stub_source_file
"${stub_source_dir}/libwebp_${TARGET}_stub.c")
set(stub_source_code
"// Generated file. DO NOT EDIT!\n"
"// C source file created for target ${TARGET}.\n"
"void libwebp_${TARGET}_stub_function(void)\;\n"
"void libwebp_${TARGET}_stub_function(void) {}\n")
file(WRITE "${stub_source_file}" ${stub_source_code})
target_sources(${TARGET} PRIVATE ${stub_source_file})
endfunction()
if(MSVC)
# avoid security warnings for e.g., fopen() used in the examples.
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
else()
add_definitions(-Wall)
endif()
include_directories(${WEBP_DEP_INCLUDE_DIRS})
add_library(webpdecode OBJECT ${WEBP_DEC_SRCS})
target_include_directories(webpdecode
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS})
target_include_directories(webpdspdecode
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webputilsdecode
OBJECT
${WEBP_UTILS_COMMON_SRCS}
${WEBP_UTILS_DEC_SRCS})
target_include_directories(webputilsdecode
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webpdecoder
$<TARGET_OBJECTS:webpdecode>
$<TARGET_OBJECTS:webpdspdecode>
$<TARGET_OBJECTS:webputilsdecode>)
if(XCODE)
libwebp_add_stub_file(webpdecoder)
endif()
target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES})
target_include_directories(
webpdecoder
PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
set_target_properties(
webpdecoder
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
configure_pkg_config("src/libwebpdecoder.pc")
# Build the webp library.
add_library(webpencode OBJECT ${WEBP_ENC_SRCS})
target_include_directories(webpencode
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webpdsp
OBJECT
${WEBP_DSP_COMMON_SRCS}
${WEBP_DSP_DEC_SRCS}
${WEBP_DSP_ENC_SRCS})
target_include_directories(webpdsp
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webputils
OBJECT
${WEBP_UTILS_COMMON_SRCS}
${WEBP_UTILS_DEC_SRCS}
${WEBP_UTILS_ENC_SRCS})
target_include_directories(webputils
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
add_library(webp
$<TARGET_OBJECTS:webpdecode>
$<TARGET_OBJECTS:webpdsp>
$<TARGET_OBJECTS:webpencode>
$<TARGET_OBJECTS:webputils>)
if(XCODE)
libwebp_add_stub_file(webp)
endif()
target_link_libraries(webp ${WEBP_DEP_LIBRARIES}) target_link_libraries(webp ${WEBP_DEP_LIBRARIES})
target_include_directories(webp
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
PUBLIC $<INSTALL_INTERFACE:include>)
set_target_properties(
webp
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/encode.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
# Make sure the OBJECT libraries are built with position independent code (it is # Change the compile flags for SIMD files we use.
# not ON by default).
set_target_properties(webpdecode
webpdspdecode
webputilsdecode
webpencode
webpdsp
webputils
PROPERTIES POSITION_INDEPENDENT_CODE ON)
configure_pkg_config("src/libwebp.pc")
# Build the webp demux library.
add_library(webpdemux ${WEBP_DEMUX_SRCS})
target_link_libraries(webpdemux webp)
target_include_directories(webpdemux
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
PUBLIC $<INSTALL_INTERFACE:include>)
set_target_properties(
webpdemux
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
configure_pkg_config("src/demux/libwebpdemux.pc")
# Set the version numbers.
function(parse_version FILE NAME VAR)
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/src/${FILE} SOURCE_FILE)
string(REGEX MATCH
"${NAME}_la_LDFLAGS[^\n]* -version-info [0-9:]+"
TMP
${SOURCE_FILE})
string(REGEX MATCH
"[0-9:]+"
TMP
${TMP})
string(REGEX
REPLACE ":"
"."
VERSION
${TMP})
set(${VAR} "${VERSION}" PARENT_SCOPE)
endfunction()
parse_version(Makefile.am webp WEBP_WEBP_SOVERSION)
set_target_properties(webp
PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_WEBP_SOVERSION})
parse_version(Makefile.am webpdecoder WEBP_DECODER_SOVERSION)
set_target_properties(webpdecoder
PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_DECODER_SOVERSION})
parse_version(demux/Makefile.am webpdemux WEBP_DEMUX_SOVERSION)
set_target_properties(webpdemux
PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_DEMUX_SOVERSION})
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_FILE)
string(REGEX MATCH
"AC_INIT\\([^\n]*\\[[0-9\\.]+\\]"
TMP
${CONFIGURE_FILE})
string(REGEX MATCH
"[0-9\\.]+"
PROJECT_VERSION
${TMP})
# Define the libraries to install.
list(APPEND INSTALLED_LIBRARIES webpdecoder webp webpdemux)
# Deal with SIMD. Change the compile flags for SIMD files we use.
list(LENGTH WEBP_SIMD_FILES_TO_INCLUDE WEBP_SIMD_FILES_TO_INCLUDE_LENGTH) list(LENGTH WEBP_SIMD_FILES_TO_INCLUDE WEBP_SIMD_FILES_TO_INCLUDE_LENGTH)
math(EXPR WEBP_SIMD_FILES_TO_INCLUDE_RANGE math(EXPR WEBP_SIMD_FILES_TO_INCLUDE_RANGE
"${WEBP_SIMD_FILES_TO_INCLUDE_LENGTH}-1") "${WEBP_SIMD_FILES_TO_INCLUDE_LENGTH}-1"
)
foreach(I_FILE RANGE ${WEBP_SIMD_FILES_TO_INCLUDE_RANGE}) foreach(I_FILE RANGE ${WEBP_SIMD_FILES_TO_INCLUDE_RANGE})
list(GET WEBP_SIMD_FILES_TO_INCLUDE ${I_FILE} FILE) list(GET WEBP_SIMD_FILES_TO_INCLUDE ${I_FILE} FILE)
list(GET WEBP_SIMD_FLAGS_TO_INCLUDE ${I_FILE} SIMD_COMPILE_FLAG) list(GET WEBP_SIMD_FLAGS_TO_INCLUDE ${I_FILE} SIMD_COMPILE_FLAG)
set_source_files_properties(${FILE} set_source_files_properties(${FILE} PROPERTIES
PROPERTIES COMPILE_FLAGS ${SIMD_COMPILE_FLAG}
COMPILE_FLAGS )
${SIMD_COMPILE_FLAG})
endforeach() endforeach()
if(WEBP_BUILD_GIF2WEBP AND NOT GIF_FOUND)
set(WEBP_BUILD_GIF2WEBP OFF)
endif()
if(WEBP_BUILD_ANIM_UTILS AND NOT GIF_FOUND)
set(WEBP_BUILD_ANIM_UTILS OFF)
endif()
# Build the executables if asked for. # Build the executables if asked for.
if(WEBP_BUILD_ANIM_UTILS if(WEBP_BUILD_CWEBP OR WEBP_BUILD_DWEBP OR
OR WEBP_BUILD_CWEBP WEBP_BUILD_GIF2WEBP OR WEBP_BUILD_IMG2WEBP)
OR WEBP_BUILD_DWEBP
OR WEBP_BUILD_GIF2WEBP
OR WEBP_BUILD_IMG2WEBP
OR WEBP_BUILD_VWEBP)
# Example utility library. # Example utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "EXAMPLEUTIL_SRCS" set(exampleutil_SRCS
"example_util_[^ ]*") ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h
list(APPEND EXAMPLEUTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h) ${CMAKE_CURRENT_SOURCE_DIR}/examples/example_util.c
add_library(exampleutil STATIC ${EXAMPLEUTIL_SRCS}) ${CMAKE_CURRENT_SOURCE_DIR}/examples/example_util.h)
target_link_libraries(exampleutil imageioutil) add_library(exampleutil ${exampleutil_SRCS})
target_include_directories( target_link_libraries(exampleutil webp ${WEBP_DEP_LIBRARIES})
exampleutil
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEIOUTILS_SRCS" set(imageioutil_SRCS
"imageio_util_[^ ]*") ${CMAKE_CURRENT_SOURCE_DIR}/imageio/imageio_util.c
add_library(imageioutil STATIC ${IMAGEIOUTILS_SRCS}) ${CMAKE_CURRENT_SOURCE_DIR}/imageio/imageio_util.h)
target_link_libraries(imageioutil webp) add_library(imageioutil ${imageioutil_SRCS})
target_link_libraries(imageioutil ${WEBP_DEP_LIBRARIES})
# Image-decoding utility library. # Image-decoding utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS" set(imagedec_SRCS
"imagedec_[^ ]*") ${CMAKE_CURRENT_SOURCE_DIR}/examples/gifdec.c
add_library(imagedec STATIC ${IMAGEDEC_SRCS}) ${CMAKE_CURRENT_SOURCE_DIR}/examples/gifdec.h
target_link_libraries(imagedec ${CMAKE_CURRENT_SOURCE_DIR}/imageio/image_dec.c
imageioutil ${CMAKE_CURRENT_SOURCE_DIR}/imageio/image_dec.h
webpdemux ${CMAKE_CURRENT_SOURCE_DIR}/imageio/jpegdec.c
webp ${CMAKE_CURRENT_SOURCE_DIR}/imageio/jpegdec.h
${WEBP_DEP_IMG_LIBRARIES}) ${CMAKE_CURRENT_SOURCE_DIR}/imageio/metadata.c
${CMAKE_CURRENT_SOURCE_DIR}/imageio/metadata.h
${CMAKE_CURRENT_SOURCE_DIR}/imageio/pngdec.c
${CMAKE_CURRENT_SOURCE_DIR}/imageio/pngdec.h
${CMAKE_CURRENT_SOURCE_DIR}/imageio/tiffdec.c
${CMAKE_CURRENT_SOURCE_DIR}/imageio/tiffdec.h
${CMAKE_CURRENT_SOURCE_DIR}/imageio/webpdec.c
${CMAKE_CURRENT_SOURCE_DIR}/imageio/webpdec.h
${CMAKE_CURRENT_SOURCE_DIR}/imageio/wicdec.c
${CMAKE_CURRENT_SOURCE_DIR}/imageio/wicdec.h)
add_library(imagedec ${imagedec_SRCS})
target_link_libraries(imagedec webp ${WEBP_DEP_LIBRARIES}
${WEBP_DEP_IMG_LIBRARIES})
# Image-encoding utility library. # Image-encoding utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEENC_SRCS" set(imageenc_SRCS
"imageenc_[^ ]*") ${CMAKE_CURRENT_SOURCE_DIR}/imageio/image_enc.c
add_library(imageenc STATIC ${IMAGEENC_SRCS}) ${CMAKE_CURRENT_SOURCE_DIR}/imageio/image_enc.h)
target_link_libraries(imageenc imageioutil webp) add_library(imageenc ${imageenc_SRCS})
target_link_libraries(imageenc webp imageioutil
set_property(TARGET exampleutil ${WEBP_DEP_LIBRARIES} ${WEBP_DEP_IMG_LIBRARIES})
imageioutil
imagedec
imageenc
PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}/src)
endif() endif()
if(WEBP_BUILD_DWEBP) if(WEBP_BUILD_DWEBP)
# dwebp # dwebp
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "DWEBP_SRCS" "dwebp") include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
add_executable(dwebp ${DWEBP_SRCS}) add_executable(dwebp
target_link_libraries(dwebp exampleutil imagedec imageenc) ${CMAKE_CURRENT_SOURCE_DIR}/examples/dwebp.c
target_include_directories(dwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h)
install(TARGETS dwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) target_link_libraries(dwebp imagedec imageenc webp
exampleutil imageioutil
${WEBP_DEP_LIBRARIES} ${WEBP_DEP_IMG_LIBRARIES}
)
endif() endif()
if(WEBP_BUILD_CWEBP) if(WEBP_BUILD_CWEBP)
# cwebp # cwebp
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "CWEBP_SRCS" "cwebp") include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
add_executable(cwebp ${CWEBP_SRCS}) add_executable(cwebp
target_link_libraries(cwebp exampleutil imagedec webp) ${CMAKE_CURRENT_SOURCE_DIR}/examples/cwebp.c
target_include_directories(cwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src) ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h)
install(TARGETS cwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) target_link_libraries(cwebp imagedec webp exampleutil imageioutil
endif() ${WEBP_DEP_LIBRARIES} ${WEBP_DEP_IMG_LIBRARIES}
)
if(WEBP_BUILD_GIF2WEBP OR WEBP_BUILD_IMG2WEBP)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/mux "WEBP_MUX_SRCS" "")
add_library(libwebpmux ${WEBP_MUX_SRCS})
target_link_libraries(libwebpmux webp)
target_include_directories(libwebpmux
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
parse_version(mux/Makefile.am webpmux WEBP_MUX_SOVERSION)
set_target_properties(libwebpmux
PROPERTIES VERSION
${PACKAGE_VERSION}
SOVERSION
${WEBP_MUX_SOVERSION})
set_target_properties(libwebpmux
PROPERTIES PUBLIC_HEADER
"${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h;")
set_target_properties(libwebpmux PROPERTIES OUTPUT_NAME webpmux)
list(APPEND INSTALLED_LIBRARIES libwebpmux)
configure_pkg_config("src/mux/libwebpmux.pc")
endif() endif()
if(WEBP_BUILD_GIF2WEBP) if(WEBP_BUILD_GIF2WEBP)
# gif2webp # gif2webp
include_directories(${WEBP_DEP_GIF_INCLUDE_DIRS}) include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "GIF2WEBP_SRCS" set(GIF2WEBP_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/gif2webp.c)
"gif2webp") parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/mux "GIF2WEBP_SRCS")
add_executable(gif2webp ${GIF2WEBP_SRCS}) add_executable(gif2webp ${GIF2WEBP_SRCS})
target_link_libraries(gif2webp target_link_libraries(gif2webp imagedec webp exampleutil imageioutil
exampleutil ${WEBP_DEP_LIBRARIES} ${WEBP_DEP_IMG_LIBRARIES}
imageioutil )
webp
libwebpmux
${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(gif2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS gif2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
if(WEBP_BUILD_IMG2WEBP) if(WEBP_BUILD_IMG2WEBP)
# img2webp # img2webp
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS}) include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "IMG2WEBP_SRCS" set(IMG2WEBP_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/img2webp.c)
"img2webp") parse_Makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/mux "IMG2WEBP_SRCS")
add_executable(img2webp ${IMG2WEBP_SRCS}) add_executable(img2webp ${IMG2WEBP_SRCS})
target_link_libraries(img2webp target_link_libraries(img2webp imagedec webp exampleutil imageioutil
exampleutil ${WEBP_DEP_LIBRARIES} ${WEBP_DEP_IMG_LIBRARIES}
imagedec )
imageioutil
webp
libwebpmux)
target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS img2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
if(WEBP_BUILD_VWEBP)
# vwebp
find_package(GLUT)
if(GLUT_FOUND)
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "VWEBP_SRCS" "vwebp")
add_executable(vwebp ${VWEBP_SRCS})
target_link_libraries(vwebp
${OPENGL_LIBRARIES}
exampleutil
${GLUT_glut_LIBRARY}
imageioutil
webp
webpdemux)
target_include_directories(vwebp
PRIVATE ${GLUT_INCLUDE_DIR}
${CMAKE_CURRENT_BINARY_DIR}/src
${OPENGL_INCLUDE_DIR})
install(TARGETS vwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
check_c_compiler_flag("-Wno-deprecated-declarations" HAS_NO_DEPRECATED)
if(HAS_NO_DEPRECATED)
target_compile_options(vwebp PRIVATE "-Wno-deprecated-declarations")
endif()
endif()
endif()
endif()
if(WEBP_BUILD_WEBPINFO)
# webpinfo
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "WEBPINFO_SRCS"
"webpinfo")
add_executable(webpinfo ${WEBPINFO_SRCS})
target_link_libraries(webpinfo exampleutil imageioutil)
target_include_directories(webpinfo PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS webpinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(WEBP_BUILD_WEBPMUX)
# webpmux
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "WEBPMUX_SRCS"
"webpmux")
add_executable(webpmux ${WEBPMUX_SRCS})
target_link_libraries(webpmux exampleutil imageioutil libwebpmux webp)
target_include_directories(webpmux PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS webpmux RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(WEBP_BUILD_EXTRAS)
set(EXTRAS_MAKEFILE "${CMAKE_CURRENT_SOURCE_DIR}/extras")
parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_EXTRAS_SRCS" "libwebpextras_la")
parse_makefile_am(${EXTRAS_MAKEFILE} "GET_DISTO_SRCS" "get_disto")
parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_QUALITY_SRCS" "webp_quality")
parse_makefile_am(${EXTRAS_MAKEFILE} "VWEBP_SDL_SRCS" "vwebp_sdl")
# get_disto
add_executable(get_disto ${GET_DISTO_SRCS})
target_link_libraries(get_disto imagedec)
target_include_directories(get_disto
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}/src)
install(TARGETS get_disto RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# webp_quality
add_executable(webp_quality ${WEBP_QUALITY_SRCS} ${WEBP_EXTRAS_SRCS})
target_link_libraries(webp_quality exampleutil imagedec)
target_include_directories(webp_quality
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR})
install(TARGETS webp_quality RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# vwebp_sdl
find_package(SDL)
if(SDL_FOUND)
add_executable(vwebp_sdl ${VWEBP_SDL_SRCS})
target_link_libraries(vwebp_sdl ${SDL_LIBRARY} imageioutil webp)
target_include_directories(vwebp_sdl
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/src
${SDL_INCLUDE_DIR})
set(WEBP_HAVE_SDL 1)
target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL)
install(TARGETS vwebp_sdl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
endif()
if(WEBP_BUILD_WEBP_JS)
# wasm2js does not support SIMD.
if(NOT WEBP_ENABLE_SIMD)
# JavaScript version
add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
target_link_libraries(webp_js webpdecoder SDL)
target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set(WEBP_HAVE_SDL 1)
set_target_properties(
webp_js
PROPERTIES LINK_FLAGS "-s WASM=0 \
-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp)
target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
endif()
# WASM version
add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
target_link_libraries(webp_wasm webpdecoder SDL)
target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set_target_properties(
webp_wasm
PROPERTIES LINK_FLAGS "-s WASM=1 \
-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN)
endif()
if(WEBP_BUILD_ANIM_UTILS)
# anim_diff
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS} ${WEBP_DEP_GIF_INCLUDE_DIRS})
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DIFF_SRCS"
"anim_diff")
add_executable(anim_diff ${ANIM_DIFF_SRCS})
target_link_libraries(anim_diff
exampleutil
imagedec
imageenc
imageioutil
webp
libwebpmux
webpdemux
${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(anim_diff PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
# anim_dump
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS} ${WEBP_DEP_GIF_INCLUDE_DIRS})
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DUMP_SRCS"
"anim_dump")
add_executable(anim_dump ${ANIM_DUMP_SRCS})
target_link_libraries(anim_dump
exampleutil
imagedec
imageenc
imageioutil
webp
libwebpmux
webpdemux
${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(anim_dump PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
endif()
# Install the different headers and libraries.
install(TARGETS ${INSTALLED_LIBRARIES}
EXPORT ${PROJECT_NAME}Targets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp
INCLUDES
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
set(ConfigPackageLocation ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake/)
install(EXPORT ${PROJECT_NAME}Targets
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${ConfigPackageLocation})
# Create the CMake version file.
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"
VERSION ${PACKAGE_VERSION}
COMPATIBILITY AnyNewerVersion)
# Create the Config file.
include(CMakePackageConfigHelpers)
configure_package_config_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/WebPConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake
INSTALL_DESTINATION
${ConfigPackageLocation})
# Install the generated CMake files.
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake"
DESTINATION ${ConfigPackageLocation})
# Install the man pages.
set(MAN_PAGES
cwebp.1
dwebp.1
gif2webp.1
img2webp.1
vwebp.1
webpmux.1
webpinfo.1)
set(EXEC_BUILDS
"CWEBP"
"DWEBP"
"GIF2WEBP"
"IMG2WEBP"
"VWEBP"
"WEBPMUX"
"WEBPINFO")
list(LENGTH MAN_PAGES MAN_PAGES_LENGTH)
math(EXPR MAN_PAGES_RANGE "${MAN_PAGES_LENGTH} - 1")
foreach(I_MAN RANGE ${MAN_PAGES_RANGE})
list(GET EXEC_BUILDS ${I_MAN} EXEC_BUILD)
if(WEBP_BUILD_${EXEC_BUILD})
list(GET MAN_PAGES ${I_MAN} MAN_PAGE)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man/${MAN_PAGE}
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
COMPONENT doc)
endif()
endforeach()

660
ChangeLog
View File

@ -1,657 +1,9 @@
170a8712 Fix check_c_source_compiles with pthread.
85995719 disable CombinedShannonEntropy_SSE2 on x86
8af7436f Merge "{ios,xcframework}build.sh: make min version(s) more visible" into 1.2.0
e56c3c5b pngdec: raise memory limit if needed
13b8e9fe {ios,xcframework}build.sh: make min version(s) more visible
a9225410 animdecoder_fuzzer: fix memory leak
d6c2285d update gradle to 6.1.1
52ce6333 update NEWS
28c49820 bump version to 1.2.0
7363dff2 webp/encode.h: restore WEBP_ENCODER_ABI_VERSION to v1.1.0
826aafa5 update AUTHORS
63258823 animdecoder_fuzzer: validate canvas size
9eb26381 CMake: remove duplicate "include(GNUInstallDirs)"
2e7bed79 WebPPicture: clarify the ownership of user-owned data.
cccf5e33 webpmux: add an '-set loop <value>' option
c9a3f6a1 Merge changes Ie29f9867,I289c54c4
319f56f1 iosbuild.sh: sync some aspects of xcframeworkbuild.sh
e8e8db98 add xcframeworkbuild.sh
ae545534 dsp.h: allow config.h to override MSVC SIMD autodetection
fef789f3 Merge "cmake: fix per-file assembly flags"
fc14fc03 Have C encoding predictors use decoding predictors.
7656f0b3 README,cosmetics: fix a couple typos
d2e245ea cmake: disable webp.js if WEBP_ENABLE_SIMD=1
96099a79 cmake: fix per-file assembly flags
5abb5582 Merge "cmake: fix compilation w/Xcode generator"
8484a120 cmake: fix compilation w/Xcode generator
d7bf01c9 Merge changes Ifcae0f38,Iee2d7401
36c81ff6 WASM-SIMD: port 2 patches from rreverser@'s tree
988b02ab Merge "Couple of fixes to allow SIMD on Emscripten"
26faf770 wicdec: fail with animated images
ab2d08a8 [cd]webp: document lack of animated webp support
52273943 Couple of fixes to allow SIMD on Emscripten
8870ba7f Fix skia bug #10952
4b3c6953 Detect if StoreFrame read more than anmf_payload_size bytes
17fd4ba8 webp/decode.h,cosmetics: normalize 'flip' comment
411d3677 remove some unreachable break statements
3700ffd7 WebPPictureHasTransparency: remove unreachable return
83604bf3 {animencoder,enc_dec}_fuzzer: convert some abort()s to returns
eb44119c Merge changes I8ae09473,I678c8b1e
9f6055fc fuzz_utils.h: rename max() to Max()
695788e7 fuzz_utils.h: make functions WEBP_INLINE
906c1fcd make ImgIoUtilReadFile use WebPMalloc instead of malloc
8cb7e536 rename demux_api_fuzzer.c -> mux_demux_api_fuzzer.c
443db47d add animdecoder_fuzzer.cc
36a6eea3 Merge "import fuzzers from oss-fuzz/chromium"
ec5f12c1 Makefile.vc: remove deprecated /Gm option
64425a08 picture_tools_enc: fix windows build warning
bd94090a import fuzzers from oss-fuzz/chromium
cf847cba use WEBP_DSP_INIT_FUNC for Init{GammaTables*,GetCoeffs}
55a080e5 Add WebPReplaceTransparentPixels() in dsp
84739717 GetBackgroundColorGIF: promote to uint32_t before << 24
def64e92 cwebp: Fix -print_psnr for near_lossless
cf2f88b3 Add palette and spatial for q >= 75 and -m 5
f0110bae Add no-color cache configuration to the cruncher
749a8b99 Better estimate of the cache cost.
4f9f00cc Use spatial predictors on top of palette no matter what.
7658c686 Add spatial prediction on top of palette in cruncher.
133ff0e3 webp_js: force WASM=0 option explicitly
e3c259a2 Fix integer overflow in EmitFancyRGB.
b3ff0bde man/{gif2,img2}webp,webpmux: normalize some wording
f9b30586 fix ABI breakage introduced by 6a0ff358
1d58dcfc README.webp_js: update note about emscripten version
44070266 README.webp_js: s/fastcomp/upstream/
2565fa8f README.webp_js: update cmake command
47309ef5 webp: WEBP_OFFSET_PTR()
687ab00e DC{4,8,16}_NEON: replace vmovl w/vaddl
1b92fe75 DC16_NEON,aarch64: use vaddlv
53f3d8cf dec_neon,DC8_NEON: use vaddlv instead of movl+vaddv
27d08240 Fix integer overflow in WebPAnimDecoderGetNext()
69776e38 Merge "remove call to MBAnalyzeBestIntra4Mode for method >= 5"
a99078c1 remove call to MBAnalyzeBestIntra4Mode for method >= 5
22e404cc CMakeLists.txt: fix set(CACHE) argument order
71690b52 fix MSVC warning
6a0ff358 Enc: add a qmin / qmax range for quality factor
0fa56f30 Merge tag 'v1.1.0'
6cf504d0 PNM decoding: handle max_value != 255
d7844e97 update ChangeLog (tag: v1.1.0-rc2, tag: v1.1.0, origin/1.1.0)
7f006436 Makefile.vc: fix webp_quality.exe link
cf047e83 Makefile.vc: fix webp_quality.exe link
c074c653 update NEWS
30f09551 bump version to 1.1.0
a76694a1 update AUTHORS
6e3ef7b3 extras: fix WEBP_SWAP_16BIT_CSP check
47178dbd extras: add WebPUnmultiplyARGB() convenience function
22cbae33 idec_dec: fix 0 offset of NULL pointer
290dd0b4 muxread: fix 0 offset of NULL pointer
0df474ac Merge "lossless_(enc_|)sse2: avoid offsetting a NULL pointer"
c6b75a19 lossless_(enc_|)sse2: avoid offsetting a NULL pointer
295e5e38 fix UBSAN warning
e2575e05 DC8_NEON,aarch64: use vaddv
b0e09e34 dec_neon: Fix build failure under some toolchains
cf0e903c dsp/lossless: Fix non gcc ARM builds
bb7bc40b Remove ubsan errors.
78881b76 CMake: fix GLUT library link
9f750f7a cmake: fix BUILD_SHARED_LIBS build on mac
17850e74 libwebp: Remove char-subscripts warning in pnmdec.c
2fa2552d Merge "Expose WebPMalloc() in addition to WebPFree()"
a4df4aae Expose WebPMalloc() in addition to WebPFree()
853ea3d8 imageio/tiff: Return error before allocating bad tile size
af650c0b Fix a Wxor-used-as-pow false positive
601ef17c libwebp.py: update to swig 3.0.12
0e48d889 bugfix: last alpha rows were incorrectly decoded
24d2ccb4 webp: Fix imageio ReadPNM() TUPLTYPE
fab8f9cf cosmetics: normalize '*' association
94138e0e update .gitignore
0fe1a89d update ChangeLog (tag: v1.0.3-rc1, tag: v1.0.3)
2ad0916d update NEWS
1287362b bump version to 1.0.3
7b968cc2 update AUTHORS
9d6988f4 Fix the oscillating prediction problem at low quality
312f74d0 makefile.unix: allow *_LIBS to be overridden w/EXTRA_LIBS
92dbf237 filters_sse2,cosmetics: shorten some long lines
a277d197 filters_sse2.c: quiet integer sanitizer warnings
804540f1 Fix cpufeatures in CMake.
bf00c15b Add CMake option for bittrace.
a788b498 filters_sse2.c: quiet integer sanitizer warnings
e6a92c5e filters.c: quiet integer sanitizer warnings
ec1cc40a lossless.c: remove U32 -> S8 conversion warnings
1106478f remove conversion U32 -> S8 warnings
812a6b49 lossless_enc: fix some conversion warning
4627c1c9 lossless_enc,TransformColorBlue: quiet uint32_t conv warning
c84673a6 lossless_enc_sse{2,41}: quiet signed conv warnings
776a7757 dec_sse2: quiet signed conv warnings
bd39c063 Merge "thread_utils: release mutex before signaling"
0550576f Merge "(alpha_processing,enc}_sse2: quiet signed conv warnings"
6682f2c4 thread_utils: release mutex before signaling
e78dea75 (alpha_processing,enc}_sse2: quiet signed conv warnings
9acf18ba iosbuild.sh: add WebP{Demux,Mux}.framework
b9be7e65 vwebp: remove the -fit option (and make it default)
1394a2bb Merge "README.webp_js: update Emscripten.cmake note"
dd3e7f8a README.webp_js: update Emscripten.cmake note
32cf8801 predictor_enc,GetBestGreenRedToBlue: quiet implicit conv warnings
e1c8acb5 Merge "vwebp: add a -fit option"
cbd23dd5 vwebp: add a -fit option
2e672351 bit_writer_utils,Flush: quiet implicit conversion warnings
1326988d swig: update libwebp_python_wrap.c
0e7f8548 update generated swig files
17ed1438 Merge "PutLE{16,24}: quiet implicit conversion warnings"
24686538 PutLE{16,24}: quiet implicit conversion warnings
153bb3a0 fix some clang-7 warnings:
ab2dc893 Rescaler: fix rounding error
aa65f89a HistogramCombineStochastic: fix free of uninit value
af0bac64 Merge "encode.h: mention 'exact' default in WebPEncodeLossless*"
6d2e11ec encode.h: mention 'exact' default in WebPEncodeLossless*
8c3f04fe AndroidCPUInfo: reorder terms in conditional
fcfd9c71 BitTrace: if BITTRACE is > 0, record and print syntax bits used
067031ea Speedups for unused Huffman groups.
01ac46ba libwebp: Display "libjpeg error:" in imageio/jpegdec
d9a662e1 WebPRescalerGetScaledDimensions: round scaled dimension up
62eb3f08 libwebp: Fix missing '{' in README
e05f785a Merge "unicode,INIT_WARGV: add missing cast"
63c9a69f tag the VP8LHashPix() function for potential uint roll-over
2b7214ab unicode,INIT_WARGV: add missing cast
bf424b46 tag the GetPixPairHash64() function for potential uint roll-over
7d05d6ca Have the color cache computation be u32-bit only.
6bcf8769 Remove BINARYEN_METHOD in wasm settings.
2b98df90 update ChangeLog (tag: v1.0.2-rc1, tag: v1.0.2)
61e372b7 update NEWS
7ae658a0 bump version to 1.0.2
51c4907d update AUTHORS
666bd6c6 man/cwebp.1: refine near-lossless text
561cdce5 Clarify the doc about GetFeatures.
aec2cf02 near_lossless: fix fuzzing-detected integer overflow
928a75de webp: Fix VP8LBitWriterClone() bug
5173d4ee neon IsFlat
5b081219 IsFlat: inline when possible
381b7b54 IsFlat: use int for thresh
6ed15ea1 fix unprobable leak in webp_sdl.c
22bbb24e Merge "IsFlat: return int"
8b3fb238 Merge tag 'v1.0.1'
f435de95 IsFlat: return int
41521aed utils.h: only define WEBP_NEED_LOG_TABLE_8BIT when needed
9f4d4a3f neon: GetResidualCost
0fd7514b neon: SetResidualCoeffs
f95a996c Simpler histogram clustering.
e85d3313 update ChangeLog (tag: v1.0.1-rc2, tag: v1.0.1)
fa8210e4 Fix pair update in stochastic entropy merging.
fd198f73 add codereview.settings
825389ac README.mux: add a reference to the AnimDecoder API
3be698c3 CMake: fix webp_js compilation
485ff86f Fix pair update in stochastic entropy merging.
4cd0582d CMake: fix webp_js compilation
4cbb4caf update NEWS
f5a5918d bump version to 1.0.1
d61385db Speed-up: Make sure we only initialize histograms when needed.
6752904b Speed-up: Make sure we only initialize histograms when needed.
0c570316 update AUTHORS
301a2dda img2webp: add help note about arguments from a file
f0abab92 Speedups for empty histograms.
f2dfd925 Split HistogramAdd to only have the high level logic in C.
06b7bc7d Fix compilation on windows and clang-cl+ninja.
b6284d82 img2webp: add help note about arguments from a file
decf6f6b Speedups for empty histograms.
dea3e899 Split HistogramAdd to only have the high level logic in C.
632798ae Merge "Fix compilation on windows and clang-cl+ninja."
dc1a9518 Merge "libwebp: Unicode command tools on Windows"
9cf9841b libwebp: Unicode command tools on Windows
98179495 remove some minor TODOs
a376e7b9 Fix compilation on windows and clang-cl+ninja.
cbf82cc0 Remove AVX2 files.
5030e902 Merge "TIFF decoder: remove unused KINV definition"
ac543311 Remove a few more useless #defines
123d3306 TIFF decoder: remove unused KINV definition
ef1094b0 Merge "- install pkg-config files during the CMake build"
b911fbc9 libwebp: Remove duplicate GIFDisplayError in anim_util
eee00b66 - install pkg-config files during the CMake build
ac3ec8c9 Merge "Clean-up the common sources in dsp."
3e13da7b Clean-up the common sources in dsp.
5c395f1d libwebp: cmake-format all
e7a69729 libwebp: Add extras targets in CMakeLists.txt
e52485d6 libwebp: Rename macros in webpmux.c
92dc0f09 clean-up MakeInputImageCopy()
39952de2 VP8IteratorImport: add missing 'const'
382af7a2 clean-up WebPBlendAlpha
14d020f6 libwebp: Use ExUtilGet*() in anim_diff
0d92ff25 libwebp: remove useless variable in gif2webp
556cb1b4 Merge "CMake: Set WEBP_BUILD_GIF2WEBP to off"
da26ee49 CMake: Set WEBP_BUILD_GIF2WEBP to off
b2a867c0 cwebp: Don't premultiply during -resize if -exact
637141bc pngdec: fix build w/libpng < 1.4.x
bc5092b1 pngdec: set memory functions
50d8345a Fix CMake math library.
6aa3e8aa Fix math library on Visual Studio.
d71df4e2 Fix math library finding in CMake.
de08d727 cosmetics: normalize include guard comment
009562b4 vwebp: Fix bug when Dispose then NoBlend frames
423f2579 Fix up CMake to create targets.
907208f9 Wait for all threads to be done in DecodeRemaining.
4649b3c4 vwebp: Add background color display option
78ad57a3 Fix bad glClearColor parameters
da96d8d9 Allow for a non-initialized alpha decompressor in DoRemap.
2563db47 fix rescaling rounding inaccuracy
211f37ee fix endian problems in pattern copy
5f0f5c07 Make sure partition #0 is read before VP8 data in IDecode.
de98732b fix GetColorf() bug
4338cd36 misc fixes in libwebpmux
e00af13e fix signatures after a9ceda7ff1
a9ceda7f Speed-up chunk list operations.
2281bbf6 Merge "Better handling of bogus Huffman codes."
39cb9aad Better handling of bogus Huffman codes.
89cc9d37 Merge "fix read-overflow while parsing VP8X chunk"
95fd6507 fix read-overflow while parsing VP8X chunk
9e729fe1 Fix VP8IoTeardownHook being called twice on worker sync failure
29fb8562 Merge "muxread,anmf: fail on multiple image chunks"
eb82ce76 muxread,anmf: fail on multiple image chunks
1344a2e9 fix alpha-filtering crash when image width is larger than radius
be738c6d muxread,ChunkVerifyAndAssign: validate chunk_size
2c70ad76 muxread,CreateInternal: fix riff size checks
569001f1 Fix for thread race heap-use-after-free
c56a02d9 Android.mk: use LOCAL_EXPORT_C_INCLUDES w/public libs
15795596 CMakeLists.txt,cosmetics: normalize if() formatting
1a44c233 Merge "cmake: add support for webpmux"
e9569ad7 Merge "configure,*am,cosmetics: s/WANT_/BUILD_/"
35c7de6f cmake: add support for webpmux
0f25e61c WebpToSDL(): fix the return value in case of error
5d8985de configure,*am,cosmetics: s/WANT_/BUILD_/
895fd28f Merge "man/Makefile.am: add img2webp.1"
5cf3e2af man/Makefile.am: add img2webp.1
2a9de5b9 Add build rules for anim_diff & anim_dump utils.
71ed73cf fix invalid check for buffer size
af0e4fbb gif2webp: fix transcode of loop count=65535
dce5d764 Limit memory allocation when reading invalid Huffman codes.
f9df0081 Merge "cmake: quiet glut deprecation warnings on OS X"
dc39b16f webpmux.1: correct grammar
c7aa1264 cwebp.c: fix a missing \n
53aa51e9 Merge tag 'v1.0.0'
698b8844 update ChangeLog (tag: v1.0.0)
8d510751 webp-container-spec: correct frame duration=0 note
e6b2164e vwebp: Copy Chrome's behavior w/frame duration == 0
094b3b28 cmake: quiet glut deprecation warnings on OS X
71c39a06 webp-container-spec: correct frame duration=0 note
fd3d5756 vwebp: Copy Chrome's behavior w/frame duration == 0
b0c966fb Build vwebp from CMake.
d20b7707 update ChangeLog (tag: v1.0.0-rc3)
0d5fad46 add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC
d77bf512 add WEBP_DSP_INIT / WEBP_DSP_INIT_FUNC
c1cb86af fix 16b overflow in SSE2
e577feb7 makefile.unix: add DEBUG flag for compiling w/ debug-symbol
99be34b3 cwebp,get_disto: fix bpp output
e122e511 cwebp,get_disto: fix bpp output
f5565ca8 cmake: Make sure we use near-lossless by default.
d898dc14 fix bug in WebPImport565: alpha value was not set
1c8f358d Fix CMake with WASM.
a0215fb7 webp_js: fix webp_js demo html
882784b0 update ChangeLog (tag: v1.0.0-rc2)
2f930e08 Revert "Use proper targets for CMake."
8165e8fb Use proper targets for CMake.
3f157dd5 Remove some very hard TODOs.
abb47760 Merge "Use proper targets for CMake."
cd758a17 {de,}mux/Makefile.am: add missing headers
e155dda0 Use proper targets for CMake.
b892b8ba makefile.unix,dist: use ascii for text output
64a57d05 add -version option to anim_dump,anim_diff and img2webp
994be82d Merge "Remove some very hard TODOs."
4033e1d7 Remove some very hard TODOs.
fc1b8e3a webp_js: fix webp_js demo html
15aa48d9 update ChangeLog (tag: v1.0.0-rc1)
e607dabc update AUTHORS
38410c08 [CFI] Remove function pointer casts
978eec25 [CFI] Remove function pointer casts
c57b2736 bump version to 1.0.0
cba28853 update NEWS
c909d531 Merge "remove some deprecation warning on MacOSX"
217443c7 remove some deprecation warning on MacOSX
b672bdfa configure: quiet glut deprecation warnings on OS X
daa9fcaf configure: use sdl-config if available
dd174cae Merge "imagedec: support metadata reading for WebP image decoding"
641cedcc imagedec: support metadata reading for WebP image decoding
065b2ce1 anim_diff: add a couple missing newlines in Help()
c4cc1147 Merge "gif2webp: force low duration frames to 100ms"
09333097 gif2webp: force low duration frames to 100ms
e03f0ec3 sharp_yuv: use 14b fixed-point precision for gamma
b2db361c image_enc,WebPWritePNG: move locals after setjmp
74e82ec6 Merge "WebPPictureDistortion: fix big-endian results order"
645d04ca Merge "cwebp,get_disto: report bpp"
120f58c3 Merge "lossless*sse2: improve non-const 16-bit vector creation"
a7fe9412 WebPPictureDistortion: fix big-endian results order
e26fe066 cwebp,get_disto: report bpp
9df64e28 Merge changes Id5b4a1a4,Ia20ce844
8043504f lossless*sse2: improve non-const 16-bit vector creation
1e3dfc48 Import: extract condition from loop
3b07d327 Import,RGBA: fix for BigEndian import
551948e4 Remove unused argument in VP8LBitsEntropy.
3005237a ReadWebP: fix for big-endian
499c395a Merge "anim_diff: expose the -max_diff option"
f69dcd69 Merge "remove WEBP_EXPERIMENTAL_FEATURES"
07d884d5 anim_diff: expose the -max_diff option
f4dd9256 remove WEBP_EXPERIMENTAL_FEATURES
94a8377b extract the command-line parsing helpers to example_util
fc09e6e2 PNM decoder: prevent unsupported depth=2 PAM case.
6de58603 MIPS64: Fix defined-but-not-used errors with WEBP_REDUCE_CSP
cbde5728 gif2webp: add support for reading from stdin
cf1c5054 Add an SSE4 version of some lossless color transforms.
45a8b5eb Fix lint error with man page.
cff38e8f Merge "PNG decoder: handle gAMA chunk"
59cb1a48 Merge "enable dc error-diffusion always"
78318b30 PNG decoder: handle gAMA chunk
664c21dd Merge "remove some TODOs"
815652de enable dc error-diffusion always
aec45cec remove some TODOs
5715dfce fix block-count[] increment in case of large image
c2d04f3e enable DC error-diffusion always for multi-pass
96bf07c5 use DC error diffusion for U/V at low-quality
1c59020b fix missing sse41 targets in makefile.unix
7a8e814b cosmetics: s/color_space/colorspace/
05f6fe24 upsampling: rm asserts w/REDUCE_CSP+OMIT_C_CODE
b4cf5597 Merge "Upsampling SSE2/SSE4 speedup."
ccbeb32c Makefile.vc: add missing sse41 files
55403a9a Upsampling SSE2/SSE4 speedup.
807b53c4 Implement the upsampling/yuv functions in SSE41
84101a81 Fix wasm WebP compilation
8bebd2a3 fix warning on MSVC
a7f93fe3 webpmux: allow reading argument from a file
b69f18a7 gif2webp.1: fix -loop_compatibility layout
72d530c0 Merge "fix lossless decoding w/WEBP_REDUCE_SIZE"
296c7dc4 fix lossless decoding w/WEBP_REDUCE_SIZE
0d5d029c Merge "ImgIoUtilReadFile: fix file leak upon error"
ae568ce7 ImgIoUtilReadFile: fix file leak upon error
796b5a8a Merge tag 'v0.6.1'
6b7a95fd update ChangeLog (tag: v0.6.1)
f66955de WEBP_REDUCE_CSP: restrict colorspace support
1af0df76 Merge "WEBP_REDUCE_CSP: restrict colorspace support"
6de20df0 WEBP_REDUCE_CSP: restrict colorspace support
a289d8e7 update ChangeLog (tag: v0.6.1-rc2)
c10a493c vwebp: disable double buffering on windows & mac
0d4466c2 webp_to_sdl.c: fix file mode
1b27bf8b WEBP_REDUCE_SIZE: disable all rescaler code
126be109 webpinfo: add -version option
0df22b9e WEBP_REDUCE_SIZE: disable all rescaler code
9add62b5 bump version to 0.6.1
d3e26144 update NEWS
2edda639 README: add webpinfo section
9ca568ef Merge "right-size some tables"
31f1995c Merge "SSE2 implementation of HasAlphaXXX"
a80c46bd SSE2 implementation of HasAlphaXXX
083507f2 right-size some tables
2e5785b2 anim_utils.c: remove warning when !defined(WEBP_HAVE_GIF)
b299c47e add WEBP_REDUCE_SIZE
f593d71a enc: disable pic->stats/extra_info w/WEBP_DISABLE_STATS
541179a9 Merge "predictor_enc: fix build w/--disable-near-lossless"
5755a7ec predictor_enc: fix build w/--disable-near-lossless
eab5bab7 add WEBP_DISABLE_STATS
8052c585 remove some petty TODOs from vwebp.
c245343d move LOAD8x4 and STORE8x2 closer to their use location
b9e734fd dec,cosmetics: normalize function naming style
c188d546 dec: harmonize function suffixes
28c5ac81 dec_sse41: harmonize function suffixes
e65b72a3 Merge "introduce WebPHasAlpha8b and WebPHasAlpha32b"
b94cee98 dec_sse2: remove HE8uv_SSE2
44a0ee3f introduce WebPHasAlpha8b and WebPHasAlpha32b
aebf59ac Merge "WebPPictureAllocARGB: align argb allocation"
c184665e WebPPictureAllocARGB: align argb allocation
3daf7509 WebPParseHeaders: remove obsolete animation TODO
80285d97 cmake: avoid security warnings under msvc
650eac55 cmake: don't set -Wall with MSVC
c462cd00 Remove useless code.
01a98217 Merge "remove WebPWorkerImpl declaration from the header"
3c49fc47 Merge "thread_utils: fix potentially bad call to Execute"
fde2782e thread_utils: fix potentially bad call to Execute
2a270c1d remove WebPWorkerImpl declaration from the header
f1f437cc remove mention of 'lossy-only parameters' from the doc
3879074d Merge "WebPMemToUint32: remove ptr cast to int"
04b029d2 WebPMemToUint32: remove ptr cast to int
b7971d0e dsp: avoid defining _C functions w/NEON builds
6ba98764 webpdec: correct alloc size check w/use_argb
5cfb3b0f normalize include guards
f433205e Merge changes Ia17c7dfc,I75423abb,Ia2f716b4,I161caa14,I4210081a, ...
8d033b14 {dec,enc}_neon: harmonize function suffixes x2
0295e981 upsampling_neon: harmonize function suffixes
d572c4e5 yuv_neon: harmonize function suffixes
ab9c2500 rescaler_neon: harmonize function suffixes
93e0ce27 lossless_neon: harmonize function suffixes
22fbc50e lossless_enc_neon: harmonize function suffixes
447875b4 filters_neon,cosmetics: fix indent
e51bdd43 remove unused VP8TokenToStats() function
785da7ea enc_neon: harmonize function suffixes
bc1a251f dec_neon: harmonize function suffixes
61e535f1 dsp/lossless: workaround gcc-4.8 bug on arm
68b2eab7 cwebp: fix alpha reporting w/lossless & metadata
30042faa WebPDemuxGetI: add doc details around WebPFormatFeature
0a17f471 Merge "WIP: list includes as descendants of the project dir"
a4399721 WIP: list includes as descendants of the project dir
08275708 Merge "Make sure we reach the full range for alpha blending."
d361a6a7 yuv_sse2: harmonize function suffixes
6921aa6f upsampling_sse2: harmonize function suffixes
08c67d3e ssim_sse2: harmonize function suffixes
582a1b57 rescaler_sse2: harmonize function suffixes
2c1b18ba lossless_sse2: harmonize function suffixes
0ac46e81 lossless_enc_sse2: harmonize function suffixes
bc634d57 enc_sse2: harmonize function suffixes
bcb7347c dec_sse2: harmonize function suffixes
e14ad93c Make sure we reach the full range for alpha blending.
7038ca8d demux,StoreFrame: restore hdr size check to min req
fb3daad6 cpu: fix ssse3 check
be590e06 Merge "Fix CMake redefinition for HAVE_CPU_FEATURES_H"
35f736e1 Fix CMake redefinition for HAVE_CPU_FEATURES_H
a5216efc Fix integer overflow warning.
a9c8916b decode.h,WebPIDecGetRGB: clarify output ptr validity
3c74c645 gif2webp: handle 1-frame case properly + fix anim_diff
c7f295d3 Merge "gif2webp: introduce -loop_compatibility option"
b4e04677 gif2webp: introduce -loop_compatibility option
f78da3de add LOCAL_CLANG_PREREQ and avoid WORK_AROUND_GCC w/3.8+
01c426f1 define WEBP_USE_INTRINSICS w/gcc-4.9+
8635973d use sdl-config (if available) to determine the link flags
e9459382 use CPPFLAGS before CFLAGS
4a9d788e Merge "Android.mk,mips: fix clang build with r15"
4fbdc9fb Android.mk,mips: fix clang build with r15
a80fcc4a ifdef code not used by Chrome/Android.
3993af12 Fix signed integer overflows.
f66f94ef anim_dump: small tool to dump frames from animated WebP
6eba857b Merge "rationalize the Makefile.am"
c5e34fba function definition cleanup
3822762a rationalize the Makefile.am
501ef6e4 configure style fix: animdiff -> anim_diff
f8bdc268 Merge "protect against NULL dump_folder[] value in ReadAnimatedImage()"
23bfc652 protect against NULL dump_folder[] value in ReadAnimatedImage()
8dc3d71b cosmetics,ReadAnimatedWebP: correct function comment
5bd40066 Merge changes I66a64a0a,I4d2e520f
7945575c cosmetics,webpinfo: remove an else after a return
8729fa11 cosmetics,cwebp: remove an else after a return
f324b7f9 cosmetics: normalize fn proto & decl param names
869eb369 CMake cleanups.
289e62a3 Remove declaration of unimplemented VP8ApplyNearLosslessPredict
20a94186 pnmdec,PAM: validate depth before calculating bytes_per_px
34130afe anim_encode: fix integer overflow
42c79aa6 Merge "Encoder: harmonize function suffixes"
b09307dc Encoder: harmonize function suffixes
bed0456d Merge "SSIM: harmonize the function suffix"
54f6a3cf lossless_sse2.c: fix some missed suffix changes
088f1dcc SSIM: harmonize the function suffix
86fc4dd9 webpdec: use ImgIoUtilCheckSizeArgumentsOverflow
08ea9ecd imageio: add ability restrict max image size
6f9daa4a jpegdec,ReadError: fix leaks on error
a0f72a4f VP8LTransformColorFunc: drop an non-respected 'const' from the signature.
8c934902 Merge "Lossess dec: harmonize the function suffixes"
622242aa Lossess dec: harmonize the function suffixes
1411f027 Lossless Enc: harmonize the function suffixes
24ad2e3c add const to two variables
46efe062 Merge "Allow the lossless cruncher to work for alpha."
8c3f9a47 Speed-up LZ77.
1aef4c71 Allow the lossless cruncher to work for alpha.
b8821dbd Improve the box LZ77 speed.
7beed280 add missing ()s to macro parameters
6473d20b Merge "fix Android standalone toolchain build"
dcefed95 Merge "build.gradle: fix arm64 build"
0c83a8bc Merge "yuv: harmonize suffix naming"
c6d1db4b fix Android standalone toolchain build
663a6d9d unify the ALTERNATE_CODE flag usage
73ea9f27 yuv: harmonize suffix naming
c71b68ac build.gradle: fix arm64 build
c4568b47 Rescaler: harmonize the suffix naming
6cb13b05 Merge "alpha_processing: harmonize the naming suffixes to be _C()"
83a3e69a Merge "simplify WEBP_EXTERN macro"
7295fde2 Merge "filters: harmonize the suffixes naming to _SSE2(), _C(), etc."
8e42ba4c simplify WEBP_EXTERN macro
331ab34b cost*.c: harmonize the suffix namings
b161f670 filters: harmonize the suffixes naming to _SSE2(), _C(), etc.
dec5e4d3 alpha_processing: harmonize the naming suffixes to be _C()
6878d427 fix memory leak in SDL_Init()
461ae555 Merge "configure: fix warnings in sdl check"
62486a22 configure: test for -Wundef
92982609 dsp.h: fix -Wundef w/__mips_dsp_rev
0265cede configure: fix warnings in sdl check
88c73d8a backward_references_enc.h: fix WINDOW_SIZE_BITS check
4ea49f6b rescaler_sse2.c: fix WEBP_RESCALER_FIX -> _RFIX typo
1b526638 Clean-up some CMake
87f57a4b Merge "cmake: fix gif lib detection when cross compiling"
b34a9db1 cosmetics,dec_sse2: remove some redundant comments
471c5755 cmake: fix gif lib detection when cross compiling
c793417a cmake: disable gif2webp if gif lib isn't found
dcbc1c88 cmake: split gif detection from IMG deps
66ad84f0 Merge "muxread: remove unreachable code"
50ec3ab7 muxread: remove unreachable code
7d67a164 Lossy encoding: smoothen transparent areas to improve compression
e50650c7 Merge "fix signature for DISABLE_TOKEN_BUFFER compilation"
671d2567 fix signature for DISABLE_TOKEN_BUFFER compilation
d6755580 cpu.cmake: use unique flag to test simd disable flags
28914528 Merge "Remove the argb* files."
8acb4942 Remove the argb* files.
3b62347b README: correct cmake invocation note
7ca0df13 Have the SSE2 version of PackARGB use common code.
7b250459 Merge "Re-use the transformed image when trying several LZ77 in lossless."
e132072f Re-use the transformed image when trying several LZ77 in lossless.
5d7a50ef Get code to compile in C++.
7b012987 configure: test for -Wparentheses-equality
f0569adb Fix man pages for multi-threading.
f1d5a397 multithread cruncher: only copy stats when picture->stats != NULL
f8c2ac15 Multi-thread the lossless cruncher.
a88c6522 Merge "Integrate a new LZ77 looking for matches in the neighborhood of a pixel only."
8f6df1d0 Unroll Predictors 10, 11 and 12.
355c3d1b Integrate a new LZ77 looking for matches in the neighborhood of a pixel only.
a1779a01 Refactor LZ77 handling in preparation for a new method.
67de68b5 Android.mk/build.gradle: fix mips build with clang from r14b
f209a548 Use the plane code and not the distance when computing statistics.
b903b80c Split cost-based backward references in its own file.
498cad34 Cosmetic changes in backward reference.
e4eb4587 lossless, VP8LTransformColor_C: make sure no overflow happens with colors.
af6deaff webpinfo: handle alpha flag mismatch
7caef29b Fix typo that creeped in.
39e19f92 Merge "near lossless: fix unsigned int overflow warnings."
9bbc0891 near lossless: fix unsigned int overflow warnings.
e1118d62 Merge "cosmetics,FindClosestDiscretized: use uint in mask creation"
186bc9b7 Merge "webpinfo: tolerate ALPH+VP8L"
b5887297 cosmetics,FindClosestDiscretized: use uint in mask creation
f1784aee near_lossless,FindClosestDiscretized: use unsigned ops
0d20abb3 webpinfo: tolerate ALPH+VP8L
972104b3 webpmux: tolerate false positive Alpha flag
dd7e83cc tiffdec,ReadTIFF: ensure data_size is < tsize_t max
d988eb7b tiffdec,MyRead: quiet -Wshorten-64-to-32 warning
dabda707 webpinfo: add support to parse Alpha bitstream
4c117643 webpinfo: correct background color output, BGRA->ARGB
defc98d7 Doc: clarify the role of quality in WebPConfig.
d78ff780 Merge "Fix code to compile with C++."
c8f14093 Fix code to compile with C++.
497dc6a7 pnmdec: sanitize invalid header output
d78e5867 Merge "configure: test for -Wconstant-conversion"
481e91eb Merge "pnmdec,PAM: set bytes_per_px based on depth when missing"
93b12753 configure: test for -Wconstant-conversion
645f0c53 pnmdec,PAM: set bytes_per_px based on depth when missing
e9154605 Merge "vwebp: activate GLUT double-buffering"
818d795b vwebp: activate GLUT double-buffering
d63e6f4b Add a man page for webpinfo
4d708435 Merge "NEON: implement ConvertRGB24ToY/BGR24/ARGB/RGBA32ToUV/ARGBToUV"
faf42213 NEON: implement ConvertRGB24ToY/BGR24/ARGB/RGBA32ToUV/ARGBToUV
b4d576fa Install man pages with CMake.
cbc1b921 webpinfo: add features to parse bitstream header
e644c556 Fix bad bit writer initialization.
b62cdad2 Merge "Implement a cruncher for lossless at method 6."
da3e4dfb use the exact constant for the gamma transfer function
a9c701e0 Merge "tiffdec: fix EXTRASAMPLES check"
adab8ce0 Implement a cruncher for lossless at method 6.
1b92b237 Merge "Fix VP8ApplyNearLossless to respect const and stride."
1923ff02 tiffdec: fix EXTRASAMPLES check
97cce5ba tiffdec: only request EXTRASAMPLES w/> 3 samples/px
0dcd85b6 Fix VP8ApplyNearLossless to respect const and stride.
f7682189 yuv: rationalize the C/SSE2 function naming
52245424 NEON implementation of some Sharp-YUV420 functions
690efd82 Avoid several backward reference copies.
4bb1f607 src/dec/vp8_dec.h, cosmetics: fix comments
285748be cmake: build/install webpinfo
78fd199c backward_references_enc.c: clear -Wshadow warnings
ae836410 WebPLog2FloorC: clear -Wshadow warning
d0b7404e Merge "WASM support"
134e314f WASM support
c08adb6f Merge "VP8LEnc: remove use of BitsLog2Ceiling()"
28c37ebd VP8LEnc: remove use of BitsLog2Ceiling()
2cb58ab2 webpinfo: output format as a human readable string
bb175a93 Merge "rename some symbols clashing with MSVC headers"
39eda658 Remove a duplicated pixel hash implementation.
36b8274d rename some symbols clashing with MSVC headers
274daf54 Add webpinfo tool.
ec5036e4 add explicit reference to /usr/local/{lib,inc}
18f0dfac Merge "fix TIFF encoder regarding rgbA/RGBA"
4e2b0b50 Merge "webpdec.h: fix a doc typo"
e2eeabff Merge "Install binaries, libraries and headers in CMake."
836607e6 webpdec.h: fix a doc typo
9273e441 fix TIFF encoder regarding rgbA/RGBA
17e3c11f Add limited PAM decoding support
5f624871 Install binaries, libraries and headers in CMake.
976adac1 Merge "lossless incremental decoding: fix missing eos_ test"
f8fad4fa lossless incremental decoding: fix missing eos_ test
27415d41 Merge "vwebp_sdl: fix the makefile.unix"
49566182 Merge "ImgIoUtilWriteFile(): use ImgIoUtilSetBinaryMode"
6f75a51b Analyze the transform entropy on the whole image.
a5e4e3af Use palette only if we can in entropy analysis.
75a9c3c4 Improve compression by better entropy analysis.
39cf6f4f vwebp_sdl: fix the makefile.unix
699b0416 ImgIoUtilWriteFile(): use ImgIoUtilSetBinaryMode
7d985bd1 Fix small entropy analysis bug.
6e7caf06 Optimize the color cache size.
833c9219 More efficient stochastic histogram merge.
5183326b Refactor the greedy histogram merge.
99f6f462 Merge "histogram_enc.c,MyRand: s/ul/u/ for unsigned constants"
80a22186 ssim.c: remove dead include
a128dfff histogram_enc.c,MyRand: s/ul/u/ for unsigned constants
693bf74e move the SSIM calculation code in ssim.c / ssim_sse2.c
10d791ca Merge "Fix the random generator in HistogramCombineStochastic."
fa63a966 Fix the random generator in HistogramCombineStochastic.
16be192f VP8LSetBitPos: remove the eos_ setting
027151ca don't erase the surface before blitting.
4105d565 disable WEBP_USE_XXX optimisations when EMSCRIPTEN is defined
9ee32a75 Merge "WebP-JS: emscripten-based Javascript decoder"
ca9f7b7d WebP-JS: emscripten-based Javascript decoder
868aa690 Perform greedy histogram merge in a unified way.
5b393f2d Merge "fix path typo for vwebp_sdl in Makefile.vc"
e0012bea CMake: only use libwebpdecoder for building dwebp
84c2a7b0 fix path typo for vwebp_sdl in Makefile.vc
1b0e4abf Merge "Add a flag to disable SIMD optimizations."
32263250 Add a flag to disable SIMD optimizations.
b494fdec optimize the ARGB->ARGB Import to use memcpy
f1536039 Merge "ReadWebP: decode directly into a pre-allocated buffer"
e69ed291 ReadWebP: decode directly into a pre-allocated buffer
57d8de8a Merge "vwebp_sdl: simple viewer based on SDL"
5cfd4ebc LZ77 interval speedups. Faster, smaller, simpler.
1e7ad88b PNM header decoder: add some basic numerical validation
17c7890c Merge "Add a decoder only library for WebP in CMake."
be733786 Merge "Add clang build fix for MSA"
03cda0e4 Add a decoder only library for WebP in CMake.
aa893914 Add clang build fix for MSA
31a92e97 Merge "imageio: add limited PNM support for reading"
dcf9d82a imageio: add limited PNM support for reading
6524fcd6 vwebp_sdl: simple viewer based on SDL
6cf24a24 get_disto: fix reference file read
43d472aa Merge tag 'v0.6.0'
50d1a848 update ChangeLog (tag: v0.6.0, origin/0.6.0)
20a7fea0 extras/Makefile.am: fix libwebpextras.la reference 20a7fea0 extras/Makefile.am: fix libwebpextras.la reference
415f3ffe update ChangeLog (tag: v0.6.0-rc3) 415f3ffe update ChangeLog (tag: v0.6.0-rc3)
3c6d1224 update NEWS 3c6d1224 update NEWS
ee4a4141 update AUTHORS ee4a4141 update AUTHORS
32ed856f Fix "all|no frames are keyframes" settings. 32ed856f Fix "all|no frames are keyframes" settings.
1c3190b6 Merge "Fix "all|no frames are keyframes" settings."
f4dc56fd disable GradientUnfilter_NEON f4dc56fd disable GradientUnfilter_NEON
4f3e3bbd disable GradientUnfilter_NEON
2dc0bdca Fix "all|no frames are keyframes" settings.
0d8e0588 img2webp: treat -loop as a no-op w/single images 0d8e0588 img2webp: treat -loop as a no-op w/single images
b0450139 ReadImage(): restore size reporting b0450139 ReadImage(): restore size reporting
0ad3b4ef update ChangeLog (tag: v0.6.0-rc2) 0ad3b4ef update ChangeLog (tag: v0.6.0-rc2)
@ -719,7 +71,7 @@ b016cb91 NEON: faster fancy upsampling
f04eb376 Merge tag 'v0.5.2' f04eb376 Merge tag 'v0.5.2'
341d711c NEON: 5% faster conversion to RGB565 and RGBA4444 341d711c NEON: 5% faster conversion to RGB565 and RGBA4444
abb54827 remove Clang warnings with unused arch arguments. abb54827 remove Clang warnings with unused arch arguments.
ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2, origin/0.5.2) ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2, origin/0.5.2, 0.5.2)
aa7744ca anim_util: quiet implicit conv warnings in 32-bit aa7744ca anim_util: quiet implicit conv warnings in 32-bit
d9120271 jpegdec: correct ContextFill signature d9120271 jpegdec: correct ContextFill signature
24eb3940 Remove some errors when compiling the code as C++. 24eb3940 Remove some errors when compiling the code as C++.
@ -1006,7 +358,7 @@ bbb6ecd9 Merge "Add MSA optimized distortion functions"
c0991a14 io,EmitRescaledAlphaYUV: factor out a common expr c0991a14 io,EmitRescaledAlphaYUV: factor out a common expr
48bf5ed1 build.gradle: remove tab 48bf5ed1 build.gradle: remove tab
bfef6c9f Merge tag 'v0.5.1' bfef6c9f Merge tag 'v0.5.1'
3d97bb75 update ChangeLog (tag: v0.5.1, origin/0.5.1) 3d97bb75 update ChangeLog (tag: v0.5.1, origin/0.5.1, 0.5.1)
deb54d91 Clarify the expected 'config' lifespan in WebPIDecode() deb54d91 Clarify the expected 'config' lifespan in WebPIDecode()
435308e0 Add MSA optimized encoder transform functions 435308e0 Add MSA optimized encoder transform functions
dce64bfa Add MSA optimized alpha filter functions dce64bfa Add MSA optimized alpha filter functions
@ -1200,7 +552,7 @@ b74657fb configure: fix builtin detection w/-Werror
6c1d7631 avoid Yoda style for comparison 6c1d7631 avoid Yoda style for comparison
8ce975ac SSE optimization for vector mismatch. 8ce975ac SSE optimization for vector mismatch.
7db53831 Merge tag 'v0.5.0' 7db53831 Merge tag 'v0.5.0'
37f04949 update ChangeLog (tag: v0.5.0-rc1, tag: v0.5.0, origin/0.5.0) 37f04949 update ChangeLog (tag: v0.5.0-rc1, tag: v0.5.0, origin/0.5.0, 0.5.0)
7e7b6ccc faster rgb565/rgb4444/argb output 7e7b6ccc faster rgb565/rgb4444/argb output
4c7f565f update NEWS 4c7f565f update NEWS
1f62b6b2 update AUTHORS 1f62b6b2 update AUTHORS
@ -1984,7 +1336,7 @@ b5a36cc9 add -near_lossless [0..100] experimental option
0524d9e5 dsp: detect mips64 & disable mips32 code 0524d9e5 dsp: detect mips64 & disable mips32 code
d3485d96 cwebp.1: fix quality description placement d3485d96 cwebp.1: fix quality description placement
29a9fe22 Merge tag 'v0.4.1' 29a9fe22 Merge tag 'v0.4.1'
8af27718 update ChangeLog (tag: v0.4.1, origin/0.4.1) 8af27718 update ChangeLog (tag: v0.4.1, origin/0.4.1, 0.4.1)
e09e9ff6 Record & log the image pre-processing time. e09e9ff6 Record & log the image pre-processing time.
f59c0b4b iosbuild.sh: specify optimization flags f59c0b4b iosbuild.sh: specify optimization flags
8d34ea3e update ChangeLog (tag: v0.4.1-rc1) 8d34ea3e update ChangeLog (tag: v0.4.1-rc1)
@ -2369,7 +1721,7 @@ ea59a8e9 Merge "Merge tag 'v0.4.0'"
effcb0fd Merge tag 'v0.4.0' effcb0fd Merge tag 'v0.4.0'
7c76255d autoconf: update ax_pthread.m4 7c76255d autoconf: update ax_pthread.m4
fff2a11b make -short work with -print_ssim, -print_psnr, etc. fff2a11b make -short work with -print_ssim, -print_psnr, etc.
68e7901d update ChangeLog (tag: v0.4.0-rc1, tag: v0.4.0, origin/0.4.0) 68e7901d update ChangeLog (tag: v0.4.0-rc1, tag: v0.4.0, origin/0.4.0, 0.4.0)
256e4333 update NEWS description with new general features 256e4333 update NEWS description with new general features
29625340 Merge "gif2webp: don't use C99 %zu" into 0.4.0 29625340 Merge "gif2webp: don't use C99 %zu" into 0.4.0
3b9f9dd0 gif2webp: don't use C99 %zu 3b9f9dd0 gif2webp: don't use C99 %zu
@ -3145,7 +2497,7 @@ a61a824b Merge "Add NULL check in chunk APIs"
a0770727 mux struct naming a0770727 mux struct naming
6c66dde8 Merge "Tune Lossless encoder" 6c66dde8 Merge "Tune Lossless encoder"
ab5ea217 Tune Lossless encoder ab5ea217 Tune Lossless encoder
74fefc8c Update ChangeLog (tag: v0.2.1, origin/0.2.0) 74fefc8c Update ChangeLog (tag: v0.2.1, origin/0.2.0, 0.2.0)
92f8059c Rename some chunks: 92f8059c Rename some chunks:
3bb4bbeb Merge "Mux API change:" 3bb4bbeb Merge "Mux API change:"
d0c79f05 Mux API change: d0c79f05 Mux API change:

View File

@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src imageio man SUBDIRS = src imageio man
EXTRA_DIST = COPYING autogen.sh EXTRA_DIST = COPYING autogen.sh
if BUILD_EXTRAS if WANT_EXTRAS
SUBDIRS += extras SUBDIRS += extras
endif endif

View File

@ -28,8 +28,8 @@ PLATFORM_LDFLAGS = /SAFESEH
NOLOGO = /nologo NOLOGO = /nologo
CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
CCDEBUG = cl.exe $(NOLOGO) /Od /Zi /D_DEBUG /RTC1 CCDEBUG = cl.exe $(NOLOGO) /Od /Gm /Zi /D_DEBUG /RTC1
CFLAGS = /I. /Isrc $(NOLOGO) /W3 /EHsc /c CFLAGS = /Isrc $(NOLOGO) /W3 /EHsc /c
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS) LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS)
@ -53,6 +53,11 @@ OUTDIR = ..\obj\
OUTDIR = $(OBJDIR) OUTDIR = $(OBJDIR)
!ENDIF !ENDIF
!IF "$(HAVE_AVX2)" == "1"
CFLAGS = $(CFLAGS) /DWEBP_HAVE_AVX2
AVX2_FLAGS = /arch:AVX2
!ENDIF
############################################################## ##############################################################
# Runtime library configuration # Runtime library configuration
!IF "$(RTLIBCFG)" == "static" !IF "$(RTLIBCFG)" == "static"
@ -129,16 +134,12 @@ LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
CFGSET = TRUE CFGSET = TRUE
!ENDIF !ENDIF
!IF "$(UNICODE)" == "1"
CFLAGS = $(CFLAGS) /D_UNICODE /DUNICODE
!ENDIF
####################### #######################
# Usage # Usage
# #
!IF "$(CFGSET)" == "FALSE" !IF "$(CFGSET)" == "FALSE"
!MESSAGE Usage: nmake /f Makefile.vc [CFG=<config>] !MESSAGE Usage: nmake /f Makefile.vc [CFG=<config>]
!MESSAGE . [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [UNICODE=1] [<target>] !MESSAGE . [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [<target>]
!MESSAGE !MESSAGE
!MESSAGE where <config> is one of: !MESSAGE where <config> is one of:
!MESSAGE - release-static - release static library !MESSAGE - release-static - release static library
@ -154,7 +155,6 @@ CFLAGS = $(CFLAGS) /D_UNICODE /DUNICODE
!MESSAGE - all - build (de)mux-based targets for CFG !MESSAGE - all - build (de)mux-based targets for CFG
!MESSAGE - gif2webp - requires libgif & >= VS2013 !MESSAGE - gif2webp - requires libgif & >= VS2013
!MESSAGE - anim_diff - requires libgif & >= VS2013 !MESSAGE - anim_diff - requires libgif & >= VS2013
!MESSAGE - anim_dump
!MESSAGE !MESSAGE
!MESSAGE RTLIBCFG controls the runtime library linkage - 'static' or 'dynamic'. !MESSAGE RTLIBCFG controls the runtime library linkage - 'static' or 'dynamic'.
!MESSAGE 'legacy' will produce a Windows 2000 compatible library. !MESSAGE 'legacy' will produce a Windows 2000 compatible library.
@ -226,21 +226,21 @@ DSP_DEC_OBJS = \
$(DIROBJ)\dsp\upsampling_msa.obj \ $(DIROBJ)\dsp\upsampling_msa.obj \
$(DIROBJ)\dsp\upsampling_neon.obj \ $(DIROBJ)\dsp\upsampling_neon.obj \
$(DIROBJ)\dsp\upsampling_sse2.obj \ $(DIROBJ)\dsp\upsampling_sse2.obj \
$(DIROBJ)\dsp\upsampling_sse41.obj \
$(DIROBJ)\dsp\yuv.obj \ $(DIROBJ)\dsp\yuv.obj \
$(DIROBJ)\dsp\yuv_mips32.obj \ $(DIROBJ)\dsp\yuv_mips32.obj \
$(DIROBJ)\dsp\yuv_mips_dsp_r2.obj \ $(DIROBJ)\dsp\yuv_mips_dsp_r2.obj \
$(DIROBJ)\dsp\yuv_neon.obj \
$(DIROBJ)\dsp\yuv_sse2.obj \ $(DIROBJ)\dsp\yuv_sse2.obj \
$(DIROBJ)\dsp\yuv_sse41.obj \
DSP_ENC_OBJS = \ DSP_ENC_OBJS = \
$(DIROBJ)\dsp\argb.obj \
$(DIROBJ)\dsp\argb_mips_dsp_r2.obj \
$(DIROBJ)\dsp\argb_sse2.obj \
$(DIROBJ)\dsp\cost.obj \ $(DIROBJ)\dsp\cost.obj \
$(DIROBJ)\dsp\cost_mips32.obj \ $(DIROBJ)\dsp\cost_mips32.obj \
$(DIROBJ)\dsp\cost_mips_dsp_r2.obj \ $(DIROBJ)\dsp\cost_mips_dsp_r2.obj \
$(DIROBJ)\dsp\cost_neon.obj \
$(DIROBJ)\dsp\cost_sse2.obj \ $(DIROBJ)\dsp\cost_sse2.obj \
$(DIROBJ)\dsp\enc.obj \ $(DIROBJ)\dsp\enc.obj \
$(DIROBJ)\dsp\enc_avx2.obj \
$(DIROBJ)\dsp\enc_mips32.obj \ $(DIROBJ)\dsp\enc_mips32.obj \
$(DIROBJ)\dsp\enc_mips_dsp_r2.obj \ $(DIROBJ)\dsp\enc_mips_dsp_r2.obj \
$(DIROBJ)\dsp\enc_msa.obj \ $(DIROBJ)\dsp\enc_msa.obj \
@ -254,8 +254,6 @@ DSP_ENC_OBJS = \
$(DIROBJ)\dsp\lossless_enc_neon.obj \ $(DIROBJ)\dsp\lossless_enc_neon.obj \
$(DIROBJ)\dsp\lossless_enc_sse2.obj \ $(DIROBJ)\dsp\lossless_enc_sse2.obj \
$(DIROBJ)\dsp\lossless_enc_sse41.obj \ $(DIROBJ)\dsp\lossless_enc_sse41.obj \
$(DIROBJ)\dsp\ssim.obj \
$(DIROBJ)\dsp\ssim_sse2.obj \
EX_ANIM_UTIL_OBJS = \ EX_ANIM_UTIL_OBJS = \
$(DIROBJ)\examples\anim_util.obj \ $(DIROBJ)\examples\anim_util.obj \
@ -265,7 +263,6 @@ IMAGEIO_DEC_OBJS = \
$(DIROBJ)\imageio\jpegdec.obj \ $(DIROBJ)\imageio\jpegdec.obj \
$(DIROBJ)\imageio\metadata.obj \ $(DIROBJ)\imageio\metadata.obj \
$(DIROBJ)\imageio\pngdec.obj \ $(DIROBJ)\imageio\pngdec.obj \
$(DIROBJ)\imageio\pnmdec.obj \
$(DIROBJ)\imageio\tiffdec.obj \ $(DIROBJ)\imageio\tiffdec.obj \
$(DIROBJ)\imageio\webpdec.obj \ $(DIROBJ)\imageio\webpdec.obj \
$(DIROBJ)\imageio\wicdec.obj \ $(DIROBJ)\imageio\wicdec.obj \
@ -282,10 +279,10 @@ EX_UTIL_OBJS = \
ENC_OBJS = \ ENC_OBJS = \
$(DIROBJ)\enc\alpha_enc.obj \ $(DIROBJ)\enc\alpha_enc.obj \
$(DIROBJ)\enc\analysis_enc.obj \ $(DIROBJ)\enc\analysis_enc.obj \
$(DIROBJ)\enc\backward_references_cost_enc.obj \
$(DIROBJ)\enc\backward_references_enc.obj \ $(DIROBJ)\enc\backward_references_enc.obj \
$(DIROBJ)\enc\config_enc.obj \ $(DIROBJ)\enc\config_enc.obj \
$(DIROBJ)\enc\cost_enc.obj \ $(DIROBJ)\enc\cost_enc.obj \
$(DIROBJ)\enc\delta_palettization_enc.obj \
$(DIROBJ)\enc\filter_enc.obj \ $(DIROBJ)\enc\filter_enc.obj \
$(DIROBJ)\enc\frame_enc.obj \ $(DIROBJ)\enc\frame_enc.obj \
$(DIROBJ)\enc\histogram_enc.obj \ $(DIROBJ)\enc\histogram_enc.obj \
@ -347,8 +344,7 @@ all: ex
OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe
EXTRA_EXAMPLES = $(DIRBIN)\vwebp.exe $(DIRBIN)\webpmux.exe \ EXTRA_EXAMPLES = $(DIRBIN)\vwebp.exe $(DIRBIN)\webpmux.exe \
$(DIRBIN)\img2webp.exe $(DIRBIN)\get_disto.exe \ $(DIRBIN)\img2webp.exe $(DIRBIN)\get_disto.exe \
$(DIRBIN)\webp_quality.exe $(DIRBIN)\vwebp_sdl.exe \ $(DIRBIN)\webp_quality.exe
$(DIRBIN)\webpinfo.exe
ex: $(OUT_LIBS) $(OUT_EXAMPLES) ex: $(OUT_LIBS) $(OUT_EXAMPLES)
all: ex $(EXTRA_EXAMPLES) all: ex $(EXTRA_EXAMPLES)
@ -356,58 +352,42 @@ all: ex $(EXTRA_EXAMPLES)
# C99 support which is only available from VS2013 onward. # C99 support which is only available from VS2013 onward.
gif2webp: $(DIRBIN)\gif2webp.exe gif2webp: $(DIRBIN)\gif2webp.exe
anim_diff: $(DIRBIN)\anim_diff.exe anim_diff: $(DIRBIN)\anim_diff.exe
anim_dump: $(DIRBIN)\anim_dump.exe
$(DIRBIN)\anim_diff.exe: $(DIROBJ)\examples\anim_diff.obj $(EX_ANIM_UTIL_OBJS) $(DIRBIN)\anim_diff.exe: $(DIROBJ)\examples\anim_diff.obj $(EX_ANIM_UTIL_OBJS)
$(DIRBIN)\anim_diff.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\anim_diff.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\anim_diff.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP) $(DIRBIN)\anim_diff.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\anim_dump.exe: $(DIROBJ)\examples\anim_dump.obj $(EX_ANIM_UTIL_OBJS)
$(DIRBIN)\anim_dump.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
$(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: $(DIROBJ)\examples\cwebp.obj $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\cwebp.exe: $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\cwebp.exe: $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\cwebp.exe: $(LIBWEBPDEMUX)
$(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS) $(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS) $(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS)
$(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_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: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS)
$(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX) $(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX)
$(DIRBIN)\gif2webp.exe: $(LIBWEBP) $(DIRBIN)\gif2webp.exe: $(LIBWEBP)
$(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj $(EX_UTIL_OBJS) $(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj $(EX_UTIL_OBJS)
$(DIRBIN)\vwebp.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP) $(DIRBIN)\vwebp.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\vwebp_sdl.exe: $(DIROBJ)\extras\vwebp_sdl.obj
$(DIRBIN)\vwebp_sdl.exe: $(DIROBJ)\extras\webp_to_sdl.obj
$(DIRBIN)\vwebp_sdl.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
$(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX) $(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX)
$(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP) $(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
$(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX) $(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX)
$(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS) $(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj $(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj
$(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
$(DIRBIN)\get_disto.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\webp_quality.exe: $(DIROBJ)\extras\webp_quality.obj $(DIRBIN)\webp_quality.exe: $(DIROBJ)\extras\webp_quality.obj
$(DIRBIN)\webp_quality.exe: $(IMAGEIO_UTIL_OBJS) $(DIRBIN)\webp_quality.exe: $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\webp_quality.exe: $(EXTRAS_OBJS) $(DIRBIN)\webp_quality.exe: $(EXTRAS_OBJS) $(LIBWEBP)
# EXTRA_OBJS requires private symbols from dsp. Explicitly add those when
# building libwebp as a dll.
!IF "$(DLLBUILD)" == "TRUE"
$(DIRBIN)\webp_quality.exe: $(DSP_DEC_OBJS)
!ENDIF
$(DIRBIN)\webp_quality.exe: $(LIBWEBP)
$(DIRBIN)\webpinfo.exe: $(DIROBJ)\examples\webpinfo.obj
$(DIRBIN)\webpinfo.exe: $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\webpinfo.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\webpinfo.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
$(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP) $(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP)
$(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS): $(OUTPUT_DIRS) $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS): $(OUTPUT_DIRS)
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(EXTRAS_OBJS): $(OUTPUT_DIRS) $(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(EXTRAS_OBJS): $(OUTPUT_DIRS)
!ENDIF # ARCH == ARM !ENDIF # ARCH == ARM
experimental:
$(MAKE) /f Makefile.vc \
CFG=$(CFG) \
CFLAGS="$(CFLAGS) /DWEBP_EXPERIMENTAL_FEATURES" /$(MAKEFLAGS)
$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS) $(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS)
$(LIBWEBP): $(LIBWEBP_OBJS) $(LIBWEBP): $(LIBWEBP_OBJS)
$(LIBWEBPMUX): $(LIBWEBPMUX_OBJS) $(LIBWEBPMUX): $(LIBWEBPMUX_OBJS)
@ -453,18 +433,18 @@ $(OUTPUT_DIRS):
$(DIROBJ)\$(DLLINC): $(DIROBJ)\$(DLLINC):
@echo #ifndef WEBP_DLL_H_ > $@ @echo #ifndef WEBP_DLL_H_ > $@
@echo #define WEBP_DLL_H_ >> $@ @echo #define WEBP_DLL_H_ >> $@
@echo #define WEBP_EXTERN __declspec(dllexport) >> $@ @echo #define WEBP_EXTERN(type) __declspec(dllexport) type >> $@
@echo #endif /* WEBP_DLL_H_ */ >> $@ @echo #endif /* WEBP_DLL_H_ */ >> $@
.SUFFIXES: .c .obj .res .exe .SUFFIXES: .c .obj .res .exe
# File-specific flag builds. Note batch rules take precedence over wildcards, # File-specific flag builds. Note batch rules take precedence over wildcards,
# so for now name each file individually. # so for now name each file individually.
$(DIROBJ)\dsp\enc_avx2.obj: src\dsp\enc_avx2.c
$(CC) $(CFLAGS) $(AVX2_FLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dsp\ \
src\dsp\$(@B).c
$(DIROBJ)\examples\anim_diff.obj: examples\anim_diff.c $(DIROBJ)\examples\anim_diff.obj: examples\anim_diff.c
$(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \ $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
/Fo$(DIROBJ)\examples\ examples\$(@B).c /Fo$(DIROBJ)\examples\ examples\$(@B).c
$(DIROBJ)\examples\anim_dump.obj: examples\anim_dump.c
$(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
/Fo$(DIROBJ)\examples\ examples\$(@B).c
$(DIROBJ)\examples\anim_util.obj: examples\anim_util.c $(DIROBJ)\examples\anim_util.obj: examples\anim_util.c
$(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \ $(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
/Fo$(DIROBJ)\examples\ examples\$(@B).c /Fo$(DIROBJ)\examples\ examples\$(@B).c
@ -494,18 +474,15 @@ $(DIROBJ)\examples\gifdec.obj: examples\gifdec.c
{src\utils}.c{$(DIROBJ)\utils}.obj:: {src\utils}.c{$(DIROBJ)\utils}.obj::
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\utils\ $< $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\utils\ $<
LNKLIBS = ole32.lib windowscodecs.lib shlwapi.lib
!IF "$(UNICODE)" == "1"
LNKLIBS = $(LNKLIBS) Shell32.lib
!ENDIF
{$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe: {$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS) $(LNKEXE) $(LDFLAGS) /OUT:$@ $** \
ole32.lib windowscodecs.lib shlwapi.lib
$(MT) -manifest $@.manifest -outputresource:$@;1 $(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest del $@.manifest
{$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe: {$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS) $(LNKEXE) $(LDFLAGS) /OUT:$@ $** \
ole32.lib windowscodecs.lib shlwapi.lib
$(MT) -manifest $@.manifest -outputresource:$@;1 $(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest del $@.manifest

78
NEWS
View File

@ -1,81 +1,3 @@
- 12/23/2020: version 1.2.0
* API changes:
- libwebp:
encode.h: add a qmin / qmax range for quality factor (cwebp adds -qrange)
* lossless encoder improvements
* SIMD support for Wasm builds
* add xcframeworkbuild.sh, supports Mac Catalyst builds
* import fuzzers from oss-fuzz & chromium (#409)
* webpmux: add an '-set loop <value>' option (#494)
* toolchain updates and bug fixes (#449, #463, #470, #475, #477, #478, #479,
#488, #491)
- 12/18/2019: version 1.1.0
* API changes:
- libwebp:
WebPMalloc (issue #442)
- extras:
WebPUnmultiplyARGB
* alpha decode fix (issue #439)
* toolchain updates and bug fixes
(chromium: #1026858, #1027136, #1027409, #1028620, #1028716, #995200)
(oss-fuzz: #19430, #19447)
- 7/4/2019: version 1.0.3
This is a binary compatible release.
* resize fixes for Nx1 sizes and the addition of non-opaque alpha values for
odd sizes (issues #418, #434)
* lossless encode/decode performance improvements
* lossy compression performance improvement at low quality levels with flat
content (issue #432)
* python swig files updated to support python 3
Tool updates:
vwebp will now preserve the aspect ratio of images that exceed monitor
resolution by scaling the image to fit (issue #433)
- 1/14/2019: version 1.0.2
This is a binary compatible release.
* (Windows) unicode file support in the tools (linux and mac already had
support, issue #398)
* lossless encoder speedups
* lossy encoder speedup on ARM
* lossless multi-threaded security fix (chromium:917029)
- 11/2/2018: version 1.0.1
This is a binary compatible release.
* lossless encoder speedups
* big-endian fix for alpha decoding (issue #393)
* gif2webp fix for loop count=65535 transcode (issue #382)
* further security related hardening in libwebp & libwebpmux
(issues #383, #385, #386, #387, #388, #391)
(oss-fuzz #9099, #9100, #9105, #9106, #9111, #9112, #9119, #9123, #9170,
#9178, #9179, #9183, #9186, #9191, #9364, #9417, #9496, #10349,
#10423, #10634, #10700, #10838, #10922, #11021, #11088, #11152)
* miscellaneous bug & build fixes (issues #381, #394, #396, #397, #400)
- 4/2/2018: version 1.0.0
This is a binary compatible release.
* lossy encoder improvements to avoid chroma shifts in various circumstances
(issues #308, #340)
* big-endian fixes for decode, RGBA import and WebPPictureDistortion
Tool updates:
gifwebp, anim_diff - default duration behavior (<= 10ms) changed to match
web browsers, transcoding tools (issue #379)
img2webp, webpmux - allow options to be passed in via a file (issue #355)
- 11/24/2017: version 0.6.1
This is a binary compatible release.
* lossless performance and compression improvements + a new 'cruncher' mode
(-m 6 -q 100)
* ARM performance improvements with clang (15-20% w/ndk r15c, issue #339)
* webp-js: emscripten/webassembly based javascript decoder
* miscellaneous bug & build fixes (issue #329, #332, #343, #353, #360, #361,
#363)
Tool updates / additions:
added webpinfo - prints file format information (issue #330)
gif2webp - loop behavior modified to match Chrome M63+ (crbug.com/649264);
'-loop_compatibility' can be used for the old behavior
- 1/26/2017: version 0.6.0 - 1/26/2017: version 0.6.0
* lossless performance and compression improvements * lossless performance and compression improvements
* miscellaneous performance improvements (SSE2, NEON, MSA) * miscellaneous performance improvements (SSE2, NEON, MSA)

61
README
View File

@ -4,7 +4,7 @@
\__\__/\____/\_____/__/ ____ ___ \__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/ / _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__ / \_/ / / \ \ __/ \__
\____/____/\_____/_____/____/v1.2.0 \____/____/\_____/_____/____/v0.6.0
Description: Description:
============ ============
@ -113,8 +113,8 @@ make install
CMake: CMake:
------ ------
With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo The support for CMake is minimal: it only helps you compile libwebp, cwebp and
and the JS bindings. dwebp.
Prerequisites: Prerequisites:
A compiler (e.g., gcc with autotools) and CMake. A compiler (e.g., gcc with autotools) and CMake.
@ -123,27 +123,18 @@ minimal build:
$ sudo apt-get install build-essential cmake $ sudo apt-get install build-essential cmake
When building from git sources, you will need to run cmake to generate the When building from git sources, you will need to run cmake to generate the
makefiles. configure script.
mkdir build && cd build && cmake ../ mkdir build && cd build && cmake ../
make make
make install make install
If you also want any of the executables, you will need to enable them through If you also want cwebp or dwebp, you will need to enable them through CMake:
CMake, e.g.:
cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../ cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../
or through your favorite interface (like ccmake or cmake-qt-gui). or through your favorite interface (like ccmake or cmake-qt-gui).
Use option -DWEBP_UNICODE=ON for Unicode support on Windows (with chcp 65001).
Finally, once installed, you can also use WebP in your CMake project by doing:
find_package(WebP)
which will define the CMake variables WebP_INCLUDE_DIRS and WebP_LIBRARIES.
Gradle: Gradle:
------- -------
The support for Gradle is minimal: it only helps you compile libwebp, cwebp and The support for Gradle is minimal: it only helps you compile libwebp, cwebp and
@ -225,7 +216,6 @@ Usage:
If input size (-s) for an image is not specified, it is If input size (-s) for an image is not specified, it is
assumed to be a PNG, JPEG, TIFF or WebP file. assumed to be a PNG, JPEG, TIFF or WebP file.
Note: Animated PNG and WebP files are not supported.
Options: Options:
-h / -help ............. short help -h / -help ............. short help
@ -255,8 +245,6 @@ Options:
-partition_limit <int> . limit quality to fit the 512k limit on -partition_limit <int> . limit quality to fit the 512k limit on
the first partition (0=no degradation ... 100=full) the first partition (0=no degradation ... 100=full)
-pass <int> ............ analysis pass number (1..10) -pass <int> ............ analysis pass number (1..10)
-qrange <min> <max> .... specifies the permissible quality range
(default: 0 100)
-crop <x> <y> <w> <h> .. crop picture with the given rectangle -crop <x> <y> <w> <h> .. crop picture with the given rectangle
-resize <w> <h> ........ resize picture (after any cropping) -resize <w> <h> ........ resize picture (after any cropping)
-mt .................... use multi-threading if available -mt .................... use multi-threading if available
@ -297,7 +285,6 @@ Experimental Options:
-af .................... auto-adjust filter strength -af .................... auto-adjust filter strength
-pre <int> ............. pre-processing filter -pre <int> ............. pre-processing filter
The main options you might want to try in order to further tune the The main options you might want to try in order to further tune the
visual quality are: visual quality are:
-preset -preset
@ -345,9 +332,7 @@ The full list of options is available using -h:
> dwebp -h > dwebp -h
Usage: dwebp in_file [options] [-o out_file] Usage: dwebp in_file [options] [-o out_file]
Decodes the WebP image file to PNG format [Default]. Decodes the WebP image file to PNG format [Default]
Note: Animated WebP files are not supported.
Use following options to convert into alternate image formats: Use following options to convert into alternate image formats:
-pam ......... save the raw RGBA samples as a color PAM -pam ......... save the raw RGBA samples as a color PAM
-ppm ......... save the raw RGB samples as a color PPM -ppm ......... save the raw RGB samples as a color PPM
@ -375,23 +360,6 @@ Use following options to convert into alternate image formats:
-quiet ....... quiet mode, don't print anything -quiet ....... quiet mode, don't print anything
-noasm ....... disable all assembly optimizations -noasm ....... disable all assembly optimizations
WebP file analysis tool:
========================
'webpinfo' can be used to print out the chunk level structure and bitstream
header information of WebP files. It can also check if the files are of valid
WebP format.
Usage: webpinfo [options] in_files
Note: there could be multiple input files;
options must come before input files.
Options:
-version ........... Print version number and exit.
-quiet ............. Do not show chunk parsing information.
-diag .............. Show parsing error diagnosis.
-summary ........... Show chunk stats summary.
-bitstream_info .... Parse bitstream header.
Visualization tool: Visualization tool:
=================== ===================
@ -410,14 +378,12 @@ Options are:
-nofilter .... disable in-loop filtering -nofilter .... disable in-loop filtering
-dither <int> dithering strength (0..100), default=50 -dither <int> dithering strength (0..100), default=50
-noalphadither disable alpha plane dithering -noalphadither disable alpha plane dithering
-usebgcolor .. display background color
-mt .......... use multi-threading -mt .......... use multi-threading
-info ........ print info -info ........ print info
-h ........... this help message -h ........... this help message
Keyboard shortcuts: Keyboard shortcuts:
'c' ................ toggle use of color profile 'c' ................ toggle use of color profile
'b' ................ toggle background color display
'i' ................ overlay file information 'i' ................ overlay file information
'd' ................ disable blending & disposal (debug) 'd' ................ disable blending & disposal (debug)
'q' / 'Q' / ESC .... quit 'q' / 'Q' / ESC .... quit
@ -429,7 +395,7 @@ Prerequisites:
1) OpenGL & OpenGL Utility Toolkit (GLUT) 1) OpenGL & OpenGL Utility Toolkit (GLUT)
Linux: Linux:
$ sudo apt-get install freeglut3-dev mesa-common-dev $ sudo apt-get install freeglut3-dev mesa-common-dev
Mac + Xcode: Mac + XCode:
- These libraries should be available in the OpenGL / GLUT frameworks. - These libraries should be available in the OpenGL / GLUT frameworks.
Windows: Windows:
http://freeglut.sourceforge.net/index.php#download http://freeglut.sourceforge.net/index.php#download
@ -468,7 +434,6 @@ File-level options (only used at the start of compression):
-mixed ............... use mixed lossy/lossless automatic mode -mixed ............... use mixed lossy/lossless automatic mode
-v ................... verbose mode -v ................... verbose mode
-h ................... this help -h ................... this help
-version ............. print version number and exit
Per-frame options (only used for subsequent images input): Per-frame options (only used for subsequent images input):
-d <int> ............. frame duration in ms (default: 100) -d <int> ............. frame duration in ms (default: 100)
@ -480,9 +445,6 @@ Per-frame options (only used for subsequent images input):
example: img2webp -loop 2 in0.png -lossy in1.jpg example: img2webp -loop 2 in0.png -lossy in1.jpg
-d 80 in2.tiff -o out.webp -d 80 in2.tiff -o out.webp
Note: if a single file name is passed as the argument, the arguments will be
tokenized from this file. The file name must not start with the character '-'.
Animated GIF conversion: Animated GIF conversion:
======================== ========================
Animated GIF files can be converted to WebP files with animation using the Animated GIF files can be converted to WebP files with animation using the
@ -508,8 +470,6 @@ Options:
-metadata <string> ..... comma separated list of metadata to -metadata <string> ..... comma separated list of metadata to
copy from the input to the output if present copy from the input to the output if present
Valid values: all, none, icc, xmp (default) Valid values: all, none, icc, xmp (default)
-loop_compatibility .... use compatibility mode for Chrome
version prior to M62 (inclusive)
-mt .................... use multi-threading if available -mt .................... use multi-threading if available
-version ............... print version number and exit -version ............... print version number and exit
@ -538,11 +498,6 @@ Options:
-min_psnr <float> ... minimum per-frame PSNR -min_psnr <float> ... minimum per-frame PSNR
-raw_comparison ..... if this flag is not used, RGB is -raw_comparison ..... if this flag is not used, RGB is
premultiplied before comparison premultiplied before comparison
-max_diff <int> ..... maximum allowed difference per channel
between corresponding pixels in subsequent
frames
-h .................. this help
-version ............ print version number and exit
Building: Building:
--------- ---------
@ -603,7 +558,7 @@ The encoding flow looks like:
// Setup a config, starting form a preset and tuning some additional // Setup a config, starting form a preset and tuning some additional
// parameters // parameters
WebPConfig config; WebPConfig config;
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) { if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor))
return 0; // version error return 0; // version error
} }
// ... additional tuning // ... additional tuning

View File

@ -1,7 +1,7 @@
 __ __ ____ ____ ____ __ __ _ __ __  __ __ ____ ____ ____ __ __ _ __ __
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\ / \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
\ / __/ _ \ __/ / / (_/ /__ \ / __/ _ \ __/ / / (_/ /__
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.2.0 \__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.4.0
Description: Description:
@ -33,7 +33,6 @@ Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
webpmux -info INPUT webpmux -info INPUT
webpmux [-h|-help] webpmux [-h|-help]
webpmux -version webpmux -version
webpmux argument_file_name
GET_OPTIONS: GET_OPTIONS:
Extract relevant data: Extract relevant data:
@ -44,7 +43,6 @@ GET_OPTIONS:
SET_OPTIONS: SET_OPTIONS:
Set color profile/metadata: Set color profile/metadata:
loop LOOP_COUNT set the loop count
icc file.icc set ICC profile icc file.icc set ICC profile
exif file.exif set EXIF metadata exif file.exif set EXIF metadata
xmp file.xmp set XMP metadata xmp file.xmp set XMP metadata
@ -94,9 +92,6 @@ INPUT & OUTPUT are in WebP format.
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
valid. valid.
Note: if a single file name is passed as the argument, the arguments will be
tokenized from this file. The file name must not start with the character '-'.
Visualization tool: Visualization tool:
=================== ===================
@ -212,35 +207,6 @@ Code example:
For a detailed AnimEncoder API reference, please refer to the header file For a detailed AnimEncoder API reference, please refer to the header file
(src/webp/mux.h). (src/webp/mux.h).
AnimDecoder API:
================
This AnimDecoder API allows decoding (possibly) animated WebP images.
Code Example:
WebPAnimDecoderOptions dec_options;
WebPAnimDecoderOptionsInit(&dec_options);
// Tune 'dec_options' as needed.
WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
WebPAnimInfo anim_info;
WebPAnimDecoderGetInfo(dec, &anim_info);
for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
while (WebPAnimDecoderHasMoreFrames(dec)) {
uint8_t* buf;
int timestamp;
WebPAnimDecoderGetNext(dec, &buf, &timestamp);
// ... (Render 'buf' based on 'timestamp').
// ... (Do NOT free 'buf', as it is owned by 'dec').
}
WebPAnimDecoderReset(dec);
}
const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
// ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
WebPAnimDecoderDelete(dec);
For a detailed AnimDecoder API reference, please refer to the header file
(src/webp/demux.h).
Bugs: Bugs:
===== =====

View File

@ -1,83 +0,0 @@
__ __ ____ ____ ____ __ ____
/ \\/ \ _ \ _ \ _ \ (__)/ __\
\ / __/ _ \ __/ _) \_ \
\__\__/_____/____/_/ /____/____/
Description:
============
This file describes the compilation of libwebp into a JavaScript decoder
using Emscripten and CMake.
- install the Emscripten SDK following the procedure described at:
https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html
After installation, you should have some global variable positioned to the
location of the SDK. In particular, $EMSCRIPTEN should point to the
top-level directory containing Emscripten tools.
- make sure the file $EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake is
accessible. This is the toolchain file used by CMake to invoke Emscripten.
If $EMSCRIPTEN is unset search for Emscripten.cmake under $EMSDK and set
$EMSCRIPTEN accordingly, for example:
unix-like environments: export EMSCRIPTEN=$EMSDK/upstream/emscripten
windows: set EMSCRIPTEN=%EMSDK%\upstream\emscripten
- configure the project 'WEBP_JS' with CMake using:
cd webp_js && \
cmake -DWEBP_BUILD_WEBP_JS=ON \
-DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake \
../
- compile webp.js using 'make'.
- that's it! Upon completion, you should have the webp.js and
webp.wasm files generated.
The callable JavaScript function is WebPToSDL(), which decodes a raw WebP
bitstream into a canvas. See webp_js/index.html for a simple usage sample
(see below for instructions).
Demo HTML page:
===============
The HTML page webp_js/index.html requires an HTTP server to serve the WebP
image example. It's easy to just use Python for that.
cd webp_js && python -m SimpleHTTPServer 8080
and then navigate to http://localhost:8080 in your favorite browser.
Web-Assembly (WASM) version:
============================
CMakeLists.txt is configured to build the WASM version when using
the option WEBP_BUILD_WEBP_JS=ON. The compilation step will assemble
the files 'webp_wasm.js', 'webp_wasm.wasm' in the webp_js/ directory.
See webp_js/index_wasm.html for a simple demo page using the WASM version
of the library.
You will need a fairly recent version of Emscripten (at least 1.37.8,
latest-upstream is recommended) and of your WASM-enabled browser to run this
version.
Caveat:
=======
- First decoding using the library is usually slower, due to just-in-time
compilation.
- Some versions of llvm produce the following compile error when SSE2 is
enabled.
"Unsupported: %516 = bitcast <8 x i16> %481 to i128
LLVM ERROR: BitCast Instruction not yet supported for integer types larger than 64 bits"
The corresponding Emscripten bug is at:
https://github.com/kripken/emscripten/issues/3788
Therefore, SSE2 optimization is currently disabled in CMakeLists.txt.
- If WEBP_ENABLE_SIMD is set to 1 the JavaScript version (webp.js) will be
disabled as wasm2js does not support SIMD.

View File

@ -74,22 +74,12 @@ model {
cCompiler.args "-frename-registers -s" cCompiler.args "-frename-registers -s"
} }
} }
// mips32 fails to build with clang from r14b
// https://bugs.chromium.org/p/webp/issues/detail?id=343
if (toolChain in Clang) {
if (getTargetPlatform() == "mips") {
cCompiler.args "-no-integrated-as"
}
}
// Check for NEON usage. // Check for NEON usage.
if (getTargetPlatform() == "arm") { if (getTargetPlatform() == "arm" || getTargetPlatform() == "arm64") {
NEON = "c.neon" NEON = "c.neon"
cCompiler.define "HAVE_CPU_FEATURES_H"
} else { } else {
NEON = "c" NEON = "c"
} }
cCompiler.args "-I" + file(".").absolutePath
} }
// Link to pthread for shared libraries. // Link to pthread for shared libraries.
withType(SharedLibraryBinarySpec) { withType(SharedLibraryBinarySpec) {
@ -122,6 +112,9 @@ model {
include "alpha_processing_neon.$NEON" include "alpha_processing_neon.$NEON"
include "alpha_processing_sse2.c" include "alpha_processing_sse2.c"
include "alpha_processing_sse41.c" include "alpha_processing_sse41.c"
include "argb.c"
include "argb_mips_dsp_r2.c"
include "argb_sse2.c"
include "cpu.c" include "cpu.c"
include "dec.c" include "dec.c"
include "dec_clip_tables.c" include "dec_clip_tables.c"
@ -152,13 +145,10 @@ model {
include "upsampling_msa.c" include "upsampling_msa.c"
include "upsampling_neon.$NEON" include "upsampling_neon.$NEON"
include "upsampling_sse2.c" include "upsampling_sse2.c"
include "upsampling_sse41.c"
include "yuv.c" include "yuv.c"
include "yuv_mips32.c" include "yuv_mips32.c"
include "yuv_mips_dsp_r2.c" include "yuv_mips_dsp_r2.c"
include "yuv_neon.$NEON"
include "yuv_sse2.c" include "yuv_sse2.c"
include "yuv_sse41.c"
srcDir "src/utils" srcDir "src/utils"
include "bit_reader_utils.c" include "bit_reader_utils.c"
include "color_cache_utils.c" include "color_cache_utils.c"
@ -173,9 +163,9 @@ model {
include "cost.c" include "cost.c"
include "cost_mips32.c" include "cost_mips32.c"
include "cost_mips_dsp_r2.c" include "cost_mips_dsp_r2.c"
include "cost_neon.$NEON"
include "cost_sse2.c" include "cost_sse2.c"
include "enc.c" include "enc.c"
include "enc_avx2.c"
include "enc_mips32.c" include "enc_mips32.c"
include "enc_mips_dsp_r2.c" include "enc_mips_dsp_r2.c"
include "enc_msa.c" include "enc_msa.c"
@ -189,15 +179,13 @@ model {
include "lossless_enc_neon.$NEON" include "lossless_enc_neon.$NEON"
include "lossless_enc_sse2.c" include "lossless_enc_sse2.c"
include "lossless_enc_sse41.c" include "lossless_enc_sse41.c"
include "ssim.c"
include "ssim_sse2.c"
srcDir "src/enc" srcDir "src/enc"
include "alpha_enc.c" include "alpha_enc.c"
include "analysis_enc.c" include "analysis_enc.c"
include "backward_references_cost_enc.c"
include "backward_references_enc.c" include "backward_references_enc.c"
include "config_enc.c" include "config_enc.c"
include "cost_enc.c" include "cost_enc.c"
include "delta_palettization_enc.c"
include "filter_enc.c" include "filter_enc.c"
include "frame_enc.c" include "frame_enc.c"
include "histogram_enc.c" include "histogram_enc.c"
@ -289,7 +277,6 @@ model {
imagedec(NativeLibrarySpec) { imagedec(NativeLibrarySpec) {
binaries { binaries {
all { all {
lib library: "webpdemux", linkage: "static"
lib library: "webp", linkage: "static" lib library: "webp", linkage: "static"
} }
} }
@ -301,7 +288,6 @@ model {
include "jpegdec.c" include "jpegdec.c"
include "metadata.c" include "metadata.c"
include "pngdec.c" include "pngdec.c"
include "pnmdec.c"
include "tiffdec.c" include "tiffdec.c"
include "webpdec.c" include "webpdec.c"
} }
@ -332,7 +318,6 @@ model {
lib library: "example_util", linkage: "static" lib library: "example_util", linkage: "static"
lib library: "imagedec", linkage: "static" lib library: "imagedec", linkage: "static"
lib library: "imageio_util", linkage: "static" lib library: "imageio_util", linkage: "static"
lib library: "webpdemux", linkage: "static"
lib library: "webp", linkage: "static" lib library: "webp", linkage: "static"
} }
} }
@ -353,7 +338,6 @@ model {
lib library: "imagedec", linkage: "static" lib library: "imagedec", linkage: "static"
lib library: "imageenc", linkage: "static" lib library: "imageenc", linkage: "static"
lib library: "imageio_util", linkage: "static" lib library: "imageio_util", linkage: "static"
lib library: "webpdemux", linkage: "static"
lib library: "webp" lib library: "webp"
} }
} }
@ -393,7 +377,6 @@ model {
lib library: "imagedec", linkage: "static" lib library: "imagedec", linkage: "static"
lib library: "imageio_util", linkage: "static" lib library: "imageio_util", linkage: "static"
lib library: "webpmux", linkage: "static" lib library: "webpmux", linkage: "static"
lib library: "webpdemux", linkage: "static"
lib library: "webp" lib library: "webp"
} }
} }
@ -406,24 +389,6 @@ model {
} }
} }
} }
webpinfo_example(NativeExecutableSpec) {
binaries {
all {
lib library: "example_util", linkage: "static"
lib library: "imageio_util", linkage: "static"
lib library: "webp"
}
}
sources {
c {
source {
srcDir "./examples"
include "webpinfo.c"
}
}
}
}
} }
tasks { tasks {
// Task to test all possible configurations. // Task to test all possible configurations.
@ -432,3 +397,8 @@ model {
} }
} }
} }
// Task to generate the wrapper.
task wrapper(type: Wrapper) {
gradleVersion = '2.13'
}

View File

@ -1,11 +0,0 @@
set(WebP_VERSION @PROJECT_VERSION@)
set(WEBP_VERSION ${WebP_VERSION})
@PACKAGE_INIT@
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
set(WebP_INCLUDE_DIRS "webp")
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIRS})
set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@")
set(WEBP_LIBRARIES "${WebP_LIBRARIES}")

View File

@ -1,44 +1,48 @@
# Generate the config.h to compile with specific intrinsics / libs. # Generate the config.h to compile with specific intrinsics / libs.
# Check for compiler options. ## Check for compiler options.
include(CheckCSourceCompiles) include(CheckCSourceCompiles)
check_c_source_compiles(" check_c_source_compiles("
int main(void) { int main(void) {
(void)__builtin_bswap16(0); (void)__builtin_bswap16(0);
return 0; return 0;
} }
" HAVE_BUILTIN_BSWAP16) "
HAVE_BUILTIN_BSWAP16
)
check_c_source_compiles(" check_c_source_compiles("
int main(void) { int main(void) {
(void)__builtin_bswap32(0); (void)__builtin_bswap32(0);
return 0; return 0;
} }
" HAVE_BUILTIN_BSWAP32) "
HAVE_BUILTIN_BSWAP32
)
check_c_source_compiles(" check_c_source_compiles("
int main(void) { int main(void) {
(void)__builtin_bswap64(0); (void)__builtin_bswap64(0);
return 0; return 0;
} }
" HAVE_BUILTIN_BSWAP64) "
HAVE_BUILTIN_BSWAP64
)
# Check for libraries. ## Check for libraries.
if(NOT WEBP_BUILD_WEBP_JS) find_package(Threads)
# Disable pThreads for WASM.
find_package(Threads)
endif()
if(Threads_FOUND) if(Threads_FOUND)
# work around cmake bug on QNX (https://cmake.org/Bug/view.php?id=11333) if(CMAKE_USE_PTHREADS_INIT)
if(CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
endif() endif()
check_c_source_compiles(" foreach(PTHREAD_TEST HAVE_PTHREAD_PRIO_INHERIT PTHREAD_CREATE_UNDETACHED)
#include <pthread.h> check_c_source_compiles("
int main (void) { #include <pthread.h>
int attr = PTHREAD_PRIO_INHERIT; int main (void) {
return attr; int attr = ${PTHREAD_TEST};
} return attr;
" FLAG_HAVE_PTHREAD_PRIO_INHERIT) }
set(HAVE_PTHREAD_PRIO_INHERIT ${FLAG_HAVE_PTHREAD_PRIO_INHERIT}) " ${PTHREAD_TEST}
)
endforeach()
list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif() endif()
set(WEBP_USE_THREAD ${Threads_FOUND}) set(WEBP_USE_THREAD ${Threads_FOUND})
@ -47,69 +51,30 @@ set(WEBP_USE_THREAD ${Threads_FOUND})
set(LT_OBJDIR ".libs/") set(LT_OBJDIR ".libs/")
# Only useful for vwebp, so useless for now. # Only useful for vwebp, so useless for now.
find_package(OpenGL) # find_package(OpenGL)
set(WEBP_HAVE_GL ${OPENGL_FOUND}) # set(WEBP_HAVE_GL ${OPENGL_FOUND})
# set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIRS})
# set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} ${OPENGL_LIBRARIES})
# Check if we need to link to the C math library. We do not look for it as it is # Find the standard C math library.
# not found when cross-compiling, while it is here. find_library(MATH_LIBRARY NAMES m)
check_c_source_compiles(" if(MATH_LIBRARY)
#include <math.h> list(APPEND WEBP_DEP_LIBRARIES ${MATH_LIBRARY})
int main(int argc, char** argv) {
return (int)pow(argc, 2.5);
}
" HAVE_MATH_LIBRARY)
if(NOT HAVE_MATH_LIBRARY)
message(STATUS "Adding -lm flag.")
list(APPEND WEBP_DEP_LIBRARIES m)
endif() endif()
# Find the standard image libraries. # Find the standard image libraries.
set(WEBP_DEP_IMG_LIBRARIES) set(WEBP_DEP_IMG_LIBRARIES)
set(WEBP_DEP_IMG_INCLUDE_DIRS) set(WEBP_DEP_IMG_INCLUDE_DIRS)
foreach(I_LIB PNG JPEG TIFF) foreach(I_LIB PNG JPEG TIFF GIF)
find_package(${I_LIB}) find_package(${I_LIB})
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND}) set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
if(${I_LIB}_FOUND) if(${I_LIB}_FOUND)
list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES}) list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES})
list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIR} list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIRS})
${${I_LIB}_INCLUDE_DIRS})
endif() endif()
endforeach() endforeach()
if(WEBP_DEP_IMG_INCLUDE_DIRS)
list(REMOVE_DUPLICATES WEBP_DEP_IMG_INCLUDE_DIRS)
endif()
# GIF detection, gifdec isn't part of the imageio lib. ## Check for specific headers.
include(CMakePushCheckState)
set(WEBP_DEP_GIF_LIBRARIES)
set(WEBP_DEP_GIF_INCLUDE_DIRS)
find_package(GIF)
set(WEBP_HAVE_GIF ${GIF_FOUND})
if(GIF_FOUND)
# GIF find_package only locates the header and library, it doesn't fail
# compile tests when detecting the version, but falls back to 3 (as of at
# least cmake 3.7.2). Make sure the library links to avoid incorrect detection
# when cross compiling.
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES})
set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR})
check_c_source_compiles("
#include <gif_lib.h>
int main(void) {
(void)DGifOpenFileHandle;
return 0;
}
" GIF_COMPILES)
cmake_pop_check_state()
if(GIF_COMPILES)
list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES})
list(APPEND WEBP_DEP_GIF_INCLUDE_DIRS ${GIF_INCLUDE_DIR})
else()
unset(GIF_FOUND)
endif()
endif()
# Check for specific headers.
include(CheckIncludeFiles) include(CheckIncludeFiles)
check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS) check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS)
check_include_files(dlfcn.h HAVE_DLFCN_H) check_include_files(dlfcn.h HAVE_DLFCN_H)
@ -131,32 +96,25 @@ check_include_files(windows.h HAVE_WINDOWS_H)
# Windows specifics # Windows specifics
if(HAVE_WINCODEC_H) if(HAVE_WINCODEC_H)
list(APPEND WEBP_DEP_LIBRARIES list(APPEND WEBP_DEP_LIBRARIES shlwapi ole32 windowscodecs)
shlwapi
ole32
windowscodecs)
endif() endif()
# Check for SIMD extensions. ## Check for SIMD extensions.
include(${CMAKE_CURRENT_LIST_DIR}/cpu.cmake) include(${CMAKE_CURRENT_LIST_DIR}/cpu.cmake)
# Define extra info. ## Define extra info.
set(PACKAGE ${PROJECT_NAME}) set(PACKAGE ${PROJECT_NAME})
set(PACKAGE_NAME ${PROJECT_NAME}) set(PACKAGE_NAME ${PROJECT_NAME})
# Read from configure.ac. # Read from configure.ac.
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_AC) file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_AC)
string(REGEX MATCHALL string(REGEX MATCHALL "\\[([0-9a-z\\.:/]*)\\]"
"\\[([0-9a-z\\.:/]*)\\]" CONFIGURE_AC_PACKAGE_INFO ${CONFIGURE_AC}
CONFIGURE_AC_PACKAGE_INFO )
${CONFIGURE_AC})
function(strip_bracket VAR) function(strip_bracket VAR)
string(LENGTH ${${VAR}} TMP_LEN) string(LENGTH ${${VAR}} TMP_LEN)
math(EXPR TMP_LEN ${TMP_LEN}-2) math(EXPR TMP_LEN ${TMP_LEN}-2)
string(SUBSTRING ${${VAR}} string(SUBSTRING ${${VAR}} 1 ${TMP_LEN} TMP_SUB)
1
${TMP_LEN}
TMP_SUB)
set(${VAR} ${TMP_SUB} PARENT_SCOPE) set(${VAR} ${TMP_SUB} PARENT_SCOPE)
endfunction() endfunction()
@ -171,3 +129,13 @@ strip_bracket(PACKAGE_URL)
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_TARNAME ${PACKAGE_NAME}) set(PACKAGE_TARNAME ${PACKAGE_NAME})
set(VERSION ${PACKAGE_VERSION}) set(VERSION ${PACKAGE_VERSION})
## Generate the config.h header.
configure_file(${CMAKE_CURRENT_LIST_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/webp/config.h)
add_definitions(-DHAVE_CONFIG_H)
# The webp folder is included as we reference config.h as
# ../webp/config.h or webp/config.h
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/include/webp
)

View File

@ -13,9 +13,6 @@
/* Set to 1 if __builtin_bswap64 is available */ /* Set to 1 if __builtin_bswap64 is available */
#cmakedefine HAVE_BUILTIN_BSWAP64 1 #cmakedefine HAVE_BUILTIN_BSWAP64 1
/* Define to 1 if you have the <cpu-features.h> header file. */
#cmakedefine HAVE_CPU_FEATURES_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */ /* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1 #cmakedefine HAVE_DLFCN_H 1
@ -93,12 +90,22 @@
/* Define to the version of this package. */ /* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@" #cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#cmakedefine PTHREAD_CREATE_JOINABLE 1
/* Define to 1 if you have the ANSI C header files. */ /* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1 #cmakedefine STDC_HEADERS 1
/* Version number of package */ /* Version number of package */
#cmakedefine VERSION "@VERSION@" #cmakedefine VERSION "@VERSION@"
/* Enable experimental code */
#cmakedefine WEBP_EXPERIMENTAL_FEATURES 1
/* Set to 1 if AVX2 is supported */
#cmakedefine WEBP_HAVE_AVX2 1
/* Set to 1 if GIF library is installed */ /* Set to 1 if GIF library is installed */
#cmakedefine WEBP_HAVE_GIF 1 #cmakedefine WEBP_HAVE_GIF 1
@ -108,19 +115,9 @@
/* Set to 1 if JPEG library is installed */ /* Set to 1 if JPEG library is installed */
#cmakedefine WEBP_HAVE_JPEG 1 #cmakedefine WEBP_HAVE_JPEG 1
/* Set to 1 if NEON is supported */
#cmakedefine WEBP_HAVE_NEON
/* Set to 1 if runtime detection of NEON is enabled */
/* TODO: handle properly in CMake */
#cmakedefine WEBP_HAVE_NEON_RTCD
/* Set to 1 if PNG library is installed */ /* Set to 1 if PNG library is installed */
#cmakedefine WEBP_HAVE_PNG 1 #cmakedefine WEBP_HAVE_PNG 1
/* Set to 1 if SDL library is installed */
#cmakedefine WEBP_HAVE_SDL 1
/* Set to 1 if SSE2 is supported */ /* Set to 1 if SSE2 is supported */
#cmakedefine WEBP_HAVE_SSE2 1 #cmakedefine WEBP_HAVE_SSE2 1
@ -130,9 +127,6 @@
/* Set to 1 if TIFF library is installed */ /* Set to 1 if TIFF library is installed */
#cmakedefine WEBP_HAVE_TIFF 1 #cmakedefine WEBP_HAVE_TIFF 1
/* Enable near lossless encoding */
#cmakedefine WEBP_NEAR_LOSSLESS 1
/* Undefine this to disable thread support. */ /* Undefine this to disable thread support. */
#cmakedefine WEBP_USE_THREAD 1 #cmakedefine WEBP_USE_THREAD 1

View File

@ -1,15 +1,7 @@
# Check for SIMD extensions. ## Check for SIMD extensions.
include(CMakePushCheckState)
function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD) function(webp_check_compiler_flag WEBP_SIMD_FLAG)
if(NOT ENABLE_SIMD)
message(STATUS "Disabling ${WEBP_SIMD_FLAG} optimization.")
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE)
return()
endif()
unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE) unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE)
cmake_push_check_state()
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
check_c_source_compiles(" check_c_source_compiles("
#include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\" #include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\"
int main(void) { int main(void) {
@ -18,8 +10,8 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
#endif #endif
return 0; return 0;
} }
" WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) " WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}
cmake_pop_check_state() )
if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE) set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE)
else() else()
@ -28,26 +20,16 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
endfunction() endfunction()
# those are included in the names of WEBP_USE_* in c++ code. # those are included in the names of WEBP_USE_* in c++ code.
set(WEBP_SIMD_FLAGS "SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA") set(WEBP_SIMD_FLAGS "SSE2;SSE41;AVX2;MIPS32;MIPS_DSP_R2;NEON;MSA")
set(WEBP_SIMD_FILE_EXTENSIONS set(WEBP_SIMD_FILE_EXTENSIONS "_sse2.c;_sse41.c;_avx2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
"_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c") if(MSVC)
if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC") # MSVC does not have a SSE4 flag but AVX2 support implies
# With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2 # SSE4 support.
# or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4 set(SIMD_ENABLE_FLAGS "/arch:SSE2;/arch:AVX2;/arch:AVX2;;;;")
# flag, but an AVX one. Using that with SSE4 code risks generating illegal
# instructions when used on machines with SSE4 only. The flags are left for
# older (untested) versions to avoid any potential compatibility issues.
if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:")
set(SIMD_ENABLE_FLAGS)
else()
set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;")
endif()
set(SIMD_DISABLE_FLAGS) set(SIMD_DISABLE_FLAGS)
else() else()
set(SIMD_ENABLE_FLAGS set(SIMD_ENABLE_FLAGS "-msse2;-msse4.1;-mavx2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
"-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa") set(SIMD_DISABLE_FLAGS "-mno-sse2;-mno-sse4.1;-mno-avx2;;-mno-dspr2;;-mno-msa")
set(SIMD_DISABLE_FLAGS
"-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
endif() endif()
set(WEBP_SIMD_FILES_TO_NOT_INCLUDE) set(WEBP_SIMD_FILES_TO_NOT_INCLUDE)
@ -56,9 +38,10 @@ set(WEBP_SIMD_FLAGS_TO_INCLUDE)
if(${ANDROID}) if(${ANDROID})
if(${ANDROID_ABI} STREQUAL "armeabi-v7a") if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
# This is because Android studio uses the configuration "-march=armv7-a # This is because Android studio uses the configuration
# -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon # "-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16"
# optimizations but should (as this configuration does not exist anymore). # that does not trigger neon optimizations but should
# (as this configuration does not exist anymore).
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ")
endif() endif()
endif() endif()
@ -67,40 +50,25 @@ list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH)
math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1") math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1")
foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE}) foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
# With Emscripten 2.0.9 -msimd128 -mfpu=neon will enable NEON, but the
# source will fail to compile.
if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 2)
break()
endif()
list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG) list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG)
# First try with no extra flag added as the compiler might have default flags # First try with no extra flag added as the compiler might have default flags
# (especially on Android). # (especially on Android).
unset(WEBP_HAVE_${WEBP_SIMD_FLAG} CACHE) unset(WEBP_HAVE_${WEBP_SIMD_FLAG} CACHE)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS) set(CMAKE_REQUIRED_FLAGS)
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) webp_check_compiler_flag(${WEBP_SIMD_FLAG})
if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG}) if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG})
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
if(EMSCRIPTEN)
set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}")
endif()
set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG}) set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG})
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) webp_check_compiler_flag(${WEBP_SIMD_FLAG})
else() else()
if(MSVC AND SIMD_ENABLE_FLAGS) set(SIMD_COMPILE_FLAG " ")
# The detection for SSE2/SSE4 support under MSVC is based on the compiler
# version so e.g., clang-cl will require flags to enable the assembly.
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
else()
set(SIMD_COMPILE_FLAG " ")
endif()
endif() endif()
# Check which files we should include or not. # Check which files we should include or not.
list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION) list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION)
file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../" file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../"
"src/dsp/*${WEBP_SIMD_FILE_EXTENSION}") "src/dsp/*${WEBP_SIMD_FILE_EXTENSION}"
)
if(WEBP_HAVE_${WEBP_SIMD_FLAG}) if(WEBP_HAVE_${WEBP_SIMD_FLAG})
# Memorize the file and flags. # Memorize the file and flags.
foreach(FILE ${SIMD_FILES}) foreach(FILE ${SIMD_FILES})
@ -128,12 +96,11 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
set(COMMON_PATTERNS) set(COMMON_PATTERNS)
endif() endif()
set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG}) set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG})
check_c_source_compiles("int main(void) {return 0;}" check_c_source_compiles("int main(void) {return 0;}" FLAG2
FLAG_${SIMD_COMPILE_FLAG} FAIL_REGEX "warning: argument unused during compilation:"
FAIL_REGEX ${COMMON_PATTERNS}
"warning: argument unused during compilation:" )
${COMMON_PATTERNS}) if(NOT FLAG2)
if(NOT FLAG_${SIMD_COMPILE_FLAG})
unset(HAS_COMPILE_FLAG CACHE) unset(HAS_COMPILE_FLAG CACHE)
endif() endif()
endif() endif()
@ -143,5 +110,4 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
endif() endif()
endif() endif()
endif() endif()
cmake_pop_check_state()
endforeach() endforeach()

View File

@ -1,4 +0,0 @@
# This file is used by git cl to get repository specific information.
GERRIT_HOST: True
CODE_REVIEW_SERVER: chromium-review.googlesource.com
GERRIT_SQUASH_UPLOADS: False

View File

@ -1,4 +1,4 @@
AC_INIT([libwebp], [1.2.0], AC_INIT([libwebp], [0.6.0],
[https://bugs.chromium.org/p/webp],, [https://bugs.chromium.org/p/webp],,
[http://developers.google.com/speed/webp]) [http://developers.google.com/speed/webp])
AC_CANONICAL_HOST AC_CANONICAL_HOST
@ -67,7 +67,6 @@ AC_DEFUN([TEST_AND_ADD_CFLAGS],
CFLAGS="$SAVED_CFLAGS"]) CFLAGS="$SAVED_CFLAGS"])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-fvisibility=hidden]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-fvisibility=hidden])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wconstant-conversion])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wfloat-conversion]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wfloat-conversion])
@ -76,11 +75,8 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-security])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-declarations]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-declarations])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wundef])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code-aggressive])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused-but-set-variable]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused-but-set-variable])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused]) TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused])
@ -123,6 +119,31 @@ AS_IF([test "$GCC" = "yes" ], [
AC_SUBST([AM_CFLAGS]) AC_SUBST([AM_CFLAGS])
dnl === Check for machine specific flags dnl === Check for machine specific flags
AC_ARG_ENABLE([avx2],
AS_HELP_STRING([--disable-avx2],
[Disable detection of AVX2 support
@<:@default=auto@:>@]))
AS_IF([test "x$enable_avx2" != "xno" -a "x$enable_sse4_1" != "xno" \
-a "x$enable_sse2" != "xno"], [
AVX2_CFLAGS="$INTRINSICS_CFLAGS $AVX2_FLAGS"
TEST_AND_ADD_CFLAGS([AVX2_FLAGS], [-mavx2])
AS_IF([test -n "$AVX2_FLAGS"], [
SAVED_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS $AVX2_FLAGS"
AC_CHECK_HEADER([immintrin.h],
[AC_DEFINE(WEBP_HAVE_AVX2, [1],
[Set to 1 if AVX2 is supported])],
[AVX2_FLAGS=""],
dnl it's illegal to directly include avx2intrin.h, but it's
dnl included conditionally in immintrin.h, tricky!
[#ifndef __AVX2__
#error avx2 is not enabled
#endif
])
CFLAGS=$SAVED_CFLAGS])
AC_SUBST([AVX2_FLAGS])])
AC_ARG_ENABLE([sse4.1], AC_ARG_ENABLE([sse4.1],
AS_HELP_STRING([--disable-sse4.1], AS_HELP_STRING([--disable-sse4.1],
[Disable detection of SSE4.1 support [Disable detection of SSE4.1 support
@ -220,13 +241,9 @@ AS_IF([test "x$enable_neon" != "xno"], [
NEON_FLAGS=""], NEON_FLAGS=""],
[AC_DEFINE(WEBP_HAVE_NEON_RTCD, [1], [AC_DEFINE(WEBP_HAVE_NEON_RTCD, [1],
[Set to 1 if runtime detection of NEON is enabled])])]) [Set to 1 if runtime detection of NEON is enabled])])])
;;
case "$host_os" in esac
*android*) AC_CHECK_HEADERS([cpu-features.h]) ;; AC_SUBST([NEON_FLAGS])])
esac
;;
esac
AC_SUBST([NEON_FLAGS])])
dnl === CLEAR_LIBVARS([var_pfx]) dnl === CLEAR_LIBVARS([var_pfx])
dnl === Clears <var_pfx>_{INCLUDES,LIBS}. dnl === Clears <var_pfx>_{INCLUDES,LIBS}.
@ -323,8 +340,6 @@ AS_IF([test "x$enable_gl" != "xno"], [
# override with --with-gl* # override with --with-gl*
glut_cflags="$glut_cflags|-framework GLUT -framework OpenGL" glut_cflags="$glut_cflags|-framework GLUT -framework OpenGL"
glut_ldflags="$glut_ldflags|-framework GLUT -framework OpenGL" glut_ldflags="$glut_ldflags|-framework GLUT -framework OpenGL"
# quiet deprecation warnings for glut
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wno-deprecated-declarations])
;; ;;
esac esac
@ -413,67 +428,6 @@ AS_IF([test "x$enable_gl" != "xno"], [
]) ])
AM_CONDITIONAL([BUILD_VWEBP], [test "$build_vwebp" = "yes"]) AM_CONDITIONAL([BUILD_VWEBP], [test "$build_vwebp" = "yes"])
dnl === check for SDL support ===
AC_ARG_ENABLE([sdl],
AS_HELP_STRING([--disable-sdl],
[Disable detection of SDL support
@<:@default=auto@:>@]))
AS_IF([test "x$enable_sdl" != "xno"], [
CLEAR_LIBVARS([SDL])
AC_PATH_PROGS([LIBSDL_CONFIG], [sdl-config])
if test -n "$LIBSDL_CONFIG"; then
SDL_INCLUDES=`$LIBSDL_CONFIG --cflags`
SDL_LIBS="`$LIBSDL_CONFIG --libs`"
fi
WITHLIB_OPTION([sdl], [SDL])
sdl_header="no"
LIBCHECK_PROLOGUE([SDL])
AC_CHECK_HEADER([SDL/SDL.h], [sdl_header="SDL/SDL.h"],
[AC_CHECK_HEADER([SDL.h], [sdl_header="SDL.h"],
[AC_MSG_WARN(SDL library not available - no sdl.h)])])
if test x"$sdl_header" != "xno"; then
AC_LANG_PUSH(C)
SDL_SAVED_LIBS="$LIBS"
for lib in "" "-lSDL" "-lSDLmain -lSDL"; do
LIBS="$SDL_SAVED_LIBS $lib"
# Perform a full link to ensure SDL_main is resolved if needed.
AC_LINK_IFELSE(
[AC_LANG_SOURCE([
#include <$sdl_header>
int main(int argc, char** argv) {
SDL_Init(0);
return 0;
}])],
[SDL_LIBS="$LDFLAGS $LIBS"
SDL_INCLUDES="$SDL_INCLUDES -DWEBP_HAVE_SDL"
AC_DEFINE(WEBP_HAVE_SDL, [1],
[Set to 1 if SDL library is installed])
sdl_support=yes]
)
if test x"$sdl_support" = "xyes"; then
break
fi
done
# LIBS is restored by LIBCHECK_EPILOGUE
AC_LANG_POP
if test x"$sdl_header" = "xSDL.h"; then
SDL_INCLUDES="$SDL_INCLUDES -DWEBP_HAVE_JUST_SDL_H"
fi
fi
LIBCHECK_EPILOGUE([SDL])
if test x"$sdl_support" = "xyes"; then
build_vwebp_sdl=yes
else
AC_MSG_WARN(Optional SDL library not found)
fi
])
AM_CONDITIONAL([BUILD_VWEBP_SDL], [test "$build_vwebp_sdl" = "yes"])
dnl === check for PNG support === dnl === check for PNG support ===
AC_ARG_ENABLE([png], AS_HELP_STRING([--disable-png], AC_ARG_ENABLE([png], AS_HELP_STRING([--disable-png],
@ -591,7 +545,7 @@ AS_IF([test "x$enable_gif" != "xno"], [
if test "$gif_support" = "yes" -a \ if test "$gif_support" = "yes" -a \
"$enable_libwebpdemux" = "yes"; then "$enable_libwebpdemux" = "yes"; then
build_anim_diff=yes build_animdiff=yes
fi fi
if test "$gif_support" = "yes" -a \ if test "$gif_support" = "yes" -a \
@ -599,19 +553,14 @@ AS_IF([test "x$enable_gif" != "xno"], [
build_gif2webp=yes build_gif2webp=yes
fi fi
]) ])
AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_anim_diff}" = "yes"]) AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_animdiff}" = "yes"])
AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"]) AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"])
if test "$enable_libwebpdemux" = "yes" -a "$enable_libwebpmux" = "yes"; then if test "$enable_libwebpmux" = "yes"; then
build_img2webp=yes build_img2webp=yes
fi fi
AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"]) AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"])
if test "$enable_libwebpmux" = "yes"; then
build_webpinfo=yes
fi
AM_CONDITIONAL([BUILD_WEBPINFO], [test "${build_webpinfo}" = "yes"])
dnl === check for WIC support === dnl === check for WIC support ===
AC_ARG_ENABLE([wic], AC_ARG_ENABLE([wic],
@ -664,7 +613,7 @@ if test "$enable_wic" = "yes"; then
fi fi
esac esac
dnl === If --enable-swap-16bit-csp is defined, add -DWEBP_SWAP_16BIT_CSP=1 dnl === If --enable-swap-16bit-csp is defined, add -DWEBP_SWAP_16BIT_CSP
USE_SWAP_16BIT_CSP="" USE_SWAP_16BIT_CSP=""
AC_MSG_CHECKING(if --enable-swap-16bit-csp option is specified) AC_MSG_CHECKING(if --enable-swap-16bit-csp option is specified)
@ -672,25 +621,23 @@ AC_ARG_ENABLE([swap-16bit-csp],
AS_HELP_STRING([--enable-swap-16bit-csp], AS_HELP_STRING([--enable-swap-16bit-csp],
[Enable byte swap for 16 bit colorspaces])) [Enable byte swap for 16 bit colorspaces]))
if test "$enable_swap_16bit_csp" = "yes"; then if test "$enable_swap_16bit_csp" = "yes"; then
USE_SWAP_16BIT_CSP="-DWEBP_SWAP_16BIT_CSP=1" USE_SWAP_16BIT_CSP="-DWEBP_SWAP_16BIT_CSP"
fi fi
AC_MSG_RESULT(${enable_swap_16bit_csp-no}) AC_MSG_RESULT(${enable_swap_16bit_csp-no})
AC_SUBST(USE_SWAP_16BIT_CSP) AC_SUBST(USE_SWAP_16BIT_CSP)
dnl === If --disable-near-lossless is defined, add -DWEBP_NEAR_LOSSLESS=0 dnl === If --enable-experimental is defined, add -DWEBP_EXPERIMENTAL_FEATURES
AC_DEFINE(WEBP_NEAR_LOSSLESS, [1], [Enable near lossless encoding]) USE_EXPERIMENTAL_CODE=""
AC_MSG_CHECKING(if --disable-near-lossless option is specified) AC_MSG_CHECKING(if --enable-experimental option is specified)
AC_ARG_ENABLE([near_lossless], AC_ARG_ENABLE([experimental], AS_HELP_STRING([--enable-experimental],
AS_HELP_STRING([--disable-near-lossless], [Activate experimental features]))
[Disable near lossless encoding]), if test "$enable_experimental" = "yes"; then
[], [enable_near_lossless=yes]) AC_DEFINE(WEBP_EXPERIMENTAL_FEATURES, [1], [Enable experimental code])
if test "$enable_near_lossless" = "no"; then USE_EXPERIMENTAL_CODE="-DWEBP_EXPERIMENTAL_FEATURES"
AC_DEFINE(WEBP_NEAR_LOSSLESS, [0], [Enable near lossless encoding])
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi fi
AC_MSG_RESULT(${enable_experimental-no})
AC_SUBST(USE_EXPERIMENTAL_CODE)
dnl === Check whether libwebpmux should be built dnl === Check whether libwebpmux should be built
AC_MSG_CHECKING(whether libwebpmux is to be built) AC_MSG_CHECKING(whether libwebpmux is to be built)
@ -698,16 +645,15 @@ AC_ARG_ENABLE([libwebpmux],
AS_HELP_STRING([--enable-libwebpmux], AS_HELP_STRING([--enable-libwebpmux],
[Build libwebpmux @<:@default=no@:>@])) [Build libwebpmux @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpmux-no}) AC_MSG_RESULT(${enable_libwebpmux-no})
AM_CONDITIONAL([BUILD_MUX], [test "$enable_libwebpmux" = "yes"]) AM_CONDITIONAL([WANT_MUX], [test "$enable_libwebpmux" = "yes"])
dnl === Check whether libwebpdemux should be built dnl === Check whether libwebpdemux should be built
AC_MSG_CHECKING(whether libwebpdemux is to be built) AC_MSG_CHECKING(whether libwebpdemux is to be built)
AC_ARG_ENABLE([libwebpdemux], AC_ARG_ENABLE([libwebpdemux],
AS_HELP_STRING([--disable-libwebpdemux], AS_HELP_STRING([--enable-libwebpdemux],
[Disable libwebpdemux @<:@default=no@:>@]), [Build libwebpdemux @<:@default=no@:>@]))
[], [enable_libwebpdemux=yes])
AC_MSG_RESULT(${enable_libwebpdemux-no}) AC_MSG_RESULT(${enable_libwebpdemux-no})
AM_CONDITIONAL([BUILD_DEMUX], [test "$enable_libwebpdemux" = "yes"]) AM_CONDITIONAL([WANT_DEMUX], [test "$enable_libwebpdemux" = "yes"])
dnl === Check whether decoder library should be built. dnl === Check whether decoder library should be built.
AC_MSG_CHECKING(whether decoder library is to be built) AC_MSG_CHECKING(whether decoder library is to be built)
@ -723,7 +669,7 @@ AC_ARG_ENABLE([libwebpextras],
AS_HELP_STRING([--enable-libwebpextras], AS_HELP_STRING([--enable-libwebpextras],
[Build libwebpextras @<:@default=no@:>@])) [Build libwebpextras @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpextras-no}) AC_MSG_RESULT(${enable_libwebpextras-no})
AM_CONDITIONAL([BUILD_EXTRAS], [test "$enable_libwebpextras" = "yes"]) AM_CONDITIONAL([WANT_EXTRAS], [test "$enable_libwebpextras" = "yes"])
dnl ========================= dnl =========================
@ -754,25 +700,22 @@ libwebpmux: ${enable_libwebpmux-no}
libwebpextras: ${enable_libwebpextras-no} libwebpextras: ${enable_libwebpextras-no}
Tools: Tools:
cwebp : ${enable_libwebpdemux-no} cwebp : yes
Input format support Input format support
==================== ====================
JPEG : ${jpeg_support-no} JPEG : ${jpeg_support-no}
PNG : ${png_support-no} PNG : ${png_support-no}
TIFF : ${tiff_support-no} TIFF : ${tiff_support-no}
WIC : ${wic_support-no} WIC : ${wic_support-no}
dwebp : ${enable_libwebpdemux-no} dwebp : yes
Output format support Output format support
===================== =====================
PNG : ${png_support-no} PNG : ${png_support-no}
WIC : ${wic_support-no} WIC : ${wic_support-no}
GIF support : ${gif_support-no} GIF support : ${gif_support-no}
anim_diff : ${build_anim_diff-no} anim_diff : ${build_animdiff-no}
gif2webp : ${build_gif2webp-no} gif2webp : ${build_gif2webp-no}
img2webp : ${build_img2webp-no} img2webp : ${build_img2webp-no}
webpmux : ${enable_libwebpmux-no} webpmux : ${enable_libwebpmux-no}
vwebp : ${build_vwebp-no} vwebp : ${build_vwebp-no}
webpinfo : ${build_webpinfo-no}
SDL support : ${sdl_support-no}
vwebp_sdl : ${build_vwebp_sdl-no}
]) ])

View File

@ -446,9 +446,8 @@ Frame Height Minus One: 24 bits (_uint24_)
Frame Duration: 24 bits (_uint24_) Frame Duration: 24 bits (_uint24_)
: The time to wait before displaying the next frame, in 1 millisecond units. : The time to wait before displaying the next frame, in 1 millisecond units.
Note the interpretation of frame duration of 0 (and often <= 10) is In particular, frame duration of 0 is useful when one wants to update
implementation defined. Many tools and browsers assign a minimum duration multiple areas of the canvas at once during the animation.
similar to GIF.
Reserved: 6 bits Reserved: 6 bits

View File

@ -26,7 +26,8 @@ LOCAL_SRC_FILES := \
cwebp.c \ cwebp.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpdemux webp LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webp
LOCAL_MODULE := cwebp LOCAL_MODULE := cwebp
@ -41,7 +42,9 @@ LOCAL_SRC_FILES := \
dwebp.c \ dwebp.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_STATIC_LIBRARIES := example_util imagedec imageenc webpdemux webp LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
LOCAL_STATIC_LIBRARIES := example_util imagedec imageenc webp
LOCAL_MODULE := dwebp LOCAL_MODULE := dwebp
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -55,6 +58,7 @@ LOCAL_SRC_FILES := \
webpmux.c \ webpmux.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
LOCAL_STATIC_LIBRARIES := example_util imageio_util webpmux webp LOCAL_STATIC_LIBRARIES := example_util imageio_util webpmux webp
LOCAL_MODULE := webpmux_example LOCAL_MODULE := webpmux_example
@ -70,24 +74,9 @@ LOCAL_SRC_FILES := \
img2webp.c \ img2webp.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS) LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpmux webpdemux \ LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
webp LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpmux webp
LOCAL_MODULE := img2webp_example LOCAL_MODULE := img2webp_example
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
################################################################################
# webpinfo
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
webpinfo.c \
LOCAL_CFLAGS := $(WEBP_CFLAGS)
LOCAL_STATIC_LIBRARIES := example_util imageio_util webp
LOCAL_MODULE := webpinfo_example
include $(BUILD_EXECUTABLE)

View File

@ -1,11 +1,8 @@
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
bin_PROGRAMS = bin_PROGRAMS = dwebp cwebp
if BUILD_DEMUX
bin_PROGRAMS += dwebp cwebp
endif
if BUILD_ANIMDIFF if BUILD_ANIMDIFF
noinst_PROGRAMS = anim_diff anim_dump noinst_PROGRAMS = anim_diff
endif endif
if BUILD_GIF2WEBP if BUILD_GIF2WEBP
bin_PROGRAMS += gif2webp bin_PROGRAMS += gif2webp
@ -13,53 +10,34 @@ endif
if BUILD_IMG2WEBP if BUILD_IMG2WEBP
bin_PROGRAMS += img2webp bin_PROGRAMS += img2webp
endif endif
if BUILD_MUX if WANT_MUX
bin_PROGRAMS += webpmux bin_PROGRAMS += webpmux
endif endif
if BUILD_VWEBP if BUILD_VWEBP
bin_PROGRAMS += vwebp bin_PROGRAMS += vwebp
endif endif
if BUILD_WEBPINFO
bin_PROGRAMS += webpinfo
endif
noinst_LTLIBRARIES = libexample_util.la noinst_LTLIBRARIES = libexample_util.la
libexample_util_la_SOURCES = example_util.c example_util.h libexample_util_la_SOURCES = example_util.c example_util.h
libexample_util_la_LIBADD = ../src/libwebp.la libexample_util_la_LIBADD = ../src/libwebp.la
anim_diff_SOURCES = anim_diff.c anim_util.c anim_util.h gifdec.c gifdec.h anim_diff_SOURCES = anim_diff.c anim_util.c anim_util.h
anim_diff_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES) anim_diff_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GIF_INCLUDES)
anim_diff_LDADD = anim_diff_LDADD = ../src/demux/libwebpdemux.la
anim_diff_LDADD += ../src/demux/libwebpdemux.la anim_diff_LDADD += libexample_util.la ../imageio/libimageio_util.la
anim_diff_LDADD += libexample_util.la
anim_diff_LDADD += ../imageio/libimageio_util.la
anim_diff_LDADD += $(GIF_LIBS) -lm anim_diff_LDADD += $(GIF_LIBS) -lm
anim_dump_SOURCES = anim_dump.c anim_util.c anim_util.h gifdec.c gifdec.h
anim_dump_CPPFLAGS = $(AM_CPPFLAGS) $(PNG_INCLUDES)
anim_dump_CPPFLAGS += $(GIF_INCLUDES)
anim_dump_LDADD =
anim_dump_LDADD += ../src/demux/libwebpdemux.la
anim_dump_LDADD += libexample_util.la
anim_dump_LDADD += ../imageio/libimageio_util.la
anim_dump_LDADD += ../imageio/libimageenc.la
anim_dump_LDADD += $(PNG_LIBS) $(GIF_LIBS) $(TIFF_LIBS) -lm
cwebp_SOURCES = cwebp.c stopwatch.h cwebp_SOURCES = cwebp.c stopwatch.h
cwebp_CPPFLAGS = $(AM_CPPFLAGS) cwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
cwebp_LDADD = cwebp_LDADD = libexample_util.la ../imageio/libimageio_util.la
cwebp_LDADD += libexample_util.la cwebp_LDADD += ../imageio/libimagedec.la ../src/libwebp.la
cwebp_LDADD += ../imageio/libimageio_util.la
cwebp_LDADD += ../imageio/libimagedec.la
cwebp_LDADD += ../src/libwebp.la
cwebp_LDADD += $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS) cwebp_LDADD += $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS)
dwebp_SOURCES = dwebp.c stopwatch.h dwebp_SOURCES = dwebp.c stopwatch.h
dwebp_CPPFLAGS = $(AM_CPPFLAGS) dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
dwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES) dwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES)
dwebp_LDADD = dwebp_LDADD = libexample_util.la
dwebp_LDADD += libexample_util.la
dwebp_LDADD += ../imageio/libimagedec.la dwebp_LDADD += ../imageio/libimagedec.la
dwebp_LDADD += ../imageio/libimageenc.la dwebp_LDADD += ../imageio/libimageenc.la
dwebp_LDADD += ../imageio/libimageio_util.la dwebp_LDADD += ../imageio/libimageio_util.la
@ -67,53 +45,31 @@ dwebp_LDADD += ../src/libwebp.la
dwebp_LDADD +=$(PNG_LIBS) $(JPEG_LIBS) dwebp_LDADD +=$(PNG_LIBS) $(JPEG_LIBS)
gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h
gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES) gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GIF_INCLUDES)
gif2webp_LDADD = gif2webp_LDADD = libexample_util.la ../imageio/libimageio_util.la
gif2webp_LDADD += libexample_util.la gif2webp_LDADD += ../src/mux/libwebpmux.la ../src/libwebp.la $(GIF_LIBS)
gif2webp_LDADD += ../imageio/libimageio_util.la
gif2webp_LDADD += ../src/mux/libwebpmux.la
gif2webp_LDADD += ../src/libwebp.la
gif2webp_LDADD += $(GIF_LIBS)
vwebp_SOURCES = vwebp.c vwebp_SOURCES = vwebp.c
vwebp_CPPFLAGS = $(AM_CPPFLAGS) $(GL_INCLUDES) vwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GL_INCLUDES)
vwebp_LDADD = vwebp_LDADD = libexample_util.la ../imageio/libimageio_util.la
vwebp_LDADD += libexample_util.la vwebp_LDADD += ../src/demux/libwebpdemux.la $(GL_LIBS)
vwebp_LDADD += ../imageio/libimageio_util.la
vwebp_LDADD += ../src/demux/libwebpdemux.la
vwebp_LDADD += $(GL_LIBS)
webpmux_SOURCES = webpmux.c webpmux_SOURCES = webpmux.c
webpmux_CPPFLAGS = $(AM_CPPFLAGS) webpmux_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
webpmux_LDADD = webpmux_LDADD = libexample_util.la ../imageio/libimageio_util.la
webpmux_LDADD += libexample_util.la webpmux_LDADD += ../src/mux/libwebpmux.la ../src/libwebp.la
webpmux_LDADD += ../imageio/libimageio_util.la
webpmux_LDADD += ../src/mux/libwebpmux.la
webpmux_LDADD += ../src/libwebp.la
img2webp_SOURCES = img2webp.c img2webp_SOURCES = img2webp.c
img2webp_CPPFLAGS = $(AM_CPPFLAGS) img2webp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
img2webp_LDADD = img2webp_LDADD = libexample_util.la ../imageio/libimageio_util.la
img2webp_LDADD += libexample_util.la
img2webp_LDADD += ../imageio/libimageio_util.la
img2webp_LDADD += ../imageio/libimagedec.la img2webp_LDADD += ../imageio/libimagedec.la
img2webp_LDADD += ../src/mux/libwebpmux.la img2webp_LDADD += ../src/mux/libwebpmux.la ../src/libwebp.la
img2webp_LDADD += ../src/libwebp.la
img2webp_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS) img2webp_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS)
webpinfo_SOURCES = webpinfo.c
webpinfo_CPPFLAGS = $(AM_CPPFLAGS)
webpinfo_LDADD =
webpinfo_LDADD += libexample_util.la
webpinfo_LDADD += ../imageio/libimageio_util.la
webpinfo_LDADD += ../src/libwebp.la
if BUILD_LIBWEBPDECODER if BUILD_LIBWEBPDECODER
anim_diff_LDADD += ../src/libwebpdecoder.la anim_diff_LDADD += ../src/libwebpdecoder.la
anim_dump_LDADD += ../src/libwebpdecoder.la
vwebp_LDADD += ../src/libwebpdecoder.la vwebp_LDADD += ../src/libwebpdecoder.la
else else
anim_diff_LDADD += ../src/libwebp.la anim_diff_LDADD += ../src/libwebp.la
anim_dump_LDADD += ../src/libwebp.la
vwebp_LDADD += ../src/libwebp.la vwebp_LDADD += ../src/libwebp.la
endif endif

View File

@ -20,8 +20,6 @@
#include <string.h> // for 'strcmp'. #include <string.h> // for 'strcmp'.
#include "./anim_util.h" #include "./anim_util.h"
#include "./example_util.h"
#include "./unicode.h"
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf #define snprintf _snprintf
@ -145,18 +143,8 @@ static int CompareAnimatedImagePair(const AnimatedImage* const img1,
if (!ok) return 0; // These are fatal failures, can't proceed. if (!ok) return 0; // These are fatal failures, can't proceed.
if (is_multi_frame_image) { // Checks relevant for multi-frame images only. if (is_multi_frame_image) { // Checks relevant for multi-frame images only.
int max_loop_count_workaround = 0; ok = CompareValues(img1->loop_count, img2->loop_count,
// Transcodes to webp increase the gif loop count by 1 for compatibility. "Loop count mismatch") && ok;
// When the gif has the maximum value the webp value will be off by one.
if ((img1->format == ANIM_GIF && img1->loop_count == 65536 &&
img2->format == ANIM_WEBP && img2->loop_count == 65535) ||
(img1->format == ANIM_WEBP && img1->loop_count == 65535 &&
img2->format == ANIM_GIF && img2->loop_count == 65536)) {
max_loop_count_workaround = 1;
}
ok = (max_loop_count_workaround ||
CompareValues(img1->loop_count, img2->loop_count,
"Loop count mismatch")) && ok;
ok = CompareBackgroundColor(img1->bgcolor, img2->bgcolor, ok = CompareBackgroundColor(img1->bgcolor, img2->bgcolor,
premultiply) && ok; premultiply) && ok;
} }
@ -199,11 +187,11 @@ static void Help(void) {
printf(" -min_psnr <float> ... minimum per-frame PSNR\n"); printf(" -min_psnr <float> ... minimum per-frame PSNR\n");
printf(" -raw_comparison ..... if this flag is not used, RGB is\n"); printf(" -raw_comparison ..... if this flag is not used, RGB is\n");
printf(" premultiplied before comparison\n"); printf(" premultiplied before comparison\n");
printf(" -max_diff <int> ..... maximum allowed difference per channel\n" #ifdef WEBP_EXPERIMENTAL_FEATURES
" between corresponding pixels in subsequent\n" printf(" -max_diff <int> ..... maximum allowed difference per channel "
" between corresponding pixels in subsequent"
" frames\n"); " frames\n");
printf(" -h .................. this help\n"); #endif
printf(" -version ............ print version number and exit\n");
} }
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
@ -219,49 +207,56 @@ int main(int argc, const char* argv[]) {
const char* files[2] = { NULL, NULL }; const char* files[2] = { NULL, NULL };
AnimatedImage images[2]; AnimatedImage images[2];
INIT_WARGV(argc, argv); if (argc < 3) {
Help();
return -1;
}
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-dump_frames")) { if (!strcmp(argv[c], "-dump_frames")) {
if (c < argc - 1) { if (c < argc - 1) {
dump_frames = 1; dump_frames = 1;
dump_folder = (const char*)GET_WARGV(argv, ++c); dump_folder = argv[++c];
} else { } else {
parse_error = 1; parse_error = 1;
} }
} else if (!strcmp(argv[c], "-min_psnr")) { } else if (!strcmp(argv[c], "-min_psnr")) {
if (c < argc - 1) { if (c < argc - 1) {
min_psnr = ExUtilGetFloat(argv[++c], &parse_error); const char* const v = argv[++c];
char* end = NULL;
const double d = strtod(v, &end);
if (end == v) {
parse_error = 1;
fprintf(stderr, "Error! '%s' is not a floating point number.\n", v);
}
min_psnr = d;
} else { } else {
parse_error = 1; parse_error = 1;
} }
} else if (!strcmp(argv[c], "-raw_comparison")) { } else if (!strcmp(argv[c], "-raw_comparison")) {
premultiply = 0; premultiply = 0;
#ifdef WEBP_EXPERIMENTAL_FEATURES
} else if (!strcmp(argv[c], "-max_diff")) { } else if (!strcmp(argv[c], "-max_diff")) {
if (c < argc - 1) { if (c < argc - 1) {
max_diff = ExUtilGetInt(argv[++c], 0, &parse_error); const char* const v = argv[++c];
char* end = NULL;
const int n = (int)strtol(v, &end, 10);
if (end == v) {
parse_error = 1;
fprintf(stderr, "Error! '%s' is not an integer.\n", v);
}
max_diff = n;
} else { } else {
parse_error = 1; parse_error = 1;
} }
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { #endif
Help();
FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version);
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
(dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff);
FREE_WARGV_AND_RETURN(0);
} else { } else {
if (!got_input1) { if (!got_input1) {
files[0] = (const char*)GET_WARGV(argv, c); files[0] = argv[c];
got_input1 = 1; got_input1 = 1;
} else if (!got_input2) { } else if (!got_input2) {
files[1] = (const char*)GET_WARGV(argv, c); files[1] = argv[c];
got_input2 = 1; got_input2 = 1;
} else { } else {
parse_error = 1; parse_error = 1;
@ -269,30 +264,23 @@ int main(int argc, const char* argv[]) {
} }
if (parse_error) { if (parse_error) {
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} }
} }
if (argc < 3) {
Help();
FREE_WARGV_AND_RETURN(-1);
}
if (!got_input2) { if (!got_input2) {
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} }
if (dump_frames) { if (dump_frames) {
WPRINTF("Dumping decoded frames in: %s\n", (const W_CHAR*)dump_folder); printf("Dumping decoded frames in: %s\n", dump_folder);
} }
memset(images, 0, sizeof(images)); memset(images, 0, sizeof(images));
for (i = 0; i < 2; ++i) { for (i = 0; i < 2; ++i) {
WPRINTF("Decoding file: %s\n", (const W_CHAR*)files[i]); printf("Decoding file: %s\n", files[i]);
if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) { if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) {
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", fprintf(stderr, "Error decoding file: %s\n Aborting.\n", files[i]);
(const W_CHAR*)files[i]);
return_code = -2; return_code = -2;
goto End; goto End;
} else { } else {
@ -302,16 +290,14 @@ int main(int argc, const char* argv[]) {
if (!CompareAnimatedImagePair(&images[0], &images[1], if (!CompareAnimatedImagePair(&images[0], &images[1],
premultiply, min_psnr)) { premultiply, min_psnr)) {
WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0], fprintf(stderr, "\nFiles %s and %s differ.\n", files[0], files[1]);
(const W_CHAR*)files[1]);
return_code = -3; return_code = -3;
} else { } else {
WPRINTF("\nFiles %s and %s are identical.\n", (const W_CHAR*)files[0], printf("\nFiles %s and %s are identical.\n", files[0], files[1]);
(const W_CHAR*)files[1]);
return_code = 0; return_code = 0;
} }
End: End:
ClearAnimatedImage(&images[0]); ClearAnimatedImage(&images[0]);
ClearAnimatedImage(&images[1]); ClearAnimatedImage(&images[1]);
FREE_WARGV_AND_RETURN(return_code); return return_code;
} }

View File

@ -1,121 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Decodes an animated WebP file and dumps the decoded frames as PNG or TIFF.
//
// Author: Skal (pascal.massimino@gmail.com)
#include <stdio.h>
#include <string.h> // for 'strcmp'.
#include "./anim_util.h"
#include "webp/decode.h"
#include "../imageio/image_enc.h"
#include "./unicode.h"
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
static void Help(void) {
printf("Usage: anim_dump [options] files...\n");
printf("\nOptions:\n");
printf(" -folder <string> .... dump folder (default: '.')\n");
printf(" -prefix <string> .... prefix for dumped frames "
"(default: 'dump_')\n");
printf(" -tiff ............... save frames as TIFF\n");
printf(" -pam ................ save frames as PAM\n");
printf(" -h .................. this help\n");
printf(" -version ............ print version number and exit\n");
}
int main(int argc, const char* argv[]) {
int error = 0;
const W_CHAR* dump_folder = TO_W_CHAR(".");
const W_CHAR* prefix = TO_W_CHAR("dump_");
const W_CHAR* suffix = TO_W_CHAR("png");
WebPOutputFileFormat format = PNG;
int c;
INIT_WARGV(argc, argv);
if (argc < 2) {
Help();
FREE_WARGV_AND_RETURN(-1);
}
for (c = 1; !error && c < argc; ++c) {
if (!strcmp(argv[c], "-folder")) {
if (c + 1 == argc) {
fprintf(stderr, "missing argument after option '%s'\n", argv[c]);
error = 1;
break;
}
dump_folder = GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-prefix")) {
if (c + 1 == argc) {
fprintf(stderr, "missing argument after option '%s'\n", argv[c]);
error = 1;
break;
}
prefix = GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-tiff")) {
format = TIFF;
suffix = TO_W_CHAR("tiff");
} else if (!strcmp(argv[c], "-pam")) {
format = PAM;
suffix = TO_W_CHAR("pam");
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version);
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
(dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff);
FREE_WARGV_AND_RETURN(0);
} else {
uint32_t i;
AnimatedImage image;
const W_CHAR* const file = GET_WARGV(argv, c);
memset(&image, 0, sizeof(image));
WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n",
file, dump_folder, prefix, suffix);
if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) {
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file);
error = 1;
break;
}
for (i = 0; !error && i < image.num_frames; ++i) {
W_CHAR out_file[1024];
WebPDecBuffer buffer;
WebPInitDecBuffer(&buffer);
buffer.colorspace = MODE_RGBA;
buffer.is_external_memory = 1;
buffer.width = image.canvas_width;
buffer.height = image.canvas_height;
buffer.u.RGBA.rgba = image.frames[i].rgba;
buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t);
buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height;
WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s",
dump_folder, prefix, i, suffix);
if (!WebPSaveImage(&buffer, format, (const char*)out_file)) {
WFPRINTF(stderr, "Error while saving image '%s'\n", out_file);
error = 1;
}
WebPFreeDecBuffer(&buffer);
}
ClearAnimatedImage(&image);
}
}
FREE_WARGV_AND_RETURN(error ? 1 : 0);
}

View File

@ -16,16 +16,13 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#if defined(WEBP_HAVE_GIF) #ifdef WEBP_HAVE_GIF
#include <gif_lib.h> #include <gif_lib.h>
#endif #endif
#include "webp/format_constants.h" #include "webp/format_constants.h"
#include "webp/decode.h" #include "webp/decode.h"
#include "webp/demux.h" #include "webp/demux.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./gifdec.h"
#include "./unicode.h"
#include "./unicode_gif.h"
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf #define snprintf _snprintf
@ -36,13 +33,11 @@ static const int kNumChannels = 4;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Common utilities. // Common utilities.
#if defined(WEBP_HAVE_GIF)
// Returns true if the frame covers the full canvas. // Returns true if the frame covers the full canvas.
static int IsFullFrame(int width, int height, static int IsFullFrame(int width, int height,
int canvas_width, int canvas_height) { int canvas_width, int canvas_height) {
return (width == canvas_width && height == canvas_height); return (width == canvas_width && height == canvas_height);
} }
#endif // WEBP_HAVE_GIF
static int CheckSizeForOverflow(uint64_t size) { static int CheckSizeForOverflow(uint64_t size) {
return (size == (size_t)size); return (size == (size_t)size);
@ -60,15 +55,15 @@ static int AllocateFrames(AnimatedImage* const image, uint32_t num_frames) {
!CheckSizeForOverflow(total_frame_size)) { !CheckSizeForOverflow(total_frame_size)) {
return 0; return 0;
} }
mem = (uint8_t*)WebPMalloc((size_t)total_size); mem = (uint8_t*)malloc((size_t)total_size);
frames = (DecodedFrame*)WebPMalloc((size_t)total_frame_size); frames = (DecodedFrame*)malloc((size_t)total_frame_size);
if (mem == NULL || frames == NULL) { if (mem == NULL || frames == NULL) {
WebPFree(mem); free(mem);
WebPFree(frames); free(frames);
return 0; return 0;
} }
WebPFree(image->raw_mem); free(image->raw_mem);
image->num_frames = num_frames; image->num_frames = num_frames;
image->frames = frames; image->frames = frames;
for (i = 0; i < num_frames; ++i) { for (i = 0; i < num_frames; ++i) {
@ -82,15 +77,14 @@ static int AllocateFrames(AnimatedImage* const image, uint32_t num_frames) {
void ClearAnimatedImage(AnimatedImage* const image) { void ClearAnimatedImage(AnimatedImage* const image) {
if (image != NULL) { if (image != NULL) {
WebPFree(image->raw_mem); free(image->raw_mem);
WebPFree(image->frames); free(image->frames);
image->num_frames = 0; image->num_frames = 0;
image->frames = NULL; image->frames = NULL;
image->raw_mem = NULL; image->raw_mem = NULL;
} }
} }
#if defined(WEBP_HAVE_GIF)
// Clear the canvas to transparent. // Clear the canvas to transparent.
static void ZeroFillCanvas(uint8_t* rgba, static void ZeroFillCanvas(uint8_t* rgba,
uint32_t canvas_width, uint32_t canvas_height) { uint32_t canvas_width, uint32_t canvas_height) {
@ -132,7 +126,6 @@ static void CopyFrameRectangle(const uint8_t* src, uint8_t* dst, int stride,
dst += stride; dst += stride;
} }
} }
#endif // WEBP_HAVE_GIF
// Canonicalize all transparent pixels to transparent black to aid comparison. // Canonicalize all transparent pixels to transparent black to aid comparison.
static void CleanupTransparentPixels(uint32_t* rgba, static void CleanupTransparentPixels(uint32_t* rgba,
@ -154,42 +147,40 @@ static int DumpFrame(const char filename[], const char dump_folder[],
int ok = 0; int ok = 0;
size_t max_len; size_t max_len;
int y; int y;
const W_CHAR* base_name = NULL; const char* base_name = NULL;
W_CHAR* file_name = NULL; char* file_name = NULL;
FILE* f = NULL; FILE* f = NULL;
const char* row; const char* row;
if (dump_folder == NULL) dump_folder = (const char*)TO_W_CHAR("."); base_name = strrchr(filename, '/');
base_name = (base_name == NULL) ? filename : base_name + 1;
base_name = WSTRRCHR(filename, '/'); max_len = strlen(dump_folder) + 1 + strlen(base_name)
base_name = (base_name == NULL) ? (const W_CHAR*)filename : base_name + 1;
max_len = WSTRLEN(dump_folder) + 1 + WSTRLEN(base_name)
+ strlen("_frame_") + strlen(".pam") + 8; + strlen("_frame_") + strlen(".pam") + 8;
file_name = (W_CHAR*)WebPMalloc(max_len * sizeof(*file_name)); file_name = (char*)malloc(max_len * sizeof(*file_name));
if (file_name == NULL) goto End; if (file_name == NULL) goto End;
if (WSNPRINTF(file_name, max_len, "%s/%s_frame_%d.pam", if (snprintf(file_name, max_len, "%s/%s_frame_%d.pam",
(const W_CHAR*)dump_folder, base_name, frame_num) < 0) { dump_folder, base_name, frame_num) < 0) {
fprintf(stderr, "Error while generating file name\n"); fprintf(stderr, "Error while generating file name\n");
goto End; goto End;
} }
f = WFOPEN(file_name, "wb"); f = fopen(file_name, "wb");
if (f == NULL) { if (f == NULL) {
WFPRINTF(stderr, "Error opening file for writing: %s\n", file_name); fprintf(stderr, "Error opening file for writing: %s\n", file_name);
ok = 0; ok = 0;
goto End; goto End;
} }
if (fprintf(f, "P7\nWIDTH %d\nHEIGHT %d\n" if (fprintf(f, "P7\nWIDTH %d\nHEIGHT %d\n"
"DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n", "DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
canvas_width, canvas_height) < 0) { canvas_width, canvas_height) < 0) {
WFPRINTF(stderr, "Write error for file %s\n", file_name); fprintf(stderr, "Write error for file %s\n", file_name);
goto End; goto End;
} }
row = (const char*)rgba; row = (const char*)rgba;
for (y = 0; y < canvas_height; ++y) { for (y = 0; y < canvas_height; ++y) {
if (fwrite(row, canvas_width * kNumChannels, 1, f) != 1) { if (fwrite(row, canvas_width * kNumChannels, 1, f) != 1) {
WFPRINTF(stderr, "Error writing to file: %s\n", file_name); fprintf(stderr, "Error writing to file: %s\n", file_name);
goto End; goto End;
} }
row += canvas_width * kNumChannels; row += canvas_width * kNumChannels;
@ -197,7 +188,7 @@ static int DumpFrame(const char filename[], const char dump_folder[],
ok = 1; ok = 1;
End: End:
if (f != NULL) fclose(f); if (f != NULL) fclose(f);
WebPFree(file_name); free(file_name);
return ok; return ok;
} }
@ -209,7 +200,7 @@ static int IsWebP(const WebPData* const webp_data) {
return (WebPGetInfo(webp_data->bytes, webp_data->size, NULL, NULL) != 0); return (WebPGetInfo(webp_data->bytes, webp_data->size, NULL, NULL) != 0);
} }
// Read animated WebP bitstream 'webp_data' into 'AnimatedImage' struct. // Read animated WebP bitstream 'file_str' into 'AnimatedImage' struct.
static int ReadAnimatedWebP(const char filename[], static int ReadAnimatedWebP(const char filename[],
const WebPData* const webp_data, const WebPData* const webp_data,
AnimatedImage* const image, int dump_frames, AnimatedImage* const image, int dump_frames,
@ -225,7 +216,7 @@ static int ReadAnimatedWebP(const char filename[],
dec = WebPAnimDecoderNew(webp_data, NULL); dec = WebPAnimDecoderNew(webp_data, NULL);
if (dec == NULL) { if (dec == NULL) {
WFPRINTF(stderr, "Error parsing image: %s\n", (const W_CHAR*)filename); fprintf(stderr, "Error parsing image: %s\n", filename);
goto End; goto End;
} }
@ -278,7 +269,6 @@ static int ReadAnimatedWebP(const char filename[],
prev_frame_timestamp = timestamp; prev_frame_timestamp = timestamp;
} }
ok = dump_ok; ok = dump_ok;
if (ok) image->format = ANIM_WEBP;
End: End:
WebPAnimDecoderDelete(dec); WebPAnimDecoderDelete(dec);
@ -288,7 +278,7 @@ static int ReadAnimatedWebP(const char filename[],
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// GIF Decoding. // GIF Decoding.
#if defined(WEBP_HAVE_GIF) #ifdef WEBP_HAVE_GIF
// Returns true if this is a valid GIF bitstream. // Returns true if this is a valid GIF bitstream.
static int IsGIF(const WebPData* const data) { static int IsGIF(const WebPData* const data) {
@ -373,6 +363,26 @@ static int DGifSavedExtensionToGCB(GifFileType* GifFile, int ImageIndex,
#define DGifCloseFile(a, b) DGifCloseFile(a) #define DGifCloseFile(a, b) DGifCloseFile(a)
#endif #endif
static void GIFDisplayError(const GifFileType* const gif, int gif_error) {
// libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
#if LOCAL_GIF_PREREQ(4, 2)
#if LOCAL_GIF_PREREQ(5, 0)
const char* error_str =
GifErrorString((gif == NULL) ? gif_error : gif->Error);
#else
const char* error_str = GifErrorString();
(void)gif;
#endif
if (error_str == NULL) error_str = "Unknown error";
fprintf(stderr, "GIFLib Error %d: %s\n", gif_error, error_str);
#else
(void)gif;
fprintf(stderr, "GIFLib Error %d: ", gif_error);
PrintGifError();
fprintf(stderr, "\n");
#endif
}
static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose, static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose,
const DecodedFrame* const prev_frame, const DecodedFrame* const prev_frame,
int canvas_width, int canvas_height) { int canvas_width, int canvas_height) {
@ -405,7 +415,7 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) {
return 0xffffffff; // Invalid: assume white. return 0xffffffff; // Invalid: assume white.
} else { } else {
const GifColorType color = color_map->Colors[gif->SBackGroundColor]; const GifColorType color = color_map->Colors[gif->SBackGroundColor];
return (0xffu << 24) | return (0xff << 24) |
(color.Red << 16) | (color.Red << 16) |
(color.Green << 8) | (color.Green << 8) |
(color.Blue << 0); (color.Blue << 0);
@ -413,11 +423,6 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) {
} }
// Find appropriate app extension and get loop count from the next extension. // Find appropriate app extension and get loop count from the next extension.
// We use Chrome's interpretation of the 'loop_count' semantics:
// if not present -> loop once
// if present and loop_count == 0, return 0 ('infinite').
// if present and loop_count != 0, it's the number of *extra* loops
// so we need to return loop_count + 1 as total loop number.
static uint32_t GetLoopCountGIF(const GifFileType* const gif) { static uint32_t GetLoopCountGIF(const GifFileType* const gif) {
int i; int i;
for (i = 0; i < gif->ImageCount; ++i) { for (i = 0; i < gif->ImageCount; ++i) {
@ -435,13 +440,12 @@ static uint32_t GetLoopCountGIF(const GifFileType* const gif) {
if (signature_is_ok && if (signature_is_ok &&
eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 && eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 &&
eb2->Bytes[0] == 1) { eb2->Bytes[0] == 1) {
const uint32_t extra_loop = ((uint32_t)(eb2->Bytes[2]) << 8) + return ((uint32_t)(eb2->Bytes[2]) << 8) +
((uint32_t)(eb2->Bytes[1]) << 0); ((uint32_t)(eb2->Bytes[1]) << 0);
return (extra_loop > 0) ? extra_loop + 1 : 0;
} }
} }
} }
return 1; // Default. return 0; // Default.
} }
// Get duration of 'n'th frame in milliseconds. // Get duration of 'n'th frame in milliseconds.
@ -513,15 +517,15 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
int gif_error; int gif_error;
GifFileType* gif; GifFileType* gif;
gif = DGifOpenFileUnicode((const W_CHAR*)filename, NULL); gif = DGifOpenFileName(filename, NULL);
if (gif == NULL) { if (gif == NULL) {
WFPRINTF(stderr, "Could not read file: %s.\n", (const W_CHAR*)filename); fprintf(stderr, "Could not read file: %s.\n", filename);
return 0; return 0;
} }
gif_error = DGifSlurp(gif); gif_error = DGifSlurp(gif);
if (gif_error != GIF_OK) { if (gif_error != GIF_OK) {
WFPRINTF(stderr, "Could not parse image: %s.\n", (const W_CHAR*)filename); fprintf(stderr, "Could not parse image: %s.\n", filename);
GIFDisplayError(gif, gif_error); GIFDisplayError(gif, gif_error);
DGifCloseFile(gif, NULL); DGifCloseFile(gif, NULL);
return 0; return 0;
@ -577,9 +581,6 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
curr_frame = &image->frames[i]; curr_frame = &image->frames[i];
curr_rgba = curr_frame->rgba; curr_rgba = curr_frame->rgba;
curr_frame->duration = GetFrameDurationGIF(gif, i); curr_frame->duration = GetFrameDurationGIF(gif, i);
// Force frames with a small or no duration to 100ms to be consistent
// with web browsers and other transcoding tools (like gif2webp itself).
if (curr_frame->duration <= 10) curr_frame->duration = 100;
if (i == 0) { // Initialize as transparent. if (i == 0) { // Initialize as transparent.
curr_frame->is_key_frame = 1; curr_frame->is_key_frame = 1;
@ -671,7 +672,6 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
} }
} }
} }
image->format = ANIM_GIF;
DGifCloseFile(gif, NULL); DGifCloseFile(gif, NULL);
return 1; return 1;
} }
@ -707,7 +707,7 @@ int ReadAnimatedImage(const char filename[], AnimatedImage* const image,
memset(image, 0, sizeof(*image)); memset(image, 0, sizeof(*image));
if (!ImgIoUtilReadFile(filename, &webp_data.bytes, &webp_data.size)) { if (!ImgIoUtilReadFile(filename, &webp_data.bytes, &webp_data.size)) {
WFPRINTF(stderr, "Error reading file: %s\n", (const W_CHAR*)filename); fprintf(stderr, "Error reading file: %s\n", filename);
return 0; return 0;
} }
@ -717,9 +717,9 @@ int ReadAnimatedImage(const char filename[], AnimatedImage* const image,
} else if (IsGIF(&webp_data)) { } else if (IsGIF(&webp_data)) {
ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder); ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder);
} else { } else {
WFPRINTF(stderr, fprintf(stderr,
"Unknown file type: %s. Supported file types are WebP and GIF\n", "Unknown file type: %s. Supported file types are WebP and GIF\n",
(const W_CHAR*)filename); filename);
ok = 0; ok = 0;
} }
if (!ok) ClearAnimatedImage(image); if (!ok) ClearAnimatedImage(image);
@ -771,9 +771,3 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
*psnr = 4.3429448 * log(255. * 255. / sse); *psnr = 4.3429448 * log(255. * 255. / sse);
} }
} }
void GetAnimatedImageVersions(int* const decoder_version,
int* const demux_version) {
*decoder_version = WebPGetDecoderVersion();
*demux_version = WebPGetDemuxVersion();
}

View File

@ -22,11 +22,6 @@
extern "C" { extern "C" {
#endif #endif
typedef enum {
ANIM_GIF,
ANIM_WEBP
} AnimatedFileFormat;
typedef struct { typedef struct {
uint8_t* rgba; // Decoded and reconstructed full frame. uint8_t* rgba; // Decoded and reconstructed full frame.
int duration; // Frame duration in milliseconds. int duration; // Frame duration in milliseconds.
@ -34,7 +29,6 @@ typedef struct {
} DecodedFrame; } DecodedFrame;
typedef struct { typedef struct {
AnimatedFileFormat format;
uint32_t canvas_width; uint32_t canvas_width;
uint32_t canvas_height; uint32_t canvas_height;
uint32_t bgcolor; uint32_t bgcolor;
@ -62,10 +56,6 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
uint32_t width, uint32_t height, int premultiply, uint32_t width, uint32_t height, int premultiply,
int* const max_diff, double* const psnr); int* const max_diff, double* const psnr);
// Return library versions used by anim_util.
void GetAnimatedImageVersions(int* const decoder_version,
int* const demux_version);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View File

@ -12,7 +12,6 @@
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -24,9 +23,7 @@
#include "../examples/example_util.h" #include "../examples/example_util.h"
#include "../imageio/image_dec.h" #include "../imageio/image_dec.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "../imageio/webpdec.h"
#include "./stopwatch.h" #include "./stopwatch.h"
#include "./unicode.h"
#include "webp/encode.h" #include "webp/encode.h"
#ifndef WEBP_DLL #ifndef WEBP_DLL
@ -91,10 +88,9 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
} }
} }
if (!ok) { if (!ok) {
WFPRINTF(stderr, "Error! Could not process file %s\n", fprintf(stderr, "Error! Could not process file %s\n", filename);
(const W_CHAR*)filename);
} }
WebPFree((void*)data); free((void*)data);
return ok; return ok;
} }
@ -118,10 +114,9 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
} }
End: End:
if (!ok) { if (!ok) {
WFPRINTF(stderr, "Error! Could not process file %s\n", fprintf(stderr, "Error! Could not process file %s\n", filename);
(const W_CHAR*)filename);
} }
WebPFree((void*)data); free((void*)data);
return ok; return ok;
} }
@ -130,8 +125,7 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
static void AllocExtraInfo(WebPPicture* const pic) { static void AllocExtraInfo(WebPPicture* const pic) {
const int mb_w = (pic->width + 15) / 16; const int mb_w = (pic->width + 15) / 16;
const int mb_h = (pic->height + 15) / 16; const int mb_h = (pic->height + 15) / 16;
pic->extra_info = pic->extra_info = (uint8_t*)malloc(mb_w * mb_h * sizeof(*pic->extra_info));
(uint8_t*)WebPMalloc(mb_w * mb_h * sizeof(*pic->extra_info));
} }
static void PrintByteCount(const int bytes[4], int total_size, static void PrintByteCount(const int bytes[4], int total_size,
@ -146,11 +140,10 @@ static void PrintByteCount(const int bytes[4], int total_size,
fprintf(stderr, "| %7d (%.1f%%)\n", total, 100.f * total / total_size); fprintf(stderr, "| %7d (%.1f%%)\n", total, 100.f * total / total_size);
} }
static void PrintPercents(const int counts[4]) { static void PrintPercents(const int counts[4], int total) {
int s; int s;
const int total = counts[0] + counts[1] + counts[2] + counts[3];
for (s = 0; s < 4; ++s) { for (s = 0; s < 4; ++s) {
fprintf(stderr, "| %3d%%", (int)(100. * counts[s] / total + .5)); fprintf(stderr, "| %2d%%", 100 * counts[s] / total);
} }
fprintf(stderr, "| %7d\n", total); fprintf(stderr, "| %7d\n", total);
} }
@ -191,10 +184,9 @@ static void PrintExtraInfoLossless(const WebPPicture* const pic,
if (short_output) { if (short_output) {
fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]); fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]);
} else { } else {
WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name); fprintf(stderr, "File: %s\n", file_name);
fprintf(stderr, "Dimension: %d x %d\n", pic->width, pic->height); fprintf(stderr, "Dimension: %d x %d\n", pic->width, pic->height);
fprintf(stderr, "Output: %d bytes (%.2f bpp)\n", stats->coded_size, fprintf(stderr, "Output: %d bytes\n", stats->coded_size);
8.f * stats->coded_size / pic->width / pic->height);
PrintFullLosslessInfo(stats, "ARGB"); PrintFullLosslessInfo(stats, "ARGB");
} }
} }
@ -210,23 +202,20 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
const int num_i16 = stats->block_count[1]; const int num_i16 = stats->block_count[1];
const int num_skip = stats->block_count[2]; const int num_skip = stats->block_count[2];
const int total = num_i4 + num_i16; const int total = num_i4 + num_i16;
WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name); fprintf(stderr, "File: %s\n", file_name);
fprintf(stderr, "Dimension: %d x %d%s\n", fprintf(stderr, "Dimension: %d x %d%s\n",
pic->width, pic->height, pic->width, pic->height,
stats->alpha_data_size ? " (with alpha)" : ""); stats->alpha_data_size ? " (with alpha)" : "");
fprintf(stderr, "Output: " fprintf(stderr, "Output: "
"%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n" "%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n",
" (%.2f bpp)\n",
stats->coded_size, stats->coded_size,
stats->PSNR[0], stats->PSNR[1], stats->PSNR[2], stats->PSNR[3], stats->PSNR[0], stats->PSNR[1], stats->PSNR[2], stats->PSNR[3]);
8.f * stats->coded_size / pic->width / pic->height);
if (total > 0) { if (total > 0) {
int totals[4] = { 0, 0, 0, 0 }; int totals[4] = { 0, 0, 0, 0 };
fprintf(stderr, "block count: intra4: %6d (%.2f%%)\n" fprintf(stderr, "block count: intra4: %d\n"
" intra16: %6d (%.2f%%)\n" " intra16: %d (-> %.2f%%)\n",
" skipped: %6d (%.2f%%)\n", num_i4, num_i16, 100.f * num_i16 / total);
num_i4, 100.f * num_i4 / total, fprintf(stderr, " skipped block: %d (%.2f%%)\n",
num_i16, 100.f * num_i16 / total,
num_skip, 100.f * num_skip / total); num_skip, 100.f * num_skip / total);
fprintf(stderr, "bytes used: header: %6d (%.1f%%)\n" fprintf(stderr, "bytes used: header: %6d (%.1f%%)\n"
" mode-partition: %6d (%.1f%%)\n", " mode-partition: %6d (%.1f%%)\n",
@ -250,7 +239,7 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
PrintByteCount(stats->residual_bytes[2], stats->coded_size, totals); PrintByteCount(stats->residual_bytes[2], stats->coded_size, totals);
} }
fprintf(stderr, " macroblocks: "); fprintf(stderr, " macroblocks: ");
PrintPercents(stats->segment_size); PrintPercents(stats->segment_size, total);
fprintf(stderr, " quantizer: "); fprintf(stderr, " quantizer: ");
PrintValues(stats->segment_quant); PrintValues(stats->segment_quant);
fprintf(stderr, " filter level: "); fprintf(stderr, " filter level: ");
@ -315,7 +304,7 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
const int alpha_height = const int alpha_height =
WebPPictureHasTransparency(picture) ? picture->height : 0; WebPPictureHasTransparency(picture) ? picture->height : 0;
const int height = picture->height + uv_height + alpha_height; const int height = picture->height + uv_height + alpha_height;
FILE* const f = WFOPEN(PGM_name, "wb"); FILE* const f = fopen(PGM_name, "wb");
if (f == NULL) return 0; if (f == NULL) return 0;
fprintf(f, "P5\n%d %d\n255\n", stride, height); fprintf(f, "P5\n%d %d\n255\n", stride, height);
for (y = 0; y < picture->height; ++y) { for (y = 0; y < picture->height; ++y) {
@ -474,9 +463,8 @@ static int WriteWebPWithMetadata(FILE* const out,
} else { } else {
const int is_lossless = !memcmp(webp, "VP8L", kTagSize); const int is_lossless = !memcmp(webp, "VP8L", kTagSize);
if (is_lossless) { if (is_lossless) {
// Presence of alpha is stored in the 37th bit (29th after the // Presence of alpha is stored in the 29th bit of VP8L data.
// signature) of VP8L data. if (webp[kChunkHeaderSize + 3] & (1 << 5)) flags |= kAlphaFlag;
if (webp[kChunkHeaderSize + 4] & (1 << 4)) flags |= kAlphaFlag;
} }
ok = ok && (fwrite(kVP8XHeader, kChunkHeaderSize, 1, out) == 1); ok = ok && (fwrite(kVP8XHeader, kChunkHeaderSize, 1, out) == 1);
ok = ok && WriteLE32(out, flags); ok = ok && WriteLE32(out, flags);
@ -498,10 +486,10 @@ static int WriteWebPWithMetadata(FILE* const out,
*metadata_written |= METADATA_XMP; *metadata_written |= METADATA_XMP;
} }
return ok; return ok;
} else {
// No metadata, just write the original image file.
return (fwrite(webp, webp_size, 1, out) == 1);
} }
// No metadata, just write the original image file.
return (fwrite(webp, webp_size, 1, out) == 1);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -527,7 +515,6 @@ static void HelpLong(void) {
printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n"); printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n");
printf("If input size (-s) for an image is not specified, it is\n" printf("If input size (-s) for an image is not specified, it is\n"
"assumed to be a PNG, JPEG, TIFF or WebP file.\n"); "assumed to be a PNG, JPEG, TIFF or WebP file.\n");
printf("Note: Animated PNG and WebP files are not supported.\n");
#ifdef HAVE_WINCODEC_H #ifdef HAVE_WINCODEC_H
printf("Windows builds can take as input any of the files handled by WIC.\n"); printf("Windows builds can take as input any of the files handled by WIC.\n");
#endif #endif
@ -568,8 +555,6 @@ static void HelpLong(void) {
printf(" " printf(" "
"the first partition (0=no degradation ... 100=full)\n"); "the first partition (0=no degradation ... 100=full)\n");
printf(" -pass <int> ............ analysis pass number (1..10)\n"); printf(" -pass <int> ............ analysis pass number (1..10)\n");
printf(" -qrange <min> <max> .... specifies the permissible quality range\n"
" (default: 0 100)\n");
printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n"); printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n");
printf(" -resize <w> <h> ........ resize picture (after any cropping)\n"); printf(" -resize <w> <h> ........ resize picture (after any cropping)\n");
printf(" -mt .................... use multi-threading if available\n"); printf(" -mt .................... use multi-threading if available\n");
@ -594,6 +579,9 @@ static void HelpLong(void) {
printf(" -near_lossless <int> ... use near-lossless image\n" printf(" -near_lossless <int> ... use near-lossless image\n"
" preprocessing (0..100=off), " " preprocessing (0..100=off), "
"default=100\n"); "default=100\n");
#ifdef WEBP_EXPERIMENTAL_FEATURES /* not documented yet */
printf(" -delta_palette ......... use delta palettization\n");
#endif // WEBP_EXPERIMENTAL_FEATURES
printf(" -hint <string> ......... specify image characteristics hint,\n"); printf(" -hint <string> ......... specify image characteristics hint,\n");
printf(" one of: photo, picture or graph\n"); printf(" one of: photo, picture or graph\n");
@ -646,10 +634,10 @@ static const char* const kErrorMessages[VP8_ENC_ERROR_LAST] = {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int main(int argc, const char* argv[]) { int main(int argc, const char *argv[]) {
int return_value = -1; int return_value = -1;
const char* in_file = NULL, *out_file = NULL, *dump_file = NULL; const char *in_file = NULL, *out_file = NULL, *dump_file = NULL;
FILE* out = NULL; FILE *out = NULL;
int c; int c;
int short_output = 0; int short_output = 0;
int quiet = 0; int quiet = 0;
@ -669,38 +657,35 @@ int main(int argc, const char* argv[]) {
WebPConfig config; WebPConfig config;
WebPAuxStats stats; WebPAuxStats stats;
WebPMemoryWriter memory_writer; WebPMemoryWriter memory_writer;
int use_memory_writer;
Metadata metadata; Metadata metadata;
Stopwatch stop_watch; Stopwatch stop_watch;
INIT_WARGV(argc, argv);
MetadataInit(&metadata); MetadataInit(&metadata);
WebPMemoryWriterInit(&memory_writer); WebPMemoryWriterInit(&memory_writer);
if (!WebPPictureInit(&picture) || if (!WebPPictureInit(&picture) ||
!WebPPictureInit(&original_picture) || !WebPPictureInit(&original_picture) ||
!WebPConfigInit(&config)) { !WebPConfigInit(&config)) {
fprintf(stderr, "Error! Version mismatch!\n"); fprintf(stderr, "Error! Version mismatch!\n");
FREE_WARGV_AND_RETURN(-1); return -1;
} }
if (argc == 1) { if (argc == 1) {
HelpShort(); HelpShort();
FREE_WARGV_AND_RETURN(0); return 0;
} }
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
HelpShort(); HelpShort();
FREE_WARGV_AND_RETURN(0); return 0;
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) { } else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
HelpLong(); HelpLong();
FREE_WARGV_AND_RETURN(0); return 0;
} else if (!strcmp(argv[c], "-o") && c + 1 < argc) { } else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = (const char*)GET_WARGV(argv, ++c); out_file = argv[++c];
} else if (!strcmp(argv[c], "-d") && c + 1 < argc) { } else if (!strcmp(argv[c], "-d") && c < argc - 1) {
dump_file = (const char*)GET_WARGV(argv, ++c); dump_file = argv[++c];
config.show_compressed = 1; config.show_compressed = 1;
} else if (!strcmp(argv[c], "-print_psnr")) { } else if (!strcmp(argv[c], "-print_psnr")) {
config.show_compressed = 1; config.show_compressed = 1;
@ -713,7 +698,7 @@ int main(int argc, const char* argv[]) {
print_distortion = 2; print_distortion = 2;
} else if (!strcmp(argv[c], "-short")) { } else if (!strcmp(argv[c], "-short")) {
++short_output; ++short_output;
} else if (!strcmp(argv[c], "-s") && c + 2 < argc) { } else if (!strcmp(argv[c], "-s") && c < argc - 2) {
picture.width = ExUtilGetInt(argv[++c], 0, &parse_error); picture.width = ExUtilGetInt(argv[++c], 0, &parse_error);
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error); picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 || if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 ||
@ -723,30 +708,30 @@ int main(int argc, const char* argv[]) {
picture.width, picture.height); picture.width, picture.height);
goto Error; goto Error;
} }
} else if (!strcmp(argv[c], "-m") && c + 1 < argc) { } else if (!strcmp(argv[c], "-m") && c < argc - 1) {
config.method = ExUtilGetInt(argv[++c], 0, &parse_error); config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
use_lossless_preset = 0; // disable -z option use_lossless_preset = 0; // disable -z option
} else if (!strcmp(argv[c], "-q") && c + 1 < argc) { } else if (!strcmp(argv[c], "-q") && c < argc - 1) {
config.quality = ExUtilGetFloat(argv[++c], &parse_error); config.quality = ExUtilGetFloat(argv[++c], &parse_error);
use_lossless_preset = 0; // disable -z option use_lossless_preset = 0; // disable -z option
} else if (!strcmp(argv[c], "-z") && c + 1 < argc) { } else if (!strcmp(argv[c], "-z") && c < argc - 1) {
lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error); lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error);
if (use_lossless_preset != 0) use_lossless_preset = 1; if (use_lossless_preset != 0) use_lossless_preset = 1;
} else if (!strcmp(argv[c], "-alpha_q") && c + 1 < argc) { } else if (!strcmp(argv[c], "-alpha_q") && c < argc - 1) {
config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error); config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-alpha_method") && c + 1 < argc) { } else if (!strcmp(argv[c], "-alpha_method") && c < argc - 1) {
config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error); config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-alpha_cleanup")) { } else if (!strcmp(argv[c], "-alpha_cleanup")) {
// This flag is obsolete, does opposite of -exact. // This flag is obsolete, does opposite of -exact.
config.exact = 0; config.exact = 0;
} else if (!strcmp(argv[c], "-exact")) { } else if (!strcmp(argv[c], "-exact")) {
config.exact = 1; config.exact = 1;
} else if (!strcmp(argv[c], "-blend_alpha") && c + 1 < argc) { } else if (!strcmp(argv[c], "-blend_alpha") && c < argc - 1) {
blend_alpha = 1; blend_alpha = 1;
// background color is given in hex with an optional '0x' prefix // background color is given in hex with an optional '0x' prefix
background_color = ExUtilGetInt(argv[++c], 16, &parse_error); background_color = ExUtilGetInt(argv[++c], 16, &parse_error);
background_color = background_color & 0x00ffffffu; background_color = background_color & 0x00ffffffu;
} else if (!strcmp(argv[c], "-alpha_filter") && c + 1 < argc) { } else if (!strcmp(argv[c], "-alpha_filter") && c < argc - 1) {
++c; ++c;
if (!strcmp(argv[c], "none")) { if (!strcmp(argv[c], "none")) {
config.alpha_filtering = 0; config.alpha_filtering = 0;
@ -762,10 +747,15 @@ int main(int argc, const char* argv[]) {
keep_alpha = 0; keep_alpha = 0;
} else if (!strcmp(argv[c], "-lossless")) { } else if (!strcmp(argv[c], "-lossless")) {
config.lossless = 1; config.lossless = 1;
} else if (!strcmp(argv[c], "-near_lossless") && c + 1 < argc) { } else if (!strcmp(argv[c], "-near_lossless") && c < argc - 1) {
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error); config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
config.lossless = 1; // use near-lossless only with lossless config.lossless = 1; // use near-lossless only with lossless
} else if (!strcmp(argv[c], "-hint") && c + 1 < argc) { #ifdef WEBP_EXPERIMENTAL_FEATURES
} else if (!strcmp(argv[c], "-delta_palette")) {
config.use_delta_palette = 1;
config.lossless = 1; // delta-palette is for lossless only
#endif // WEBP_EXPERIMENTAL_FEATURES
} else if (!strcmp(argv[c], "-hint") && c < argc - 1) {
++c; ++c;
if (!strcmp(argv[c], "photo")) { if (!strcmp(argv[c], "photo")) {
config.image_hint = WEBP_HINT_PHOTO; config.image_hint = WEBP_HINT_PHOTO;
@ -777,13 +767,13 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]); fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]);
goto Error; goto Error;
} }
} else if (!strcmp(argv[c], "-size") && c + 1 < argc) { } else if (!strcmp(argv[c], "-size") && c < argc - 1) {
config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error); config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-psnr") && c + 1 < argc) { } else if (!strcmp(argv[c], "-psnr") && c < argc - 1) {
config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error); config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error);
} else if (!strcmp(argv[c], "-sns") && c + 1 < argc) { } else if (!strcmp(argv[c], "-sns") && c < argc - 1) {
config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error); config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-f") && c + 1 < argc) { } else if (!strcmp(argv[c], "-f") && c < argc - 1) {
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error); config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-af")) { } else if (!strcmp(argv[c], "-af")) {
config.autofilter = 1; config.autofilter = 1;
@ -797,32 +787,27 @@ int main(int argc, const char* argv[]) {
config.filter_type = 1; config.filter_type = 1;
} else if (!strcmp(argv[c], "-nostrong")) { } else if (!strcmp(argv[c], "-nostrong")) {
config.filter_type = 0; config.filter_type = 0;
} else if (!strcmp(argv[c], "-sharpness") && c + 1 < argc) { } else if (!strcmp(argv[c], "-sharpness") && c < argc - 1) {
config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error); config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-sharp_yuv")) { } else if (!strcmp(argv[c], "-sharp_yuv")) {
config.use_sharp_yuv = 1; config.use_sharp_yuv = 1;
} else if (!strcmp(argv[c], "-pass") && c + 1 < argc) { } else if (!strcmp(argv[c], "-pass") && c < argc - 1) {
config.pass = ExUtilGetInt(argv[++c], 0, &parse_error); config.pass = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-qrange") && c + 2 < argc) { } else if (!strcmp(argv[c], "-pre") && c < argc - 1) {
config.qmin = ExUtilGetInt(argv[++c], 0, &parse_error);
config.qmax = ExUtilGetInt(argv[++c], 0, &parse_error);
if (config.qmin < 0) config.qmin = 0;
if (config.qmax > 100) config.qmax = 100;
} else if (!strcmp(argv[c], "-pre") && c + 1 < argc) {
config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error); config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-segments") && c + 1 < argc) { } else if (!strcmp(argv[c], "-segments") && c < argc - 1) {
config.segments = ExUtilGetInt(argv[++c], 0, &parse_error); config.segments = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-partition_limit") && c + 1 < argc) { } else if (!strcmp(argv[c], "-partition_limit") && c < argc - 1) {
config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error); config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-map") && c + 1 < argc) { } else if (!strcmp(argv[c], "-map") && c < argc - 1) {
picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error); picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-crop") && c + 4 < argc) { } else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
crop = 1; crop = 1;
crop_x = ExUtilGetInt(argv[++c], 0, &parse_error); crop_x = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_y = ExUtilGetInt(argv[++c], 0, &parse_error); crop_y = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_w = ExUtilGetInt(argv[++c], 0, &parse_error); crop_w = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_h = ExUtilGetInt(argv[++c], 0, &parse_error); crop_h = ExUtilGetInt(argv[++c], 0, &parse_error);
} else if (!strcmp(argv[c], "-resize") && c + 2 < argc) { } else if (!strcmp(argv[c], "-resize") && c < argc - 2) {
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error); resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error); resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
#ifndef WEBP_DLL #ifndef WEBP_DLL
@ -833,12 +818,12 @@ int main(int argc, const char* argv[]) {
const int version = WebPGetEncoderVersion(); const int version = WebPGetEncoderVersion();
printf("%d.%d.%d\n", printf("%d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
FREE_WARGV_AND_RETURN(0); return 0;
} else if (!strcmp(argv[c], "-progress")) { } else if (!strcmp(argv[c], "-progress")) {
show_progress = 1; show_progress = 1;
} else if (!strcmp(argv[c], "-quiet")) { } else if (!strcmp(argv[c], "-quiet")) {
quiet = 1; quiet = 1;
} else if (!strcmp(argv[c], "-preset") && c + 1 < argc) { } else if (!strcmp(argv[c], "-preset") && c < argc - 1) {
WebPPreset preset; WebPPreset preset;
++c; ++c;
if (!strcmp(argv[c], "default")) { if (!strcmp(argv[c], "default")) {
@ -861,7 +846,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Could initialize configuration with preset.\n"); fprintf(stderr, "Error! Could initialize configuration with preset.\n");
goto Error; goto Error;
} }
} else if (!strcmp(argv[c], "-metadata") && c + 1 < argc) { } else if (!strcmp(argv[c], "-metadata") && c < argc - 1) {
static const struct { static const struct {
const char* option; const char* option;
int flag; int flag;
@ -895,7 +880,8 @@ int main(int argc, const char* argv[]) {
if (i == kNumTokens) { if (i == kNumTokens) {
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n", fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
(int)(token - start), start); (int)(token - start), start);
FREE_WARGV_AND_RETURN(-1); HelpLong();
return -1;
} }
start = token + 1; start = token + 1;
} }
@ -909,19 +895,19 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-v")) { } else if (!strcmp(argv[c], "-v")) {
verbose = 1; verbose = 1;
} else if (!strcmp(argv[c], "--")) { } else if (!strcmp(argv[c], "--")) {
if (c + 1 < argc) in_file = (const char*)GET_WARGV(argv, ++c); if (c < argc - 1) in_file = argv[++c];
break; break;
} else if (argv[c][0] == '-') { } else if (argv[c][0] == '-') {
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
HelpLong(); HelpLong();
FREE_WARGV_AND_RETURN(-1); return -1;
} else { } else {
in_file = (const char*)GET_WARGV(argv, c); in_file = argv[c];
} }
if (parse_error) { if (parse_error) {
HelpLong(); HelpLong();
FREE_WARGV_AND_RETURN(-1); return -1;
} }
} }
if (in_file == NULL) { if (in_file == NULL) {
@ -971,8 +957,7 @@ int main(int argc, const char* argv[]) {
} }
if (!ReadPicture(in_file, &picture, keep_alpha, if (!ReadPicture(in_file, &picture, keep_alpha,
(keep_metadata == 0) ? NULL : &metadata)) { (keep_metadata == 0) ? NULL : &metadata)) {
WFPRINTF(stderr, "Error! Cannot read input picture file '%s'\n", fprintf(stderr, "Error! Cannot read input picture file '%s'\n", in_file);
(const W_CHAR*)in_file);
goto Error; goto Error;
} }
picture.progress_hook = (show_progress && !quiet) ? ProgressReport : NULL; picture.progress_hook = (show_progress && !quiet) ? ProgressReport : NULL;
@ -985,41 +970,28 @@ int main(int argc, const char* argv[]) {
const double read_time = StopwatchReadAndReset(&stop_watch); const double read_time = StopwatchReadAndReset(&stop_watch);
fprintf(stderr, "Time to read input: %.3fs\n", read_time); fprintf(stderr, "Time to read input: %.3fs\n", read_time);
} }
// The bitstream should be kept in memory when metadata must be appended
// before writing it to a file/stream, and/or when the near-losslessly encoded
// bitstream must be decoded for distortion computation (lossy will modify the
// 'picture' but not the lossless pipeline).
// Otherwise directly write the bitstream to a file.
use_memory_writer = (out_file != NULL && keep_metadata) ||
(!quiet && print_distortion >= 0 && config.lossless &&
config.near_lossless < 100);
// Open the output // Open the output
if (out_file != NULL) { if (out_file != NULL) {
const int use_stdout = !WSTRCMP(out_file, "-"); const int use_stdout = !strcmp(out_file, "-");
out = use_stdout ? ImgIoUtilSetBinaryMode(stdout) : WFOPEN(out_file, "wb"); out = use_stdout ? ImgIoUtilSetBinaryMode(stdout) : fopen(out_file, "wb");
if (out == NULL) { if (out == NULL) {
WFPRINTF(stderr, "Error! Cannot open output file '%s'\n", fprintf(stderr, "Error! Cannot open output file '%s'\n", out_file);
(const W_CHAR*)out_file);
goto Error; goto Error;
} else { } else {
if (!short_output && !quiet) { if (!short_output && !quiet) {
WFPRINTF(stderr, "Saving file '%s'\n", (const W_CHAR*)out_file); fprintf(stderr, "Saving file '%s'\n", out_file);
} }
} }
if (use_memory_writer) { if (keep_metadata == 0) {
picture.writer = WebPMemoryWrite;
picture.custom_ptr = (void*)&memory_writer;
} else {
picture.writer = MyWriter; picture.writer = MyWriter;
picture.custom_ptr = (void*)out; picture.custom_ptr = (void*)out;
} else {
picture.writer = WebPMemoryWrite;
picture.custom_ptr = (void*)&memory_writer;
} }
} else { } else {
out = NULL; out = NULL;
if (use_memory_writer) {
picture.writer = WebPMemoryWrite;
picture.custom_ptr = (void*)&memory_writer;
}
if (!quiet && !short_output) { if (!quiet && !short_output) {
fprintf(stderr, "No output file specified (no -o flag). Encoding will\n"); fprintf(stderr, "No output file specified (no -o flag). Encoding will\n");
fprintf(stderr, "be performed, but its results discarded.\n\n"); fprintf(stderr, "be performed, but its results discarded.\n\n");
@ -1042,53 +1014,10 @@ int main(int argc, const char* argv[]) {
} }
} }
if ((resize_w | resize_h) > 0) { if ((resize_w | resize_h) > 0) {
WebPPicture picture_no_alpha;
if (config.exact) {
// If -exact, we can't premultiply RGB by A otherwise RGB is lost if A=0.
// We rescale an opaque copy and assemble scaled A and non-premultiplied
// RGB channels. This is slower but it's a very uncommon use case. Color
// leak at sharp alpha edges is possible.
if (!WebPPictureCopy(&picture, &picture_no_alpha)) {
fprintf(stderr, "Error! Cannot copy temporary picture\n");
goto Error;
}
// We enforced picture.use_argb = 1 above. Now, remove the alpha values.
{
int x, y;
uint32_t* argb_no_alpha = picture_no_alpha.argb;
for (y = 0; y < picture_no_alpha.height; ++y) {
for (x = 0; x < picture_no_alpha.width; ++x) {
argb_no_alpha[x] |= 0xff000000; // Opaque copy.
}
argb_no_alpha += picture_no_alpha.argb_stride;
}
}
if (!WebPPictureRescale(&picture_no_alpha, resize_w, resize_h)) {
fprintf(stderr, "Error! Cannot resize temporary picture\n");
goto Error;
}
}
if (!WebPPictureRescale(&picture, resize_w, resize_h)) { if (!WebPPictureRescale(&picture, resize_w, resize_h)) {
fprintf(stderr, "Error! Cannot resize picture\n"); fprintf(stderr, "Error! Cannot resize picture\n");
goto Error; goto Error;
} }
if (config.exact) { // Put back the alpha information.
int x, y;
uint32_t* argb_no_alpha = picture_no_alpha.argb;
uint32_t* argb = picture.argb;
for (y = 0; y < picture_no_alpha.height; ++y) {
for (x = 0; x < picture_no_alpha.width; ++x) {
argb[x] = (argb[x] & 0xff000000) | (argb_no_alpha[x] & 0x00ffffff);
}
argb_no_alpha += picture_no_alpha.argb_stride;
argb += picture.argb_stride;
}
WebPPictureFree(&picture_no_alpha);
}
} }
if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) { if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) {
const double preproc_time = StopwatchReadAndReset(&stop_watch); const double preproc_time = StopwatchReadAndReset(&stop_watch);
@ -1098,12 +1027,8 @@ int main(int argc, const char* argv[]) {
if (picture.extra_info_type > 0) { if (picture.extra_info_type > 0) {
AllocExtraInfo(&picture); AllocExtraInfo(&picture);
} }
// Save original picture for later comparison. Only for lossy as lossless does if (print_distortion >= 0) { // Save original picture for later comparison
// not modify 'picture' (even near-lossless). WebPPictureCopy(&picture, &original_picture);
if (print_distortion >= 0 && !config.lossless &&
!WebPPictureCopy(&picture, &original_picture)) {
fprintf(stderr, "Error! Cannot copy temporary picture\n");
goto Error;
} }
// Compress. // Compress.
@ -1121,71 +1046,40 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Time to encode picture: %.3fs\n", encode_time); fprintf(stderr, "Time to encode picture: %.3fs\n", encode_time);
} }
// Get the decompressed image for the lossless pipeline. // Write info
if (!quiet && print_distortion >= 0 && config.lossless) {
if (config.near_lossless == 100) {
// Pure lossless: image was not modified, make 'original_picture' a view
// of 'picture' by copying all members except the freeable pointers.
original_picture = picture;
original_picture.memory_ = original_picture.memory_argb_ = NULL;
} else {
// Decode the bitstream stored in 'memory_writer' to get the altered image
// to 'picture'; save the 'original_picture' beforehand.
assert(use_memory_writer);
original_picture = picture;
if (!WebPPictureInit(&picture)) { // Do not free 'picture'.
fprintf(stderr, "Error! Version mismatch!\n");
goto Error;
}
picture.use_argb = 1;
if (!ReadWebP(memory_writer.mem, memory_writer.size, &picture,
/*keep_alpha=*/WebPPictureHasTransparency(&picture),
/*metadata=*/NULL)) {
fprintf(stderr, "Error! Cannot decode encoded WebP bitstream\n");
fprintf(stderr, "Error code: %d (%s)\n", picture.error_code,
kErrorMessages[picture.error_code]);
goto Error;
}
picture.stats = original_picture.stats;
}
original_picture.stats = NULL;
}
// Write the YUV planes to a PGM file. Only available for lossy.
if (dump_file) { if (dump_file) {
if (picture.use_argb) { if (picture.use_argb) {
fprintf(stderr, "Warning: can't dump file (-d option) " fprintf(stderr, "Warning: can't dump file (-d option) in lossless mode.");
"in lossless mode.\n");
} else if (!DumpPicture(&picture, dump_file)) { } else if (!DumpPicture(&picture, dump_file)) {
WFPRINTF(stderr, "Warning, couldn't dump picture %s\n", fprintf(stderr, "Warning, couldn't dump picture %s\n", dump_file);
(const W_CHAR*)dump_file);
} }
} }
if (use_memory_writer && out != NULL && if (keep_metadata != 0) {
!WriteWebPWithMetadata(out, &picture, &memory_writer, &metadata, if (out != NULL) {
keep_metadata, &metadata_written)) { if (!WriteWebPWithMetadata(out, &picture, &memory_writer,
fprintf(stderr, "Error writing WebP file!\n"); &metadata, keep_metadata, &metadata_written)) {
goto Error; fprintf(stderr, "Error writing WebP file with metadata!\n");
} goto Error;
}
} else { // output is disabled, just display the metadata stats.
const struct {
const MetadataPayload* const payload;
int flag;
} *iter, info[] = {
{ &metadata.exif, METADATA_EXIF },
{ &metadata.iccp, METADATA_ICC },
{ &metadata.xmp, METADATA_XMP },
{ NULL, 0 }
};
uint32_t unused1 = 0;
uint64_t unused2 = 0;
if (out == NULL && keep_metadata) { for (iter = info; iter->payload != NULL; ++iter) {
// output is disabled, just display the metadata stats. if (UpdateFlagsAndSize(iter->payload, !!(keep_metadata & iter->flag),
const struct { 0, &unused1, &unused2)) {
const MetadataPayload* const payload; metadata_written |= iter->flag;
int flag; }
} *iter, info[] = {{&metadata.exif, METADATA_EXIF},
{&metadata.iccp, METADATA_ICC},
{&metadata.xmp, METADATA_XMP},
{NULL, 0}};
uint32_t unused1 = 0;
uint64_t unused2 = 0;
for (iter = info; iter->payload != NULL; ++iter) {
if (UpdateFlagsAndSize(iter->payload, !!(keep_metadata & iter->flag),
/*flag=*/0, &unused1, &unused2)) {
metadata_written |= iter->flag;
} }
} }
} }
@ -1225,7 +1119,7 @@ int main(int argc, const char* argv[]) {
Error: Error:
WebPMemoryWriterClear(&memory_writer); WebPMemoryWriterClear(&memory_writer);
WebPFree(picture.extra_info); free(picture.extra_info);
MetadataFree(&metadata); MetadataFree(&metadata);
WebPPictureFree(&picture); WebPPictureFree(&picture);
WebPPictureFree(&original_picture); WebPPictureFree(&original_picture);
@ -1233,7 +1127,7 @@ int main(int argc, const char* argv[]) {
fclose(out); fclose(out);
} }
FREE_WARGV_AND_RETURN(return_value); return return_value;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -24,7 +24,6 @@
#include "../imageio/image_enc.h" #include "../imageio/image_enc.h"
#include "../imageio/webpdec.h" #include "../imageio/webpdec.h"
#include "./stopwatch.h" #include "./stopwatch.h"
#include "./unicode.h"
static int verbose = 0; static int verbose = 0;
static int quiet = 0; static int quiet = 0;
@ -43,7 +42,7 @@ extern void* VP8GetCPUInfo; // opaque forward declaration.
static int SaveOutput(const WebPDecBuffer* const buffer, static int SaveOutput(const WebPDecBuffer* const buffer,
WebPOutputFileFormat format, const char* const out_file) { WebPOutputFileFormat format, const char* const out_file) {
const int use_stdout = (out_file != NULL) && !WSTRCMP(out_file, "-"); const int use_stdout = (out_file != NULL) && !strcmp(out_file, "-");
int ok = 1; int ok = 1;
Stopwatch stop_watch; Stopwatch stop_watch;
@ -57,7 +56,7 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
if (use_stdout) { if (use_stdout) {
fprintf(stderr, "Saved to stdout\n"); fprintf(stderr, "Saved to stdout\n");
} else { } else {
WFPRINTF(stderr, "Saved file %s\n", (const W_CHAR*)out_file); fprintf(stderr, "Saved file %s\n", out_file);
} }
} }
if (verbose) { if (verbose) {
@ -68,7 +67,7 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
if (use_stdout) { if (use_stdout) {
fprintf(stderr, "Error writing to stdout !!\n"); fprintf(stderr, "Error writing to stdout !!\n");
} else { } else {
WFPRINTF(stderr, "Error writing file %s !!\n", (const W_CHAR*)out_file); fprintf(stderr, "Error writing file %s !!\n", out_file);
} }
} }
return ok; return ok;
@ -76,8 +75,7 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
static void Help(void) { static void Help(void) {
printf("Usage: dwebp in_file [options] [-o out_file]\n\n" printf("Usage: dwebp in_file [options] [-o out_file]\n\n"
"Decodes the WebP image file to PNG format [Default].\n" "Decodes the WebP image file to PNG format [Default]\n"
"Note: Animated WebP files are not supported.\n\n"
"Use following options to convert into alternate image formats:\n" "Use following options to convert into alternate image formats:\n"
" -pam ......... save the raw RGBA samples as a color PAM\n" " -pam ......... save the raw RGBA samples as a color PAM\n"
" -ppm ......... save the raw RGB samples as a color PPM\n" " -ppm ......... save the raw RGB samples as a color PPM\n"
@ -133,7 +131,7 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
format == RGB_565) ? 2 format == RGB_565) ? 2
: 4; : 4;
uint32_t stride = bpp * w + 7; // <- just for exercising uint32_t stride = bpp * w + 7; // <- just for exercising
external_buffer = (uint8_t*)WebPMalloc(stride * h); external_buffer = (uint8_t*)malloc(stride * h);
if (external_buffer == NULL) return NULL; if (external_buffer == NULL) return NULL;
output_buffer->u.RGBA.stride = stride; output_buffer->u.RGBA.stride = stride;
output_buffer->u.RGBA.size = stride * h; output_buffer->u.RGBA.size = stride * h;
@ -146,7 +144,7 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
uint32_t total_size = stride * h * (has_alpha ? 2 : 1) uint32_t total_size = stride * h * (has_alpha ? 2 : 1)
+ 2 * uv_stride * (h + 1) / 2; + 2 * uv_stride * (h + 1) / 2;
assert(format >= YUV && format <= YUVA); assert(format >= YUV && format <= YUVA);
external_buffer = (uint8_t*)WebPMalloc(total_size); external_buffer = (uint8_t*)malloc(total_size);
if (external_buffer == NULL) return NULL; if (external_buffer == NULL) return NULL;
tmp = external_buffer; tmp = external_buffer;
output_buffer->u.YUVA.y = tmp; output_buffer->u.YUVA.y = tmp;
@ -177,10 +175,10 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
return external_buffer; return external_buffer;
} }
int main(int argc, const char* argv[]) { int main(int argc, const char *argv[]) {
int ok = 0; int ok = 0;
const char* in_file = NULL; const char *in_file = NULL;
const char* out_file = NULL; const char *out_file = NULL;
WebPDecoderConfig config; WebPDecoderConfig config;
WebPDecBuffer* const output_buffer = &config.output; WebPDecBuffer* const output_buffer = &config.output;
@ -193,20 +191,18 @@ int main(int argc, const char* argv[]) {
int incremental = 0; int incremental = 0;
int c; int c;
INIT_WARGV(argc, argv);
if (!WebPInitDecoderConfig(&config)) { if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n"); fprintf(stderr, "Library version mismatch!\n");
FREE_WARGV_AND_RETURN(-1); return -1;
} }
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
FREE_WARGV_AND_RETURN(0); return 0;
} else if (!strcmp(argv[c], "-o") && c < argc - 1) { } else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = (const char*)GET_WARGV(argv, ++c); out_file = argv[++c];
} else if (!strcmp(argv[c], "-alpha")) { } else if (!strcmp(argv[c], "-alpha")) {
format = ALPHA_PLANE_ONLY; format = ALPHA_PLANE_ONLY;
} else if (!strcmp(argv[c], "-nofancy")) { } else if (!strcmp(argv[c], "-nofancy")) {
@ -227,7 +223,7 @@ int main(int argc, const char* argv[]) {
const int version = WebPGetDecoderVersion(); const int version = WebPGetDecoderVersion();
printf("%d.%d.%d\n", printf("%d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
FREE_WARGV_AND_RETURN(0); return 0;
} else if (!strcmp(argv[c], "-pgm")) { } else if (!strcmp(argv[c], "-pgm")) {
format = PGM; format = PGM;
} else if (!strcmp(argv[c], "-yuv")) { } else if (!strcmp(argv[c], "-yuv")) {
@ -288,26 +284,26 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-incremental")) { } else if (!strcmp(argv[c], "-incremental")) {
incremental = 1; incremental = 1;
} else if (!strcmp(argv[c], "--")) { } else if (!strcmp(argv[c], "--")) {
if (c < argc - 1) in_file = (const char*)GET_WARGV(argv, ++c); if (c < argc - 1) in_file = argv[++c];
break; break;
} else if (argv[c][0] == '-') { } else if (argv[c][0] == '-') {
fprintf(stderr, "Unknown option '%s'\n", argv[c]); fprintf(stderr, "Unknown option '%s'\n", argv[c]);
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} else { } else {
in_file = (const char*)GET_WARGV(argv, c); in_file = argv[c];
} }
if (parse_error) { if (parse_error) {
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} }
} }
if (in_file == NULL) { if (in_file == NULL) {
fprintf(stderr, "missing input file!!\n"); fprintf(stderr, "missing input file!!\n");
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} }
if (quiet) verbose = 0; if (quiet) verbose = 0;
@ -316,7 +312,7 @@ int main(int argc, const char* argv[]) {
VP8StatusCode status = VP8_STATUS_OK; VP8StatusCode status = VP8_STATUS_OK;
size_t data_size = 0; size_t data_size = 0;
if (!LoadWebP(in_file, &data, &data_size, bitstream)) { if (!LoadWebP(in_file, &data, &data_size, bitstream)) {
FREE_WARGV_AND_RETURN(-1); return -1;
} }
switch (format) { switch (format) {
@ -336,8 +332,9 @@ int main(int argc, const char* argv[]) {
case BMP: case BMP:
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR; output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
break; break;
case TIFF: case TIFF: // note: force pre-multiplied alpha
output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB; output_buffer->colorspace =
bitstream->has_alpha ? MODE_rgbA : MODE_RGB;
break; break;
case PGM: case PGM:
case RAW_YUV: case RAW_YUV:
@ -393,18 +390,18 @@ int main(int argc, const char* argv[]) {
if (out_file != NULL) { if (out_file != NULL) {
if (!quiet) { if (!quiet) {
WFPRINTF(stderr, "Decoded %s.", (const W_CHAR*)in_file); fprintf(stderr, "Decoded %s. Dimensions: %d x %d %s. Format: %s. "
fprintf(stderr, " Dimensions: %d x %d %s. Format: %s. Now saving...\n", "Now saving...\n",
output_buffer->width, output_buffer->height, in_file, output_buffer->width, output_buffer->height,
bitstream->has_alpha ? " (with alpha)" : "", bitstream->has_alpha ? " (with alpha)" : "",
kFormatType[bitstream->format]); kFormatType[bitstream->format]);
} }
ok = SaveOutput(output_buffer, format, out_file); ok = SaveOutput(output_buffer, format, out_file);
} else { } else {
if (!quiet) { if (!quiet) {
WFPRINTF(stderr, "File %s can be decoded ", (const W_CHAR*)in_file); fprintf(stderr, "File %s can be decoded "
fprintf(stderr, "(dimensions: %d x %d %s. Format: %s).\n", "(dimensions: %d x %d %s. Format: %s).\n",
output_buffer->width, output_buffer->height, in_file, output_buffer->width, output_buffer->height,
bitstream->has_alpha ? " (with alpha)" : "", bitstream->has_alpha ? " (with alpha)" : "",
kFormatType[bitstream->format]); kFormatType[bitstream->format]);
fprintf(stderr, "Nothing written; " fprintf(stderr, "Nothing written; "
@ -413,9 +410,9 @@ int main(int argc, const char* argv[]) {
} }
Exit: Exit:
WebPFreeDecBuffer(output_buffer); WebPFreeDecBuffer(output_buffer);
WebPFree((void*)external_buffer); free((void*)external_buffer);
WebPFree((void*)data); free((void*)data);
FREE_WARGV_AND_RETURN(ok ? 0 : -1); return ok ? 0 : -1;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -12,14 +12,10 @@
#include "./example_util.h" #include "./example_util.h"
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "webp/mux_types.h"
#include "../imageio/imageio_util.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// String parsing // String parsing
@ -60,76 +56,3 @@ float ExUtilGetFloat(const char* const v, int* const error) {
} }
return f; return f;
} }
//------------------------------------------------------------------------------
static void ResetCommandLineArguments(int argc, const char* argv[],
CommandLineArguments* const args) {
assert(args != NULL);
args->argc_ = argc;
args->argv_ = argv;
args->own_argv_ = 0;
WebPDataInit(&args->argv_data_);
}
void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args) {
if (args != NULL) {
if (args->own_argv_) {
WebPFree((void*)args->argv_);
WebPDataClear(&args->argv_data_);
}
ResetCommandLineArguments(0, NULL, args);
}
}
#define MAX_ARGC 16384
int ExUtilInitCommandLineArguments(int argc, const char* argv[],
CommandLineArguments* const args) {
if (args == NULL || argv == NULL) return 0;
ResetCommandLineArguments(argc, argv, args);
if (argc == 1 && argv[0][0] != '-') {
char* cur;
const char sep[] = " \t\r\n\f\v";
#if defined(_WIN32) && defined(_UNICODE)
fprintf(stderr,
"Error: Reading arguments from a file is a feature unavailable "
"with Unicode binaries.\n");
return 0;
#endif
if (!ExUtilReadFileToWebPData(argv[0], &args->argv_data_)) {
return 0;
}
args->own_argv_ = 1;
args->argv_ = (const char**)WebPMalloc(MAX_ARGC * sizeof(*args->argv_));
if (args->argv_ == NULL) return 0;
argc = 0;
for (cur = strtok((char*)args->argv_data_.bytes, sep);
cur != NULL;
cur = strtok(NULL, sep)) {
if (argc == MAX_ARGC) {
fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC);
return 0;
}
assert(strlen(cur) != 0);
args->argv_[argc++] = cur;
}
args->argc_ = argc;
}
return 1;
}
//------------------------------------------------------------------------------
int ExUtilReadFileToWebPData(const char* const filename,
WebPData* const webp_data) {
const uint8_t* data;
size_t size;
if (webp_data == NULL) return 0;
if (!ImgIoUtilReadFile(filename, &data, &size)) return 0;
webp_data->bytes = data;
webp_data->size = size;
return 1;
}

View File

@ -14,7 +14,6 @@
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_ #define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
#include "webp/types.h" #include "webp/types.h"
#include "webp/mux_types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -36,33 +35,6 @@ float ExUtilGetFloat(const char* const v, int* const error);
// actually parsed is returned, or -1 if an error occurred. // actually parsed is returned, or -1 if an error occurred.
int ExUtilGetInts(const char* v, int base, int max_output, int output[]); int ExUtilGetInts(const char* v, int base, int max_output, int output[]);
// Reads a file named 'filename' into a WebPData structure. The content of
// webp_data is overwritten. Returns false in case of error.
int ExUtilReadFileToWebPData(const char* const filename,
WebPData* const webp_data);
//------------------------------------------------------------------------------
// Command-line arguments
typedef struct {
int argc_;
const char** argv_;
WebPData argv_data_;
int own_argv_;
} CommandLineArguments;
// Initializes the structure from the command-line parameters. If there is
// only one parameter and it does not start with a '-', then it is assumed to
// be a file name. This file will be read and tokenized into command-line
// arguments. The content of 'args' is overwritten.
// Returns false in case of error (memory allocation failure, non
// existing file, too many arguments, ...).
int ExUtilInitCommandLineArguments(int argc, const char* argv[],
CommandLineArguments* const args);
// Deallocate all memory and reset 'args'.
void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View File

@ -23,22 +23,12 @@
#ifdef WEBP_HAVE_GIF #ifdef WEBP_HAVE_GIF
#if defined(HAVE_UNISTD_H) && HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <gif_lib.h> #include <gif_lib.h>
#include "webp/encode.h" #include "webp/encode.h"
#include "webp/mux.h" #include "webp/mux.h"
#include "../examples/example_util.h" #include "../examples/example_util.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./gifdec.h" #include "./gifdec.h"
#include "./unicode.h"
#include "./unicode_gif.h"
#if !defined(STDIN_FILENO)
#define STDIN_FILENO 0
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -82,10 +72,8 @@ static void Help(void) {
printf(" -metadata <string> ..... comma separated list of metadata to\n"); printf(" -metadata <string> ..... comma separated list of metadata to\n");
printf(" "); printf(" ");
printf("copy from the input to the output if present\n"); printf("copy from the input to the output if present\n");
printf(" "); printf(" "
printf("Valid values: all, none, icc, xmp (default)\n"); "Valid values: all, none, icc, xmp (default)\n");
printf(" -loop_compatibility .... use compatibility mode for Chrome\n");
printf(" version prior to M62 (inclusive)\n");
printf(" -mt .................... use multi-threading if available\n"); printf(" -mt .................... use multi-threading if available\n");
printf("\n"); printf("\n");
printf(" -version ............... print version number and exit\n"); printf(" -version ............... print version number and exit\n");
@ -96,12 +84,13 @@ static void Help(void) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int main(int argc, const char* argv[]) { int main(int argc, const char *argv[]) {
int verbose = 0; int verbose = 0;
int gif_error = GIF_ERROR; int gif_error = GIF_ERROR;
WebPMuxError err = WEBP_MUX_OK; WebPMuxError err = WEBP_MUX_OK;
int ok = 0; int ok = 0;
const W_CHAR* in_file = NULL, *out_file = NULL; const char *in_file = NULL, *out_file = NULL;
FILE* out = NULL;
GifFileType* gif = NULL; GifFileType* gif = NULL;
int frame_duration = 0; int frame_duration = 0;
int frame_timestamp = 0; int frame_timestamp = 0;
@ -115,7 +104,7 @@ int main(int argc, const char* argv[]) {
WebPAnimEncoderOptions enc_options; WebPAnimEncoderOptions enc_options;
WebPConfig config; WebPConfig config;
int frame_number = 0; // Whether we are processing the first frame. int is_first_frame = 1; // Whether we are processing the first frame.
int done; int done;
int c; int c;
int quiet = 0; int quiet = 0;
@ -126,21 +115,18 @@ int main(int argc, const char* argv[]) {
int stored_icc = 0; // Whether we have already stored an ICC profile. int stored_icc = 0; // Whether we have already stored an ICC profile.
WebPData xmp_data; WebPData xmp_data;
int stored_xmp = 0; // Whether we have already stored an XMP profile. int stored_xmp = 0; // Whether we have already stored an XMP profile.
int loop_count = 0; // default: infinite int loop_count = 0;
int stored_loop_count = 0; // Whether we have found an explicit loop count. int stored_loop_count = 0; // Whether we have found an explicit loop count.
int loop_compatibility = 0;
WebPMux* mux = NULL; WebPMux* mux = NULL;
int default_kmin = 1; // Whether to use default kmin value. int default_kmin = 1; // Whether to use default kmin value.
int default_kmax = 1; int default_kmax = 1;
INIT_WARGV(argc, argv);
if (!WebPConfigInit(&config) || !WebPAnimEncoderOptionsInit(&enc_options) || if (!WebPConfigInit(&config) || !WebPAnimEncoderOptionsInit(&enc_options) ||
!WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) || !WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) ||
!WebPPictureInit(&prev_canvas)) { !WebPPictureInit(&prev_canvas)) {
fprintf(stderr, "Error! Version mismatch!\n"); fprintf(stderr, "Error! Version mismatch!\n");
FREE_WARGV_AND_RETURN(-1); return -1;
} }
config.lossless = 1; // Use lossless compression by default. config.lossless = 1; // Use lossless compression by default.
@ -150,23 +136,21 @@ int main(int argc, const char* argv[]) {
if (argc == 1) { if (argc == 1) {
Help(); Help();
FREE_WARGV_AND_RETURN(0); return 0;
} }
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
FREE_WARGV_AND_RETURN(0); return 0;
} else if (!strcmp(argv[c], "-o") && c < argc - 1) { } else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = GET_WARGV(argv, ++c); out_file = argv[++c];
} else if (!strcmp(argv[c], "-lossy")) { } else if (!strcmp(argv[c], "-lossy")) {
config.lossless = 0; config.lossless = 0;
} else if (!strcmp(argv[c], "-mixed")) { } else if (!strcmp(argv[c], "-mixed")) {
enc_options.allow_mixed = 1; enc_options.allow_mixed = 1;
config.lossless = 0; config.lossless = 0;
} else if (!strcmp(argv[c], "-loop_compatibility")) {
loop_compatibility = 1;
} else if (!strcmp(argv[c], "-q") && c < argc - 1) { } else if (!strcmp(argv[c], "-q") && c < argc - 1) {
config.quality = ExUtilGetFloat(argv[++c], &parse_error); config.quality = ExUtilGetFloat(argv[++c], &parse_error);
} else if (!strcmp(argv[c], "-m") && c < argc - 1) { } else if (!strcmp(argv[c], "-m") && c < argc - 1) {
@ -216,7 +200,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n", fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
(int)(token - start), start); (int)(token - start), start);
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} }
start = token + 1; start = token + 1;
} }
@ -229,7 +213,7 @@ int main(int argc, const char* argv[]) {
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff, (enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
enc_version & 0xff, (mux_version >> 16) & 0xff, enc_version & 0xff, (mux_version >> 16) & 0xff,
(mux_version >> 8) & 0xff, mux_version & 0xff); (mux_version >> 8) & 0xff, mux_version & 0xff);
FREE_WARGV_AND_RETURN(0); return 0;
} else if (!strcmp(argv[c], "-quiet")) { } else if (!strcmp(argv[c], "-quiet")) {
quiet = 1; quiet = 1;
enc_options.verbose = 0; enc_options.verbose = 0;
@ -237,19 +221,19 @@ int main(int argc, const char* argv[]) {
verbose = 1; verbose = 1;
enc_options.verbose = 1; enc_options.verbose = 1;
} else if (!strcmp(argv[c], "--")) { } else if (!strcmp(argv[c], "--")) {
if (c < argc - 1) in_file = GET_WARGV(argv, ++c); if (c < argc - 1) in_file = argv[++c];
break; break;
} else if (argv[c][0] == '-') { } else if (argv[c][0] == '-') {
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]); fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} else { } else {
in_file = GET_WARGV(argv, c); in_file = argv[c];
} }
if (parse_error) { if (parse_error) {
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} }
} }
@ -273,7 +257,11 @@ int main(int argc, const char* argv[]) {
} }
// Start the decoder object // Start the decoder object
gif = DGifOpenFileUnicode(in_file, &gif_error); #if LOCAL_GIF_PREREQ(5,0)
gif = DGifOpenFileName(in_file, &gif_error);
#else
gif = DGifOpenFileName(in_file);
#endif
if (gif == NULL) goto End; if (gif == NULL) goto End;
// Loop over GIF images // Loop over GIF images
@ -289,7 +277,7 @@ int main(int argc, const char* argv[]) {
if (!DGifGetImageDesc(gif)) goto End; if (!DGifGetImageDesc(gif)) goto End;
if (frame_number == 0) { if (is_first_frame) {
if (verbose) { if (verbose) {
printf("Canvas screen: %d x %d\n", gif->SWidth, gif->SHeight); printf("Canvas screen: %d x %d\n", gif->SWidth, gif->SHeight);
} }
@ -331,6 +319,7 @@ int main(int argc, const char* argv[]) {
"a memory error.\n"); "a memory error.\n");
goto End; goto End;
} }
is_first_frame = 0;
} }
// Some even more broken GIF can have sub-rect with zero width/height. // Some even more broken GIF can have sub-rect with zero width/height.
@ -347,25 +336,13 @@ int main(int argc, const char* argv[]) {
GIFBlendFrames(&frame, &gif_rect, &curr_canvas); GIFBlendFrames(&frame, &gif_rect, &curr_canvas);
if (!WebPAnimEncoderAdd(enc, &curr_canvas, frame_timestamp, &config)) { if (!WebPAnimEncoderAdd(enc, &curr_canvas, frame_timestamp, &config)) {
fprintf(stderr, "Error while adding frame #%d: %s\n", frame_number, fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc));
WebPAnimEncoderGetError(enc));
goto End;
} else {
++frame_number;
} }
// Update canvases. // Update canvases.
GIFDisposeFrame(orig_dispose, &gif_rect, &prev_canvas, &curr_canvas); GIFDisposeFrame(orig_dispose, &gif_rect, &prev_canvas, &curr_canvas);
GIFCopyPixels(&curr_canvas, &prev_canvas); GIFCopyPixels(&curr_canvas, &prev_canvas);
// Force frames with a small or no duration to 100ms to be consistent
// with web browsers and other transcoding tools. This also avoids
// incorrect durations between frames when padding frames are
// discarded.
if (frame_duration <= 10) {
frame_duration = 100;
}
// Update timestamp (for next frame). // Update timestamp (for next frame).
frame_timestamp += frame_duration; frame_timestamp += frame_duration;
@ -379,7 +356,7 @@ int main(int argc, const char* argv[]) {
} }
case EXTENSION_RECORD_TYPE: { case EXTENSION_RECORD_TYPE: {
int extension; int extension;
GifByteType* data = NULL; GifByteType *data = NULL;
if (DGifGetExtension(gif, &extension, &data) == GIF_ERROR) { if (DGifGetExtension(gif, &extension, &data) == GIF_ERROR) {
goto End; goto End;
} }
@ -409,7 +386,7 @@ int main(int argc, const char* argv[]) {
if (verbose) { if (verbose) {
fprintf(stderr, "Loop count: %d\n", loop_count); fprintf(stderr, "Loop count: %d\n", loop_count);
} }
stored_loop_count = loop_compatibility ? (loop_count != 0) : 1; stored_loop_count = (loop_count != 0);
} else { // An extension containing metadata. } else { // An extension containing metadata.
// We only store the first encountered chunk of each type, and // We only store the first encountered chunk of each type, and
// only if requested by the user. // only if requested by the user.
@ -466,23 +443,6 @@ int main(int argc, const char* argv[]) {
goto End; goto End;
} }
if (!loop_compatibility) {
if (!stored_loop_count) {
// if no loop-count element is seen, the default is '1' (loop-once)
// and we need to signal it explicitly in WebP. Note however that
// in case there's a single frame, we still don't need to store it.
if (frame_number > 1) {
stored_loop_count = 1;
loop_count = 1;
}
} else if (loop_count > 0 && loop_count < 65535) {
// adapt GIF's semantic to WebP's (except in the infinite-loop case)
loop_count += 1;
}
}
// loop_count of 0 is the default (infinite), so no need to signal it
if (loop_count == 0) stored_loop_count = 0;
if (stored_loop_count || stored_icc || stored_xmp) { if (stored_loop_count || stored_icc || stored_xmp) {
// Re-mux to add loop count and/or metadata as needed. // Re-mux to add loop count and/or metadata as needed.
mux = WebPMuxCreate(&webp_data, 1); mux = WebPMuxCreate(&webp_data, 1);
@ -542,19 +502,13 @@ int main(int argc, const char* argv[]) {
} }
if (out_file != NULL) { if (out_file != NULL) {
if (!ImgIoUtilWriteFile((const char*)out_file, webp_data.bytes, if (!ImgIoUtilWriteFile(out_file, webp_data.bytes, webp_data.size)) {
webp_data.size)) { fprintf(stderr, "Error writing output file: %s\n", out_file);
WFPRINTF(stderr, "Error writing output file: %s\n", out_file);
goto End; goto End;
} }
if (!quiet) { if (!quiet) {
if (!WSTRCMP(out_file, "-")) { fprintf(stderr, "Saved output file (%d bytes): %s\n",
fprintf(stderr, "Saved %d bytes to STDIO\n", (int)webp_data.size, out_file);
(int)webp_data.size);
} else {
WFPRINTF(stderr, "Saved output file (%d bytes): %s\n",
(int)webp_data.size, out_file);
}
} }
} else { } else {
if (!quiet) { if (!quiet) {
@ -576,6 +530,7 @@ int main(int argc, const char* argv[]) {
WebPPictureFree(&curr_canvas); WebPPictureFree(&curr_canvas);
WebPPictureFree(&prev_canvas); WebPPictureFree(&prev_canvas);
WebPAnimEncoderDelete(enc); WebPAnimEncoderDelete(enc);
if (out != NULL && out_file != NULL) fclose(out);
if (gif_error != GIF_OK) { if (gif_error != GIF_OK) {
GIFDisplayError(gif, gif_error); GIFDisplayError(gif, gif_error);
@ -588,12 +543,12 @@ int main(int argc, const char* argv[]) {
#endif #endif
} }
FREE_WARGV_AND_RETURN(!ok); return !ok;
} }
#else // !WEBP_HAVE_GIF #else // !WEBP_HAVE_GIF
int main(int argc, const char* argv[]) { int main(int argc, const char *argv[]) {
fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]); fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]);
(void)argc; (void)argc;
return 0; return 0;

View File

@ -28,17 +28,11 @@
#define GIF_DISPOSE_SHIFT 2 #define GIF_DISPOSE_SHIFT 2
// from utils/utils.h // from utils/utils.h
#ifdef __cplusplus
extern "C" {
#endif
extern void WebPCopyPlane(const uint8_t* src, int src_stride, extern void WebPCopyPlane(const uint8_t* src, int src_stride,
uint8_t* dst, int dst_stride, uint8_t* dst, int dst_stride,
int width, int height); int width, int height);
extern void WebPCopyPixels(const WebPPicture* const src, extern void WebPCopyPixels(const WebPPicture* const src,
WebPPicture* const dst); WebPPicture* const dst);
#ifdef __cplusplus
}
#endif
void GIFGetBackgroundColor(const ColorMapObject* const color_map, void GIFGetBackgroundColor(const ColorMapObject* const color_map,
int bgcolor_index, int transparent_index, int bgcolor_index, int transparent_index,
@ -137,7 +131,7 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
} }
dst = sub_image.argb; dst = sub_image.argb;
tmp = (uint8_t*)WebPMalloc(rect.width * sizeof(*tmp)); tmp = (uint8_t*)malloc(rect.width * sizeof(*tmp));
if (tmp == NULL) goto End; if (tmp == NULL) goto End;
if (image_desc->Interlace) { // Interlaced image. if (image_desc->Interlace) { // Interlaced image.
@ -168,7 +162,7 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
End: End:
if (!ok) picture->error_code = sub_image.error_code; if (!ok) picture->error_code = sub_image.error_code;
WebPPictureFree(&sub_image); WebPPictureFree(&sub_image);
WebPFree(tmp); free(tmp);
return ok; return ok;
} }

View File

@ -27,7 +27,6 @@
#include "../imageio/image_dec.h" #include "../imageio/image_dec.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./stopwatch.h" #include "./stopwatch.h"
#include "./unicode.h"
#include "webp/encode.h" #include "webp/encode.h"
#include "webp/mux.h" #include "webp/mux.h"
@ -49,7 +48,6 @@ static void Help(void) {
printf(" -mixed ............... use mixed lossy/lossless automatic mode\n"); printf(" -mixed ............... use mixed lossy/lossless automatic mode\n");
printf(" -v ................... verbose mode\n"); printf(" -v ................... verbose mode\n");
printf(" -h ................... this help\n"); printf(" -h ................... this help\n");
printf(" -version ............. print version number and exit\n");
printf("\n"); printf("\n");
printf("Per-frame options (only used for subsequent images input):\n"); printf("Per-frame options (only used for subsequent images input):\n");
@ -62,10 +60,6 @@ static void Help(void) {
printf("\n"); printf("\n");
printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n" printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
" -d 80 in2.tiff -o out.webp\n"); " -d 80 in2.tiff -o out.webp\n");
printf("\nNote: if a single file name is passed as the argument, the "
"arguments will be\n");
printf("tokenized from this file. The file name must not start with "
"the character '-'.\n");
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -84,7 +78,7 @@ static int ReadImage(const char filename[], WebPPicture* const pic) {
if (!ImgIoUtilReadFile(filename, &data, &data_size)) return 0; if (!ImgIoUtilReadFile(filename, &data, &data_size)) return 0;
reader = WebPGuessImageReader(data, data_size); reader = WebPGuessImageReader(data, data_size);
ok = reader(data, data_size, pic, 1, NULL); ok = reader(data, data_size, pic, 1, NULL);
WebPFree((void*)data); free((void*)data);
return ok; return ok;
} }
@ -123,13 +117,14 @@ static int SetLoopCount(int loop_count, WebPData* const webp_data) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int main(int argc, const char* argv[]) { int main(int argc, char* argv[]) {
const char* output = NULL; const char* output = NULL;
WebPAnimEncoder* enc = NULL; WebPAnimEncoder* enc = NULL;
int verbose = 0; int verbose = 0;
int pic_num = 0; int pic_num = 0;
int duration = 100; int duration = 100;
int timestamp_ms = 0; int timestamp_ms = 0;
int ok = 1;
int loop_count = 0; int loop_count = 0;
int width = 0, height = 0; int width = 0, height = 0;
WebPAnimEncoderOptions anim_config; WebPAnimEncoderOptions anim_config;
@ -138,33 +133,22 @@ int main(int argc, const char* argv[]) {
WebPData webp_data; WebPData webp_data;
int c; int c;
int have_input = 0; int have_input = 0;
CommandLineArguments cmd_args;
int ok;
INIT_WARGV(argc, argv);
ok = ExUtilInitCommandLineArguments(argc - 1, argv + 1, &cmd_args);
if (!ok) FREE_WARGV_AND_RETURN(1);
argc = cmd_args.argc_;
argv = cmd_args.argv_;
WebPDataInit(&webp_data); WebPDataInit(&webp_data);
if (!WebPAnimEncoderOptionsInit(&anim_config) || if (!WebPAnimEncoderOptionsInit(&anim_config) ||
!WebPConfigInit(&config) || !WebPConfigInit(&config) ||
!WebPPictureInit(&pic)) { !WebPPictureInit(&pic)) {
fprintf(stderr, "Library version mismatch!\n"); fprintf(stderr, "Library version mismatch!\n");
ok = 0; return 1;
goto End;
} }
// 1st pass of option parsing // 1st pass of option parsing
for (c = 0; ok && c < argc; ++c) { for (c = 1; ok && c < argc; ++c) {
if (argv[c][0] == '-') { if (argv[c][0] == '-') {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-o") && c + 1 < argc) { if (!strcmp(argv[c], "-o") && c + 1 < argc) {
argv[c] = NULL; argv[c] = NULL;
output = (const char*)GET_WARGV_SHIFTED(argv, ++c); output = argv[++c];
} else if (!strcmp(argv[c], "-kmin") && c + 1 < argc) { } else if (!strcmp(argv[c], "-kmin") && c + 1 < argc) {
argv[c] = NULL; argv[c] = NULL;
anim_config.kmin = ExUtilGetInt(argv[++c], 0, &parse_error); anim_config.kmin = ExUtilGetInt(argv[++c], 0, &parse_error);
@ -187,15 +171,7 @@ int main(int argc, const char* argv[]) {
verbose = 1; verbose = 1;
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
goto End; return 0;
} else if (!strcmp(argv[c], "-version")) {
const int enc_version = WebPGetEncoderVersion();
const int mux_version = WebPGetMuxVersion();
printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n",
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
enc_version & 0xff, (mux_version >> 16) & 0xff,
(mux_version >> 8) & 0xff, mux_version & 0xff);
goto End;
} else { } else {
continue; continue;
} }
@ -208,13 +184,13 @@ int main(int argc, const char* argv[]) {
} }
if (!have_input) { if (!have_input) {
fprintf(stderr, "No input file(s) for generating animation!\n"); fprintf(stderr, "No input file(s) for generating animation!\n");
goto End; return 0;
} }
// image-reading pass // image-reading pass
pic_num = 0; pic_num = 0;
config.lossless = 1; config.lossless = 1;
for (c = 0; ok && c < argc; ++c) { for (c = 1; ok && c < argc; ++c) {
if (argv[c] == NULL) continue; if (argv[c] == NULL) continue;
if (argv[c][0] == '-') { // parse local options if (argv[c][0] == '-') { // parse local options
int parse_error = 0; int parse_error = 0;
@ -251,7 +227,7 @@ int main(int argc, const char* argv[]) {
// read next input image // read next input image
pic.use_argb = 1; pic.use_argb = 1;
ok = ReadImage((const char*)GET_WARGV_SHIFTED(argv, c), &pic); ok = ReadImage(argv[c], &pic);
if (!ok) goto End; if (!ok) goto End;
if (enc == NULL) { if (enc == NULL) {
@ -283,8 +259,8 @@ int main(int argc, const char* argv[]) {
if (!ok) goto End; if (!ok) goto End;
if (verbose) { if (verbose) {
WFPRINTF(stderr, "Added frame #%3d at time %4d (file: %s)\n", fprintf(stderr, "Added frame #%3d at time %4d (file: %s)\n",
pic_num, timestamp_ms, GET_WARGV_SHIFTED(argv, c)); pic_num, timestamp_ms, argv[c]);
} }
timestamp_ms += duration; timestamp_ms += duration;
++pic_num; ++pic_num;
@ -308,7 +284,7 @@ int main(int argc, const char* argv[]) {
if (ok) { if (ok) {
if (output != NULL) { if (output != NULL) {
ok = ImgIoUtilWriteFile(output, webp_data.bytes, webp_data.size); ok = ImgIoUtilWriteFile(output, webp_data.bytes, webp_data.size);
if (ok) WFPRINTF(stderr, "output file: %s ", (const W_CHAR*)output); if (ok) fprintf(stderr, "output file: %s ", output);
} else { } else {
fprintf(stderr, "[no output file specified] "); fprintf(stderr, "[no output file specified] ");
} }
@ -318,7 +294,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "[%d frames, %u bytes].\n", fprintf(stderr, "[%d frames, %u bytes].\n",
pic_num, (unsigned int)webp_data.size); pic_num, (unsigned int)webp_data.size);
} }
WebPDataClear(&webp_data); WebPDataClear(&webp_data);
ExUtilDeleteCommandLineArguments(&cmd_args); return ok ? 0 : 1;
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
} }

View File

@ -60,4 +60,4 @@ static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
#endif /* _WIN32 */ #endif /* _WIN32 */
#endif // WEBP_EXAMPLES_STOPWATCH_H_ #endif /* WEBP_EXAMPLES_STOPWATCH_H_ */

View File

@ -1,102 +0,0 @@
// Copyright 2018 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Unicode support for Windows. The main idea is to maintain an array of Unicode
// arguments (wargv) and use it only for file paths. The regular argv is used
// for everything else.
//
// Author: Yannis Guyon (yguyon@google.com)
#ifndef WEBP_EXAMPLES_UNICODE_H_
#define WEBP_EXAMPLES_UNICODE_H_
#if defined(_WIN32) && defined(_UNICODE)
// wchar_t is used instead of TCHAR because we only perform additional work when
// Unicode is enabled and because the output of CommandLineToArgvW() is wchar_t.
#include <wchar.h>
#include <windows.h>
#include <shellapi.h>
// Create a wchar_t array containing Unicode parameters.
#define INIT_WARGV(ARGC, ARGV) \
int wargc; \
const W_CHAR** const wargv = \
(const W_CHAR**)CommandLineToArgvW(GetCommandLineW(), &wargc); \
do { \
if (wargv == NULL || wargc != (ARGC)) { \
fprintf(stderr, "Error: Unable to get Unicode arguments.\n"); \
FREE_WARGV_AND_RETURN(-1); \
} \
} while (0)
// Use this to get a Unicode argument (e.g. file path).
#define GET_WARGV(UNUSED, C) wargv[C]
// For cases where argv is shifted by one compared to wargv.
#define GET_WARGV_SHIFTED(UNUSED, C) wargv[(C) + 1]
#define GET_WARGV_OR_NULL() wargv
// Release resources. LocalFree() is needed after CommandLineToArgvW().
#define FREE_WARGV() LOCAL_FREE((W_CHAR** const)wargv)
#define LOCAL_FREE(WARGV) \
do { \
if ((WARGV) != NULL) LocalFree(WARGV); \
} while (0)
#define W_CHAR wchar_t // WCHAR without underscore might already be defined.
#define TO_W_CHAR(STR) (L##STR)
#define WFOPEN(ARG, OPT) _wfopen((const W_CHAR*)ARG, TO_W_CHAR(OPT))
#define WPRINTF(STR, ...) wprintf(TO_W_CHAR(STR), __VA_ARGS__)
#define WFPRINTF(STDERR, STR, ...) fwprintf(STDERR, TO_W_CHAR(STR), __VA_ARGS__)
#define WSTRLEN(FILENAME) wcslen((const W_CHAR*)FILENAME)
#define WSTRCMP(FILENAME, STR) wcscmp((const W_CHAR*)FILENAME, TO_W_CHAR(STR))
#define WSTRRCHR(FILENAME, STR) wcsrchr((const W_CHAR*)FILENAME, TO_W_CHAR(STR))
#define WSNPRINTF(A, B, STR, ...) _snwprintf(A, B, TO_W_CHAR(STR), __VA_ARGS__)
#else
// Unicode file paths work as is on Unix platforms, and no extra work is done on
// Windows either if Unicode is disabled.
#define INIT_WARGV(ARGC, ARGV)
#define GET_WARGV(ARGV, C) (ARGV)[C]
#define GET_WARGV_SHIFTED(ARGV, C) (ARGV)[C]
#define GET_WARGV_OR_NULL() NULL
#define FREE_WARGV()
#define LOCAL_FREE(WARGV)
#define W_CHAR char
#define TO_W_CHAR(STR) (STR)
#define WFOPEN(ARG, OPT) fopen(ARG, OPT)
#define WPRINTF(STR, ...) printf(STR, __VA_ARGS__)
#define WFPRINTF(STDERR, STR, ...) fprintf(STDERR, STR, __VA_ARGS__)
#define WSTRLEN(FILENAME) strlen(FILENAME)
#define WSTRCMP(FILENAME, STR) strcmp(FILENAME, STR)
#define WSTRRCHR(FILENAME, STR) strrchr(FILENAME, STR)
#define WSNPRINTF(A, B, STR, ...) snprintf(A, B, STR, __VA_ARGS__)
#endif // defined(_WIN32) && defined(_UNICODE)
// Don't forget to free wargv before returning (e.g. from main).
#define FREE_WARGV_AND_RETURN(VALUE) \
do { \
FREE_WARGV(); \
return (VALUE); \
} while (0)
#endif // WEBP_EXAMPLES_UNICODE_H_

View File

@ -1,75 +0,0 @@
// Copyright 2018 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// giflib doesn't have a Unicode DGifOpenFileName(). Let's make one.
//
// Author: Yannis Guyon (yguyon@google.com)
#ifndef WEBP_EXAMPLES_UNICODE_GIF_H_
#define WEBP_EXAMPLES_UNICODE_GIF_H_
#include "./unicode.h"
#ifdef HAVE_CONFIG_H
#include "webp/config.h" // For WEBP_HAVE_GIF
#endif
#if defined(WEBP_HAVE_GIF)
#ifdef _WIN32
#include <fcntl.h> // Not standard, needed for _topen and flags.
#include <io.h>
#endif
#include <gif_lib.h>
#include <string.h>
#include "./gifdec.h"
#if !defined(STDIN_FILENO)
#define STDIN_FILENO 0
#endif
static GifFileType* DGifOpenFileUnicode(const W_CHAR* file_name, int* error) {
if (!WSTRCMP(file_name, "-")) {
#if LOCAL_GIF_PREREQ(5, 0)
return DGifOpenFileHandle(STDIN_FILENO, error);
#else
(void)error;
return DGifOpenFileHandle(STDIN_FILENO);
#endif
}
#if defined(_WIN32) && defined(_UNICODE)
int file_handle = _wopen(file_name, _O_RDONLY | _O_BINARY);
if (file_handle == -1) {
if (error != NULL) *error = D_GIF_ERR_OPEN_FAILED;
return NULL;
}
#if LOCAL_GIF_PREREQ(5, 0)
return DGifOpenFileHandle(file_handle, error);
#else
return DGifOpenFileHandle(file_handle);
#endif
#else
#if LOCAL_GIF_PREREQ(5, 0)
return DGifOpenFileName(file_name, error);
#else
return DGifOpenFileName(file_name);
#endif
#endif // defined(_WIN32) && defined(_UNICODE)
// DGifCloseFile() is called later.
}
#endif // defined(WEBP_HAVE_GIF)
#endif // WEBP_EXAMPLES_UNICODE_GIF_H_

View File

@ -42,7 +42,6 @@
#include "../examples/example_util.h" #include "../examples/example_util.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./unicode.h"
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf #define snprintf _snprintf
@ -57,7 +56,6 @@ static struct {
int print_info; int print_info;
int only_deltas; int only_deltas;
int use_color_profile; int use_color_profile;
int draw_anim_background_color;
int canvas_width, canvas_height; int canvas_width, canvas_height;
int loop_count; int loop_count;
@ -207,11 +205,6 @@ static void decode_callback(int what) {
} }
} }
duration = curr->duration; duration = curr->duration;
// Behavior copied from Chrome, cf:
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/
// platform/graphics/DeferredImageDecoder.cpp?
// rcl=b4c33049f096cd283f32be9a58b9a9e768227c26&l=246
if (duration <= 10) duration = 100;
} }
if (!Decode()) { if (!Decode()) {
kParams.decoding_error = 1; kParams.decoding_error = 1;
@ -227,9 +220,6 @@ static void decode_callback(int what) {
// Callbacks // Callbacks
static void HandleKey(unsigned char key, int pos_x, int pos_y) { static void HandleKey(unsigned char key, int pos_x, int pos_y) {
// Note: rescaling the window or toggling some features during an animation
// generates visual artifacts. This is not fixed because refreshing the frame
// may require rendering the whole animation from start till current frame.
(void)pos_x; (void)pos_x;
(void)pos_y; (void)pos_y;
if (key == 'q' || key == 'Q' || key == 27 /* Esc */) { if (key == 'q' || key == 'Q' || key == 27 /* Esc */) {
@ -257,12 +247,10 @@ static void HandleKey(unsigned char key, int pos_x, int pos_y) {
glutPostRedisplay(); glutPostRedisplay();
} }
} }
} else if (key == 'b') {
kParams.draw_anim_background_color = 1 - kParams.draw_anim_background_color;
if (!kParams.has_animation) ClearPreviousFrame();
glutPostRedisplay();
} else if (key == 'i') { } else if (key == 'i') {
kParams.print_info = 1 - kParams.print_info; kParams.print_info = 1 - kParams.print_info;
// TODO(skal): handle refresh of animation's last-frame too. It's quite
// more involved though (need to save the previous frame).
if (!kParams.has_animation) ClearPreviousFrame(); if (!kParams.has_animation) ClearPreviousFrame();
glutPostRedisplay(); glutPostRedisplay();
} else if (key == 'd') { } else if (key == 'd') {
@ -272,8 +260,8 @@ static void HandleKey(unsigned char key, int pos_x, int pos_y) {
} }
static void HandleReshape(int width, int height) { static void HandleReshape(int width, int height) {
// Note: reshape doesn't preserve aspect ratio, and might // TODO(skal): should we preserve aspect ratio?
// be handling larger-than-screen pictures incorrectly. // Also: handle larger-than-screen pictures correctly.
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
@ -293,7 +281,7 @@ static void PrintString(const char* const text) {
} }
static float GetColorf(uint32_t color, int shift) { static float GetColorf(uint32_t color, int shift) {
return ((color >> shift) & 0xff) / 255.f; return (color >> shift) / 255.f;
} }
static void DrawCheckerBoard(void) { static void DrawCheckerBoard(void) {
@ -316,43 +304,6 @@ static void DrawCheckerBoard(void) {
glPopMatrix(); glPopMatrix();
} }
static void DrawBackground(void) {
// Whole window cleared with clear color, checkerboard rendered on top of it.
glClear(GL_COLOR_BUFFER_BIT);
DrawCheckerBoard();
// ANIM background color rendered (blend) on top. Default is white for still
// images (without ANIM chunk). glClear() can't be used for that (no blend).
if (kParams.draw_anim_background_color) {
glPushMatrix();
glLoadIdentity();
glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec
GetColorf(kParams.bg_color, 8),
GetColorf(kParams.bg_color, 0),
GetColorf(kParams.bg_color, 24));
glRecti(-1, -1, +1, +1);
glPopMatrix();
}
}
// Draw background in a scissored rectangle.
static void DrawBackgroundScissored(int window_x, int window_y, int frame_w,
int frame_h) {
// Only update the requested area, not the whole canvas.
window_x = window_x * kParams.viewport_width / kParams.canvas_width;
window_y = window_y * kParams.viewport_height / kParams.canvas_height;
frame_w = frame_w * kParams.viewport_width / kParams.canvas_width;
frame_h = frame_h * kParams.viewport_height / kParams.canvas_height;
// glScissor() takes window coordinates (0,0 at bottom left).
window_y = kParams.viewport_height - window_y - frame_h;
glEnable(GL_SCISSOR_TEST);
glScissor(window_x, window_y, frame_w, frame_h);
DrawBackground();
glDisable(GL_SCISSOR_TEST);
}
static void HandleDisplay(void) { static void HandleDisplay(void) {
const WebPDecBuffer* const pic = kParams.pic; const WebPDecBuffer* const pic = kParams.pic;
const WebPIterator* const curr = &kParams.curr_frame; const WebPIterator* const curr = &kParams.curr_frame;
@ -369,21 +320,38 @@ static void HandleDisplay(void) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4); glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4);
if (kParams.only_deltas) { if (kParams.only_deltas) {
DrawBackground(); DrawCheckerBoard();
} else { } else if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ||
// The rectangle of the previous frame might be different than the current curr->blend_method == WEBP_MUX_NO_BLEND) {
// frame, so we may need to DrawBackgroundScissored for both. // glScissor() takes window coordinates (0,0 at bottom left).
int window_x, window_y;
int frame_w, frame_h;
if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
// Clear the previous frame rectangle. // Clear the previous frame rectangle.
DrawBackgroundScissored(prev->x_offset, prev->y_offset, prev->width, window_x = prev->x_offset;
prev->height); window_y = kParams.canvas_height - prev->y_offset - prev->height;
} frame_w = prev->width;
if (curr->blend_method == WEBP_MUX_NO_BLEND) { frame_h = prev->height;
} else { // curr->blend_method == WEBP_MUX_NO_BLEND.
// We simulate no-blending behavior by first clearing the current frame // We simulate no-blending behavior by first clearing the current frame
// rectangle and then alpha-blending against it. // rectangle (to a checker-board) and then alpha-blending against it.
DrawBackgroundScissored(curr->x_offset, curr->y_offset, curr->width, window_x = curr->x_offset;
curr->height); window_y = kParams.canvas_height - curr->y_offset - curr->height;
frame_w = curr->width;
frame_h = curr->height;
} }
glEnable(GL_SCISSOR_TEST);
// Only update the requested area, not the whole canvas.
window_x = window_x * kParams.viewport_width / kParams.canvas_width;
window_y = window_y * kParams.viewport_height / kParams.canvas_height;
frame_w = frame_w * kParams.viewport_width / kParams.canvas_width;
frame_h = frame_h * kParams.viewport_height / kParams.canvas_height;
glScissor(window_x, window_y, frame_w, frame_h);
glClear(GL_COLOR_BUFFER_BIT); // use clear color
DrawCheckerBoard();
glDisable(GL_SCISSOR_TEST);
} }
*prev = *curr; *prev = *curr;
@ -410,36 +378,13 @@ static void HandleDisplay(void) {
} }
} }
glPopMatrix(); glPopMatrix();
#if defined(__APPLE__) || defined(_WIN32)
glFlush(); glFlush();
#else
glutSwapBuffers();
#endif
} }
static void StartDisplay(void) { static void StartDisplay(void) {
int width = kParams.canvas_width; const int width = kParams.canvas_width;
int height = kParams.canvas_height; const int height = kParams.canvas_height;
int screen_width, screen_height;
// TODO(webp:365) GLUT_DOUBLE results in flickering / old frames to be
// partially displayed with animated webp + alpha.
#if defined(__APPLE__) || defined(_WIN32)
glutInitDisplayMode(GLUT_RGBA); glutInitDisplayMode(GLUT_RGBA);
#else
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
#endif
screen_width = glutGet(GLUT_SCREEN_WIDTH);
screen_height = glutGet(GLUT_SCREEN_HEIGHT);
if (width > screen_width || height > screen_height) {
if (width > screen_width) {
height = (height * screen_width + width - 1) / width;
width = screen_width;
}
if (height > screen_height) {
width = (width * screen_height + height - 1) / height;
height = screen_height;
}
}
glutInitWindowSize(width, height); glutInitWindowSize(width, height);
glutCreateWindow("WebP viewer"); glutCreateWindow("WebP viewer");
glutDisplayFunc(HandleDisplay); glutDisplayFunc(HandleDisplay);
@ -448,59 +393,57 @@ static void StartDisplay(void) {
glutKeyboardFunc(HandleKey); glutKeyboardFunc(HandleKey);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glClearColor(0, 0, 0, 0); // window will be cleared to black (no blend) glClearColor(GetColorf(kParams.bg_color, 0),
DrawBackground(); GetColorf(kParams.bg_color, 8),
GetColorf(kParams.bg_color, 16),
GetColorf(kParams.bg_color, 24));
glClear(GL_COLOR_BUFFER_BIT);
DrawCheckerBoard();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Main // Main
static void Help(void) { static void Help(void) {
printf( printf("Usage: vwebp in_file [options]\n\n"
"Usage: vwebp in_file [options]\n\n" "Decodes the WebP image file and visualize it using OpenGL\n"
"Decodes the WebP image file and visualize it using OpenGL\n" "Options are:\n"
"Options are:\n" " -version ..... print version number and exit\n"
" -version ..... print version number and exit\n" " -noicc ....... don't use the icc profile if present\n"
" -noicc ....... don't use the icc profile if present\n" " -nofancy ..... don't use the fancy YUV420 upscaler\n"
" -nofancy ..... don't use the fancy YUV420 upscaler\n" " -nofilter .... disable in-loop filtering\n"
" -nofilter .... disable in-loop filtering\n" " -dither <int> dithering strength (0..100), default=50\n"
" -dither <int> dithering strength (0..100), default=50\n" " -noalphadither disable alpha plane dithering\n"
" -noalphadither disable alpha plane dithering\n" " -mt .......... use multi-threading\n"
" -usebgcolor .. display background color\n" " -info ........ print info\n"
" -mt .......... use multi-threading\n" " -h ........... this help message\n"
" -info ........ print info\n" "\n"
" -h ........... this help message\n" "Keyboard shortcuts:\n"
"\n" " 'c' ................ toggle use of color profile\n"
"Keyboard shortcuts:\n" " 'i' ................ overlay file information\n"
" 'c' ................ toggle use of color profile\n" " 'd' ................ disable blending & disposal (debug)\n"
" 'b' ................ toggle background color display\n" " 'q' / 'Q' / ESC .... quit\n"
" 'i' ................ overlay file information\n" );
" 'd' ................ disable blending & disposal (debug)\n"
" 'q' / 'Q' / ESC .... quit\n");
} }
int main(int argc, char* argv[]) { int main(int argc, char *argv[]) {
int c; int c;
WebPDecoderConfig* const config = &kParams.config; WebPDecoderConfig* const config = &kParams.config;
WebPIterator* const curr = &kParams.curr_frame; WebPIterator* const curr = &kParams.curr_frame;
INIT_WARGV(argc, argv);
if (!WebPInitDecoderConfig(config)) { if (!WebPInitDecoderConfig(config)) {
fprintf(stderr, "Library version mismatch!\n"); fprintf(stderr, "Library version mismatch!\n");
FREE_WARGV_AND_RETURN(-1); return -1;
} }
config->options.dithering_strength = 50; config->options.dithering_strength = 50;
config->options.alpha_dithering_strength = 100; config->options.alpha_dithering_strength = 100;
kParams.use_color_profile = 1; kParams.use_color_profile = 1;
// Background color hidden by default to see transparent areas.
kParams.draw_anim_background_color = 0;
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
int parse_error = 0; int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help(); Help();
FREE_WARGV_AND_RETURN(0); return 0;
} else if (!strcmp(argv[c], "-noicc")) { } else if (!strcmp(argv[c], "-noicc")) {
kParams.use_color_profile = 0; kParams.use_color_profile = 0;
} else if (!strcmp(argv[c], "-nofancy")) { } else if (!strcmp(argv[c], "-nofancy")) {
@ -509,8 +452,6 @@ int main(int argc, char* argv[]) {
config->options.bypass_filtering = 1; config->options.bypass_filtering = 1;
} else if (!strcmp(argv[c], "-noalphadither")) { } else if (!strcmp(argv[c], "-noalphadither")) {
config->options.alpha_dithering_strength = 0; config->options.alpha_dithering_strength = 0;
} else if (!strcmp(argv[c], "-usebgcolor")) {
kParams.draw_anim_background_color = 1;
} else if (!strcmp(argv[c], "-dither") && c + 1 < argc) { } else if (!strcmp(argv[c], "-dither") && c + 1 < argc) {
config->options.dithering_strength = config->options.dithering_strength =
ExUtilGetInt(argv[++c], 0, &parse_error); ExUtilGetInt(argv[++c], 0, &parse_error);
@ -523,30 +464,30 @@ int main(int argc, char* argv[]) {
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff, (dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
dec_version & 0xff, (dmux_version >> 16) & 0xff, dec_version & 0xff, (dmux_version >> 16) & 0xff,
(dmux_version >> 8) & 0xff, dmux_version & 0xff); (dmux_version >> 8) & 0xff, dmux_version & 0xff);
FREE_WARGV_AND_RETURN(0); return 0;
} else if (!strcmp(argv[c], "-mt")) { } else if (!strcmp(argv[c], "-mt")) {
config->options.use_threads = 1; config->options.use_threads = 1;
} else if (!strcmp(argv[c], "--")) { } else if (!strcmp(argv[c], "--")) {
if (c < argc - 1) kParams.file_name = (const char*)GET_WARGV(argv, ++c); if (c < argc - 1) kParams.file_name = argv[++c];
break; break;
} else if (argv[c][0] == '-') { } else if (argv[c][0] == '-') {
printf("Unknown option '%s'\n", argv[c]); printf("Unknown option '%s'\n", argv[c]);
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} else { } else {
kParams.file_name = (const char*)GET_WARGV(argv, c); kParams.file_name = argv[c];
} }
if (parse_error) { if (parse_error) {
Help(); Help();
FREE_WARGV_AND_RETURN(-1); return -1;
} }
} }
if (kParams.file_name == NULL) { if (kParams.file_name == NULL) {
printf("missing input file!!\n"); printf("missing input file!!\n");
Help(); Help();
FREE_WARGV_AND_RETURN(0); return 0;
} }
if (!ImgIoUtilReadFile(kParams.file_name, if (!ImgIoUtilReadFile(kParams.file_name,
@ -621,16 +562,16 @@ int main(int argc, char* argv[]) {
// Should only be reached when using FREEGLUT: // Should only be reached when using FREEGLUT:
ClearParams(); ClearParams();
FREE_WARGV_AND_RETURN(0); return 0;
Error: Error:
ClearParams(); ClearParams();
FREE_WARGV_AND_RETURN(-1); return -1;
} }
#else // !WEBP_HAVE_GL #else // !WEBP_HAVE_GL
int main(int argc, const char* argv[]) { int main(int argc, const char *argv[]) {
fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]); fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]);
(void)argc; (void)argc;
return 0; return 0;

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,6 @@
webpmux -set icc image_profile.icc in.webp -o out_icc_container.webp webpmux -set icc image_profile.icc in.webp -o out_icc_container.webp
webpmux -set exif image_metadata.exif in.webp -o out_exif_container.webp webpmux -set exif image_metadata.exif in.webp -o out_exif_container.webp
webpmux -set xmp image_metadata.xmp in.webp -o out_xmp_container.webp webpmux -set xmp image_metadata.xmp in.webp -o out_xmp_container.webp
webpmux -set loop 1 in.webp -o out_looped.webp
Extract relevant data from WebP container file: Extract relevant data from WebP container file:
webpmux -get frame n in.webp -o out_frame.webp webpmux -get frame n in.webp -o out_frame.webp
@ -48,7 +47,6 @@
webpmux -info in.webp webpmux -info in.webp
webpmux [ -h | -help ] webpmux [ -h | -help ]
webpmux -version webpmux -version
webpmux argument_file_name
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -63,7 +61,6 @@
#include "webp/mux.h" #include "webp/mux.h"
#include "../examples/example_util.h" #include "../examples/example_util.h"
#include "../imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "./unicode.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Config object to parse command-line arguments. // Config object to parse command-line arguments.
@ -98,7 +95,6 @@ typedef enum {
FEATURE_ICCP, FEATURE_ICCP,
FEATURE_ANMF, FEATURE_ANMF,
FEATURE_DURATION, FEATURE_DURATION,
FEATURE_LOOP,
LAST_FEATURE LAST_FEATURE
} FeatureType; } FeatureType;
@ -112,26 +108,28 @@ static const char* const kDescriptions[LAST_FEATURE] = {
}; };
typedef struct { typedef struct {
CommandLineArguments cmd_args_;
ActionType action_type_;
const char* input_;
const char* output_;
FeatureType type_; FeatureType type_;
FeatureArg* args_; FeatureArg* args_;
int arg_count_; int arg_count_;
} Config; } Feature;
typedef struct {
ActionType action_type_;
const char* input_;
const char* output_;
Feature feature_;
} WebPMuxConfig;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Helper functions. // Helper functions.
static int CountOccurrences(const CommandLineArguments* const args, static int CountOccurrences(const char* arglist[], int list_length,
const char* const arg) { const char* arg) {
int i; int i;
int num_occurences = 0; int num_occurences = 0;
for (i = 0; i < args->argc_; ++i) { for (i = 0; i < list_length; ++i) {
if (!strcmp(args->argv_[i], arg)) { if (!strcmp(arglist[i], arg)) {
++num_occurences; ++num_occurences;
} }
} }
@ -303,7 +301,6 @@ static void PrintHelp(void) {
printf(" webpmux -info INPUT\n"); printf(" webpmux -info INPUT\n");
printf(" webpmux [-h|-help]\n"); printf(" webpmux [-h|-help]\n");
printf(" webpmux -version\n"); printf(" webpmux -version\n");
printf(" webpmux argument_file_name\n");
printf("\n"); printf("\n");
printf("GET_OPTIONS:\n"); printf("GET_OPTIONS:\n");
@ -316,7 +313,6 @@ static void PrintHelp(void) {
printf("\n"); printf("\n");
printf("SET_OPTIONS:\n"); printf("SET_OPTIONS:\n");
printf(" Set color profile/metadata:\n"); printf(" Set color profile/metadata:\n");
printf(" loop LOOP_COUNT set the loop count\n");
printf(" icc file.icc set ICC profile\n"); printf(" icc file.icc set ICC profile\n");
printf(" exif file.exif set EXIF metadata\n"); printf(" exif file.exif set EXIF metadata\n");
printf(" xmp file.xmp set XMP metadata\n"); printf(" xmp file.xmp set XMP metadata\n");
@ -373,10 +369,6 @@ static void PrintHelp(void) {
printf("\nNote: The nature of EXIF, XMP and ICC data is not checked"); printf("\nNote: The nature of EXIF, XMP and ICC data is not checked");
printf(" and is assumed to be\nvalid.\n"); printf(" and is assumed to be\nvalid.\n");
printf("\nNote: if a single file name is passed as the argument, the "
"arguments will be\n");
printf("tokenized from this file. The file name must not start with "
"the character '-'.\n");
} }
static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) { static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) {
@ -387,32 +379,40 @@ static void WarnAboutOddOffset(const WebPMuxFrameInfo* const info) {
} }
} }
static int ReadFileToWebPData(const char* const filename,
WebPData* const webp_data) {
const uint8_t* data;
size_t size;
if (!ImgIoUtilReadFile(filename, &data, &size)) return 0;
webp_data->bytes = data;
webp_data->size = size;
return 1;
}
static int CreateMux(const char* const filename, WebPMux** mux) { static int CreateMux(const char* const filename, WebPMux** mux) {
WebPData bitstream; WebPData bitstream;
assert(mux != NULL); assert(mux != NULL);
if (!ExUtilReadFileToWebPData(filename, &bitstream)) return 0; if (!ReadFileToWebPData(filename, &bitstream)) return 0;
*mux = WebPMuxCreate(&bitstream, 1); *mux = WebPMuxCreate(&bitstream, 1);
WebPDataClear(&bitstream); free((void*)bitstream.bytes);
if (*mux != NULL) return 1; if (*mux != NULL) return 1;
WFPRINTF(stderr, "Failed to create mux object from file %s.\n", fprintf(stderr, "Failed to create mux object from file %s.\n", filename);
(const W_CHAR*)filename);
return 0; return 0;
} }
static int WriteData(const char* filename, const WebPData* const webpdata) { static int WriteData(const char* filename, const WebPData* const webpdata) {
int ok = 0; int ok = 0;
FILE* fout = WSTRCMP(filename, "-") ? WFOPEN(filename, "wb") FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb")
: ImgIoUtilSetBinaryMode(stdout); : ImgIoUtilSetBinaryMode(stdout);
if (fout == NULL) { if (fout == NULL) {
WFPRINTF(stderr, "Error opening output WebP file %s!\n", fprintf(stderr, "Error opening output WebP file %s!\n", filename);
(const W_CHAR*)filename);
return 0; return 0;
} }
if (fwrite(webpdata->bytes, webpdata->size, 1, fout) != 1) { if (fwrite(webpdata->bytes, webpdata->size, 1, fout) != 1) {
WFPRINTF(stderr, "Error writing file %s!\n", (const W_CHAR*)filename); fprintf(stderr, "Error writing file %s!\n", filename);
} else { } else {
WFPRINTF(stderr, "Saved file %s (%d bytes)\n", fprintf(stderr, "Saved file %s (%d bytes)\n",
(const W_CHAR*)filename, (int)webpdata->size); filename, (int)webpdata->size);
ok = 1; ok = 1;
} }
if (fout != stdout) fclose(fout); if (fout != stdout) fclose(fout);
@ -517,10 +517,9 @@ static int ParseBgcolorArgs(const char* args, uint32_t* const bgcolor) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Clean-up. // Clean-up.
static void DeleteConfig(Config* const config) { static void DeleteConfig(WebPMuxConfig* config) {
if (config != NULL) { if (config != NULL) {
free(config->args_); free(config->feature_.args_);
ExUtilDeleteCommandLineArguments(&config->cmd_args_);
memset(config, 0, sizeof(*config)); memset(config, 0, sizeof(*config));
} }
} }
@ -532,7 +531,7 @@ static void DeleteConfig(Config* const config) {
// Returns 1 on valid, 0 otherwise. // Returns 1 on valid, 0 otherwise.
// Also fills up num_feature_args to be number of feature arguments given. // Also fills up num_feature_args to be number of feature arguments given.
// (e.g. if there are 4 '-frame's and 1 '-loop', then num_feature_args = 5). // (e.g. if there are 4 '-frame's and 1 '-loop', then num_feature_args = 5).
static int ValidateCommandLine(const CommandLineArguments* const cmd_args, static int ValidateCommandLine(int argc, const char* argv[],
int* num_feature_args) { int* num_feature_args) {
int num_frame_args; int num_frame_args;
int num_loop_args; int num_loop_args;
@ -544,27 +543,27 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
*num_feature_args = 0; *num_feature_args = 0;
// Simple checks. // Simple checks.
if (CountOccurrences(cmd_args, "-get") > 1) { if (CountOccurrences(argv, argc, "-get") > 1) {
ERROR_GOTO1("ERROR: Multiple '-get' arguments specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple '-get' arguments specified.\n", ErrValidate);
} }
if (CountOccurrences(cmd_args, "-set") > 1) { if (CountOccurrences(argv, argc, "-set") > 1) {
ERROR_GOTO1("ERROR: Multiple '-set' arguments specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple '-set' arguments specified.\n", ErrValidate);
} }
if (CountOccurrences(cmd_args, "-strip") > 1) { if (CountOccurrences(argv, argc, "-strip") > 1) {
ERROR_GOTO1("ERROR: Multiple '-strip' arguments specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple '-strip' arguments specified.\n", ErrValidate);
} }
if (CountOccurrences(cmd_args, "-info") > 1) { if (CountOccurrences(argv, argc, "-info") > 1) {
ERROR_GOTO1("ERROR: Multiple '-info' arguments specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple '-info' arguments specified.\n", ErrValidate);
} }
if (CountOccurrences(cmd_args, "-o") > 1) { if (CountOccurrences(argv, argc, "-o") > 1) {
ERROR_GOTO1("ERROR: Multiple output files specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple output files specified.\n", ErrValidate);
} }
// Compound checks. // Compound checks.
num_frame_args = CountOccurrences(cmd_args, "-frame"); num_frame_args = CountOccurrences(argv, argc, "-frame");
num_loop_args = CountOccurrences(cmd_args, "-loop"); num_loop_args = CountOccurrences(argv, argc, "-loop");
num_bgcolor_args = CountOccurrences(cmd_args, "-bgcolor"); num_bgcolor_args = CountOccurrences(argv, argc, "-bgcolor");
num_durations_args = CountOccurrences(cmd_args, "-duration"); num_durations_args = CountOccurrences(argv, argc, "-duration");
if (num_loop_args > 1) { if (num_loop_args > 1) {
ERROR_GOTO1("ERROR: Multiple loop counts specified.\n", ErrValidate); ERROR_GOTO1("ERROR: Multiple loop counts specified.\n", ErrValidate);
@ -599,38 +598,31 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
#define ACTION_IS_NIL (config->action_type_ == NIL_ACTION) #define ACTION_IS_NIL (config->action_type_ == NIL_ACTION)
#define FEATURETYPE_IS_NIL (config->type_ == NIL_FEATURE) #define FEATURETYPE_IS_NIL (feature->type_ == NIL_FEATURE)
#define CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL) \ #define CHECK_NUM_ARGS_LESS(NUM, LABEL) \
if (argc < i + (NUM)) { \ if (argc < i + (NUM)) { \
fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \ fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \
goto LABEL; \ goto LABEL; \
} }
#define CHECK_NUM_ARGS_AT_MOST(NUM, LABEL) \ #define CHECK_NUM_ARGS_NOT_EQUAL(NUM, LABEL) \
if (argc > i + (NUM)) { \ if (argc != i + (NUM)) { \
fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \ fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \
goto LABEL; \ goto LABEL; \
} }
#define CHECK_NUM_ARGS_EXACTLY(NUM, LABEL) \
CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \
CHECK_NUM_ARGS_AT_MOST(NUM, LABEL);
// Parses command-line arguments to fill up config object. Also performs some // Parses command-line arguments to fill up config object. Also performs some
// semantic checks. unicode_argv contains wchar_t arguments or is null. // semantic checks.
static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) { static int ParseCommandLine(int argc, const char* argv[],
WebPMuxConfig* config) {
int i = 0; int i = 0;
int feature_arg_index = 0; int feature_arg_index = 0;
int ok = 1; int ok = 1;
int argc = config->cmd_args_.argc_;
const char* const* argv = config->cmd_args_.argv_;
// Unicode file paths will be used if available.
const char* const* wargv =
(unicode_argv != NULL) ? (const char**)(unicode_argv + 1) : argv;
while (i < argc) { while (i < argc) {
FeatureArg* const arg = &config->args_[feature_arg_index]; Feature* const feature = &config->feature_;
FeatureArg* const arg = &feature->args_[feature_arg_index];
if (argv[i][0] == '-') { // One of the action types or output. if (argv[i][0] == '-') { // One of the action types or output.
if (!strcmp(argv[i], "-set")) { if (!strcmp(argv[i], "-set")) {
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
@ -640,14 +632,14 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
} }
++i; ++i;
} else if (!strcmp(argv[i], "-duration")) { } else if (!strcmp(argv[i], "-duration")) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); CHECK_NUM_ARGS_LESS(2, ErrParse);
if (ACTION_IS_NIL || config->action_type_ == ACTION_DURATION) { if (ACTION_IS_NIL || config->action_type_ == ACTION_DURATION) {
config->action_type_ = ACTION_DURATION; config->action_type_ = ACTION_DURATION;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_DURATION) { if (FEATURETYPE_IS_NIL || feature->type_ == FEATURE_DURATION) {
config->type_ = FEATURE_DURATION; feature->type_ = FEATURE_DURATION;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
@ -664,20 +656,20 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
} else if (!strcmp(argv[i], "-strip")) { } else if (!strcmp(argv[i], "-strip")) {
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
config->action_type_ = ACTION_STRIP; config->action_type_ = ACTION_STRIP;
config->arg_count_ = 0; feature->arg_count_ = 0;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
++i; ++i;
} else if (!strcmp(argv[i], "-frame")) { } else if (!strcmp(argv[i], "-frame")) {
CHECK_NUM_ARGS_AT_LEAST(3, ErrParse); CHECK_NUM_ARGS_LESS(3, ErrParse);
if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) { if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) {
config->action_type_ = ACTION_SET; config->action_type_ = ACTION_SET;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_ANMF) { if (FEATURETYPE_IS_NIL || feature->type_ == FEATURE_ANMF) {
config->type_ = FEATURE_ANMF; feature->type_ = FEATURE_ANMF;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
@ -687,14 +679,14 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
++feature_arg_index; ++feature_arg_index;
i += 3; i += 3;
} else if (!strcmp(argv[i], "-loop") || !strcmp(argv[i], "-bgcolor")) { } else if (!strcmp(argv[i], "-loop") || !strcmp(argv[i], "-bgcolor")) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); CHECK_NUM_ARGS_LESS(2, ErrParse);
if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) { if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) {
config->action_type_ = ACTION_SET; config->action_type_ = ACTION_SET;
} else { } else {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} }
if (FEATURETYPE_IS_NIL || config->type_ == FEATURE_ANMF) { if (FEATURETYPE_IS_NIL || feature->type_ == FEATURE_ANMF) {
config->type_ = FEATURE_ANMF; feature->type_ = FEATURE_ANMF;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
@ -704,36 +696,34 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
++feature_arg_index; ++feature_arg_index;
i += 2; i += 2;
} else if (!strcmp(argv[i], "-o")) { } else if (!strcmp(argv[i], "-o")) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); CHECK_NUM_ARGS_LESS(2, ErrParse);
config->output_ = wargv[i + 1]; config->output_ = argv[i + 1];
i += 2; i += 2;
} else if (!strcmp(argv[i], "-info")) { } else if (!strcmp(argv[i], "-info")) {
CHECK_NUM_ARGS_EXACTLY(2, ErrParse); CHECK_NUM_ARGS_NOT_EQUAL(2, ErrParse);
if (config->action_type_ != NIL_ACTION) { if (config->action_type_ != NIL_ACTION) {
ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple actions specified.\n", ErrParse);
} else { } else {
config->action_type_ = ACTION_INFO; config->action_type_ = ACTION_INFO;
config->arg_count_ = 0; feature->arg_count_ = 0;
config->input_ = wargv[i + 1]; config->input_ = argv[i + 1];
} }
i += 2; i += 2;
} else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help")) { } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help")) {
PrintHelp(); PrintHelp();
DeleteConfig(config); DeleteConfig(config);
LOCAL_FREE((W_CHAR** const)unicode_argv);
exit(0); exit(0);
} else if (!strcmp(argv[i], "-version")) { } else if (!strcmp(argv[i], "-version")) {
const int version = WebPGetMuxVersion(); const int version = WebPGetMuxVersion();
printf("%d.%d.%d\n", printf("%d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
DeleteConfig(config); DeleteConfig(config);
LOCAL_FREE((W_CHAR** const)unicode_argv);
exit(0); exit(0);
} else if (!strcmp(argv[i], "--")) { } else if (!strcmp(argv[i], "--")) {
if (i < argc - 1) { if (i < argc - 1) {
++i; ++i;
if (config->input_ == NULL) { if (config->input_ == NULL) {
config->input_ = wargv[i]; config->input_ = argv[i];
} else { } else {
ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n", ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n",
argv[i], ErrParse); argv[i], ErrParse);
@ -751,14 +741,14 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
if (!strcmp(argv[i], "icc") || !strcmp(argv[i], "exif") || if (!strcmp(argv[i], "icc") || !strcmp(argv[i], "exif") ||
!strcmp(argv[i], "xmp")) { !strcmp(argv[i], "xmp")) {
if (FEATURETYPE_IS_NIL) { if (FEATURETYPE_IS_NIL) {
config->type_ = (!strcmp(argv[i], "icc")) ? FEATURE_ICCP : feature->type_ = (!strcmp(argv[i], "icc")) ? FEATURE_ICCP :
(!strcmp(argv[i], "exif")) ? FEATURE_EXIF : FEATURE_XMP; (!strcmp(argv[i], "exif")) ? FEATURE_EXIF : FEATURE_XMP;
} else { } else {
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse); ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
} }
if (config->action_type_ == ACTION_SET) { if (config->action_type_ == ACTION_SET) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); CHECK_NUM_ARGS_LESS(2, ErrParse);
arg->filename_ = wargv[i + 1]; arg->filename_ = argv[i + 1];
++feature_arg_index; ++feature_arg_index;
i += 2; i += 2;
} else { } else {
@ -766,21 +756,14 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
} }
} else if (!strcmp(argv[i], "frame") && } else if (!strcmp(argv[i], "frame") &&
(config->action_type_ == ACTION_GET)) { (config->action_type_ == ACTION_GET)) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse); CHECK_NUM_ARGS_LESS(2, ErrParse);
config->type_ = FEATURE_ANMF; feature->type_ = FEATURE_ANMF;
arg->params_ = argv[i + 1];
++feature_arg_index;
i += 2;
} else if (!strcmp(argv[i], "loop") &&
(config->action_type_ == ACTION_SET)) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
config->type_ = FEATURE_LOOP;
arg->params_ = argv[i + 1]; arg->params_ = argv[i + 1];
++feature_arg_index; ++feature_arg_index;
i += 2; i += 2;
} else { // Assume input file. } else { // Assume input file.
if (config->input_ == NULL) { if (config->input_ == NULL) {
config->input_ = wargv[i]; config->input_ = argv[i];
} else { } else {
ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n", ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n",
argv[i], ErrParse); argv[i], ErrParse);
@ -794,8 +777,9 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
} }
// Additional checks after config is filled. // Additional checks after config is filled.
static int ValidateConfig(Config* const config) { static int ValidateConfig(WebPMuxConfig* config) {
int ok = 1; int ok = 1;
Feature* const feature = &config->feature_;
// Action. // Action.
if (ACTION_IS_NIL) { if (ACTION_IS_NIL) {
@ -811,7 +795,7 @@ static int ValidateConfig(Config* const config) {
if (config->input_ == NULL) { if (config->input_ == NULL) {
if (config->action_type_ != ACTION_SET) { if (config->action_type_ != ACTION_SET) {
ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2); ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2);
} else if (config->type_ != FEATURE_ANMF) { } else if (feature->type_ != FEATURE_ANMF) {
ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2); ERROR_GOTO1("ERROR: No input file specified.\n", ErrValidate2);
} }
} }
@ -826,29 +810,28 @@ static int ValidateConfig(Config* const config) {
} }
// Create config object from command-line arguments. // Create config object from command-line arguments.
static int InitializeConfig(int argc, const char* argv[], Config* const config, static int InitializeConfig(int argc, const char* argv[],
const W_CHAR** const unicode_argv) { WebPMuxConfig* config) {
int num_feature_args = 0; int num_feature_args = 0;
int ok; int ok = 1;
assert(config != NULL);
memset(config, 0, sizeof(*config)); memset(config, 0, sizeof(*config));
ok = ExUtilInitCommandLineArguments(argc, argv, &config->cmd_args_);
if (!ok) return 0;
// Validate command-line arguments. // Validate command-line arguments.
if (!ValidateCommandLine(&config->cmd_args_, &num_feature_args)) { if (!ValidateCommandLine(argc, argv, &num_feature_args)) {
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1); ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
} }
config->arg_count_ = num_feature_args; config->feature_.arg_count_ = num_feature_args;
config->args_ = (FeatureArg*)calloc(num_feature_args, sizeof(*config->args_)); config->feature_.args_ =
if (config->args_ == NULL) { (FeatureArg*)calloc(num_feature_args, sizeof(*config->feature_.args_));
if (config->feature_.args_ == NULL) {
ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1); ERROR_GOTO1("ERROR: Memory allocation error.\n", Err1);
} }
// Parse command-line. // Parse command-line.
if (!ParseCommandLine(config, unicode_argv) || !ValidateConfig(config)) { if (!ParseCommandLine(argc, argv, config) || !ValidateConfig(config)) {
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1); ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
} }
@ -858,14 +841,13 @@ static int InitializeConfig(int argc, const char* argv[], Config* const config,
#undef ACTION_IS_NIL #undef ACTION_IS_NIL
#undef FEATURETYPE_IS_NIL #undef FEATURETYPE_IS_NIL
#undef CHECK_NUM_ARGS_AT_LEAST #undef CHECK_NUM_ARGS_LESS
#undef CHECK_NUM_ARGS_AT_MOST #undef CHECK_NUM_ARGS_MORE
#undef CHECK_NUM_ARGS_EXACTLY
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Processing. // Processing.
static int GetFrame(const WebPMux* mux, const Config* config) { static int GetFrame(const WebPMux* mux, const WebPMuxConfig* config) {
WebPMuxError err = WEBP_MUX_OK; WebPMuxError err = WEBP_MUX_OK;
WebPMux* mux_single = NULL; WebPMux* mux_single = NULL;
int num = 0; int num = 0;
@ -875,7 +857,7 @@ static int GetFrame(const WebPMux* mux, const Config* config) {
WebPMuxFrameInfo info; WebPMuxFrameInfo info;
WebPDataInit(&info.bitstream); WebPDataInit(&info.bitstream);
num = ExUtilGetInt(config->args_[0].params_, 10, &parse_error); num = ExUtilGetInt(config->feature_.args_[0].params_, 10, &parse_error);
if (num < 0) { if (num < 0) {
ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet); ERROR_GOTO1("ERROR: Frame/Fragment index must be non-negative.\n", ErrGet);
} }
@ -909,17 +891,18 @@ static int GetFrame(const WebPMux* mux, const Config* config) {
} }
// Read and process config. // Read and process config.
static int Process(const Config* config) { static int Process(const WebPMuxConfig* config) {
WebPMux* mux = NULL; WebPMux* mux = NULL;
WebPData chunk; WebPData chunk;
WebPMuxError err = WEBP_MUX_OK; WebPMuxError err = WEBP_MUX_OK;
int ok = 1; int ok = 1;
const Feature* const feature = &config->feature_;
switch (config->action_type_) { switch (config->action_type_) {
case ACTION_GET: { case ACTION_GET: {
ok = CreateMux(config->input_, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
switch (config->type_) { switch (feature->type_) {
case FEATURE_ANMF: case FEATURE_ANMF:
ok = GetFrame(mux, config); ok = GetFrame(mux, config);
break; break;
@ -927,10 +910,10 @@ static int Process(const Config* config) {
case FEATURE_ICCP: case FEATURE_ICCP:
case FEATURE_EXIF: case FEATURE_EXIF:
case FEATURE_XMP: case FEATURE_XMP:
err = WebPMuxGetChunk(mux, kFourccList[config->type_], &chunk); err = WebPMuxGetChunk(mux, kFourccList[feature->type_], &chunk);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not get the %s.\n", ERROR_GOTO3("ERROR (%s): Could not get the %s.\n",
ErrorString(err), kDescriptions[config->type_], Err2); ErrorString(err), kDescriptions[feature->type_], Err2);
} }
ok = WriteData(config->output_, &chunk); ok = WriteData(config->output_, &chunk);
break; break;
@ -942,7 +925,7 @@ static int Process(const Config* config) {
break; break;
} }
case ACTION_SET: { case ACTION_SET: {
switch (config->type_) { switch (feature->type_) {
case FEATURE_ANMF: { case FEATURE_ANMF: {
int i; int i;
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 }; WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
@ -951,11 +934,11 @@ static int Process(const Config* config) {
ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n", ERROR_GOTO2("ERROR (%s): Could not allocate a mux object.\n",
ErrorString(WEBP_MUX_MEMORY_ERROR), Err2); ErrorString(WEBP_MUX_MEMORY_ERROR), Err2);
} }
for (i = 0; i < config->arg_count_; ++i) { for (i = 0; i < feature->arg_count_; ++i) {
switch (config->args_[i].subtype_) { switch (feature->args_[i].subtype_) {
case SUBTYPE_BGCOLOR: { case SUBTYPE_BGCOLOR: {
uint32_t bgcolor; uint32_t bgcolor;
ok = ParseBgcolorArgs(config->args_[i].params_, &bgcolor); ok = ParseBgcolorArgs(feature->args_[i].params_, &bgcolor);
if (!ok) { if (!ok) {
ERROR_GOTO1("ERROR: Could not parse the background color \n", ERROR_GOTO1("ERROR: Could not parse the background color \n",
Err2); Err2);
@ -966,7 +949,7 @@ static int Process(const Config* config) {
case SUBTYPE_LOOP: { case SUBTYPE_LOOP: {
int parse_error = 0; int parse_error = 0;
const int loop_count = const int loop_count =
ExUtilGetInt(config->args_[i].params_, 10, &parse_error); ExUtilGetInt(feature->args_[i].params_, 10, &parse_error);
if (loop_count < 0 || loop_count > 65535) { if (loop_count < 0 || loop_count > 65535) {
// Note: This is only a 'necessary' condition for loop_count // Note: This is only a 'necessary' condition for loop_count
// to be valid. The 'sufficient' conditioned in checked in // to be valid. The 'sufficient' conditioned in checked in
@ -982,10 +965,10 @@ static int Process(const Config* config) {
case SUBTYPE_ANMF: { case SUBTYPE_ANMF: {
WebPMuxFrameInfo frame; WebPMuxFrameInfo frame;
frame.id = WEBP_CHUNK_ANMF; frame.id = WEBP_CHUNK_ANMF;
ok = ExUtilReadFileToWebPData(config->args_[i].filename_, ok = ReadFileToWebPData(feature->args_[i].filename_,
&frame.bitstream); &frame.bitstream);
if (!ok) goto Err2; if (!ok) goto Err2;
ok = ParseFrameArgs(config->args_[i].params_, &frame); ok = ParseFrameArgs(feature->args_[i].params_, &frame);
if (!ok) { if (!ok) {
WebPDataClear(&frame.bitstream); WebPDataClear(&frame.bitstream);
ERROR_GOTO1("ERROR: Could not parse frame properties.\n", ERROR_GOTO1("ERROR: Could not parse frame properties.\n",
@ -1018,38 +1001,13 @@ static int Process(const Config* config) {
case FEATURE_XMP: { case FEATURE_XMP: {
ok = CreateMux(config->input_, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
ok = ExUtilReadFileToWebPData(config->args_[0].filename_, &chunk); ok = ReadFileToWebPData(feature->args_[0].filename_, &chunk);
if (!ok) goto Err2; if (!ok) goto Err2;
err = WebPMuxSetChunk(mux, kFourccList[config->type_], &chunk, 1); err = WebPMuxSetChunk(mux, kFourccList[feature->type_], &chunk, 1);
WebPDataClear(&chunk); free((void*)chunk.bytes);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not set the %s.\n", ERROR_GOTO3("ERROR (%s): Could not set the %s.\n",
ErrorString(err), kDescriptions[config->type_], Err2); ErrorString(err), kDescriptions[feature->type_], Err2);
}
break;
}
case FEATURE_LOOP: {
WebPMuxAnimParams params = { 0xFFFFFFFF, 0 };
int parse_error = 0;
const int loop_count =
ExUtilGetInt(config->args_[0].params_, 10, &parse_error);
if (loop_count < 0 || loop_count > 65535 || parse_error) {
ERROR_GOTO1("ERROR: Loop count must be in the range 0 to 65535.\n",
Err2);
}
ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2;
ok = (WebPMuxGetAnimationParams(mux, &params) == WEBP_MUX_OK);
if (!ok) {
ERROR_GOTO1("ERROR: input file does not seem to be an animation.\n",
Err2);
}
params.loop_count = loop_count;
err = WebPMuxSetAnimationParams(mux, &params);
ok = (err == WEBP_MUX_OK);
if (!ok) {
ERROR_GOTO2("ERROR (%s): Could not set animation parameters.\n",
ErrorString(err), Err2);
} }
break; break;
} }
@ -1080,16 +1038,16 @@ static int Process(const Config* config) {
int* durations = NULL; int* durations = NULL;
WebPMux* new_mux = DuplicateMuxHeader(mux); WebPMux* new_mux = DuplicateMuxHeader(mux);
if (new_mux == NULL) goto Err2; if (new_mux == NULL) goto Err2;
durations = (int*)WebPMalloc((size_t)num_frames * sizeof(*durations)); durations = (int*)malloc((size_t)num_frames * sizeof(*durations));
if (durations == NULL) goto Err2; if (durations == NULL) goto Err2;
for (i = 0; i < num_frames; ++i) durations[i] = -1; for (i = 0; i < num_frames; ++i) durations[i] = -1;
// Parse intervals to process. // Parse intervals to process.
for (i = 0; i < config->arg_count_; ++i) { for (i = 0; i < feature->arg_count_; ++i) {
int k; int k;
int args[3]; int args[3];
int duration, start, end; int duration, start, end;
const int nb_args = ExUtilGetInts(config->args_[i].params_, const int nb_args = ExUtilGetInts(feature->args_[i].params_,
10, 3, args); 10, 3, args);
ok = (nb_args >= 1); ok = (nb_args >= 1);
if (!ok) goto Err3; if (!ok) goto Err3;
@ -1138,7 +1096,7 @@ static int Process(const Config* config) {
new_mux = NULL; new_mux = NULL;
Err3: Err3:
WebPFree(durations); free(durations);
WebPMuxDelete(new_mux); WebPMuxDelete(new_mux);
if (!ok) goto Err2; if (!ok) goto Err2;
} }
@ -1147,12 +1105,12 @@ static int Process(const Config* config) {
case ACTION_STRIP: { case ACTION_STRIP: {
ok = CreateMux(config->input_, &mux); ok = CreateMux(config->input_, &mux);
if (!ok) goto Err2; if (!ok) goto Err2;
if (config->type_ == FEATURE_ICCP || config->type_ == FEATURE_EXIF || if (feature->type_ == FEATURE_ICCP || feature->type_ == FEATURE_EXIF ||
config->type_ == FEATURE_XMP) { feature->type_ == FEATURE_XMP) {
err = WebPMuxDeleteChunk(mux, kFourccList[config->type_]); err = WebPMuxDeleteChunk(mux, kFourccList[feature->type_]);
if (err != WEBP_MUX_OK) { if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n", ERROR_GOTO3("ERROR (%s): Could not strip the %s.\n",
ErrorString(err), kDescriptions[config->type_], Err2); ErrorString(err), kDescriptions[feature->type_], Err2);
} }
} else { } else {
ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2); ERROR_GOTO1("ERROR: Invalid feature for action 'strip'.\n", Err2);
@ -1182,19 +1140,15 @@ static int Process(const Config* config) {
// Main. // Main.
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
Config config; WebPMuxConfig config;
int ok; int ok = InitializeConfig(argc - 1, argv + 1, &config);
INIT_WARGV(argc, argv);
ok = InitializeConfig(argc - 1, argv + 1, &config, GET_WARGV_OR_NULL());
if (ok) { if (ok) {
ok = Process(&config); ok = Process(&config);
} else { } else {
PrintHelp(); PrintHelp();
} }
DeleteConfig(&config); DeleteConfig(&config);
FREE_WARGV_AND_RETURN(!ok); return !ok;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -1,4 +1,3 @@
AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir)
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
noinst_LTLIBRARIES = libwebpextras.la noinst_LTLIBRARIES = libwebpextras.la
@ -12,33 +11,16 @@ libwebpextras_la_CPPFLAGS = $(AM_CPPFLAGS)
libwebpextras_la_LDFLAGS = -lm libwebpextras_la_LDFLAGS = -lm
libwebpextras_la_LIBADD = ../src/libwebp.la libwebpextras_la_LIBADD = ../src/libwebp.la
noinst_PROGRAMS = noinst_PROGRAMS = get_disto webp_quality
noinst_PROGRAMS += webp_quality
if BUILD_DEMUX
noinst_PROGRAMS += get_disto
endif
if BUILD_VWEBP_SDL
noinst_PROGRAMS += vwebp_sdl
endif
get_disto_SOURCES = get_disto.c get_disto_SOURCES = get_disto.c
get_disto_CPPFLAGS = $(AM_CPPFLAGS) get_disto_CPPFLAGS = $(AM_CPPFLAGS)
get_disto_LDADD = get_disto_LDADD = ../imageio/libimageio_util.la ../imageio/libimagedec.la
get_disto_LDADD += ../imageio/libimageio_util.la
get_disto_LDADD += ../imageio/libimagedec.la
get_disto_LDADD += ../src/libwebp.la get_disto_LDADD += ../src/libwebp.la
get_disto_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS) get_disto_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS)
webp_quality_SOURCES = webp_quality.c webp_quality_SOURCES = webp_quality.c
webp_quality_CPPFLAGS = $(AM_CPPFLAGS) webp_quality_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
webp_quality_LDADD = webp_quality_LDADD = ../imageio/libimageio_util.la
webp_quality_LDADD += ../imageio/libimageio_util.la
webp_quality_LDADD += libwebpextras.la webp_quality_LDADD += libwebpextras.la
webp_quality_LDADD += ../src/libwebp.la webp_quality_LDADD += ../src/libwebp.la
vwebp_sdl_SOURCES = vwebp_sdl.c webp_to_sdl.c webp_to_sdl.h
vwebp_sdl_CPPFLAGS = $(AM_CPPFLAGS) $(SDL_INCLUDES)
vwebp_sdl_LDADD =
vwebp_sdl_LDADD += ../imageio/libimageio_util.la
vwebp_sdl_LDADD += ../src/libwebp.la
vwebp_sdl_LDADD += $(SDL_LIBS)

View File

@ -10,15 +10,14 @@
// Additional WebP utilities. // Additional WebP utilities.
// //
#include "extras/extras.h" #include "./extras.h"
#include "webp/format_constants.h" #include "webp/format_constants.h"
#include "src/dsp/dsp.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#define XTRA_MAJ_VERSION 1 #define XTRA_MAJ_VERSION 0
#define XTRA_MIN_VERSION 2 #define XTRA_MIN_VERSION 1
#define XTRA_REV_VERSION 0 #define XTRA_REV_VERSION 0
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -49,16 +48,15 @@ int WebPImportGray(const uint8_t* gray_data, WebPPicture* pic) {
int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) { int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) {
int x, y; int x, y;
uint32_t* dst;
if (pic == NULL || rgb565 == NULL) return 0; if (pic == NULL || rgb565 == NULL) return 0;
pic->colorspace = WEBP_YUV420; pic->colorspace = WEBP_YUV420;
pic->use_argb = 1; pic->use_argb = 1;
if (!WebPPictureAlloc(pic)) return 0; if (!WebPPictureAlloc(pic)) return 0;
dst = pic->argb;
for (y = 0; y < pic->height; ++y) { for (y = 0; y < pic->height; ++y) {
const int width = pic->width; const int width = pic->width;
uint32_t* dst = pic->argb + y * pic->argb_stride;
for (x = 0; x < width; ++x) { for (x = 0; x < width; ++x) {
#if defined(WEBP_SWAP_16BIT_CSP) && (WEBP_SWAP_16BIT_CSP == 1) #ifdef WEBP_SWAP_16BIT_CSP
const uint32_t rg = rgb565[2 * x + 1]; const uint32_t rg = rgb565[2 * x + 1];
const uint32_t gb = rgb565[2 * x + 0]; const uint32_t gb = rgb565[2 * x + 0];
#else #else
@ -72,26 +70,24 @@ int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) {
r = r | (r >> 5); r = r | (r >> 5);
g = g | (g >> 6); g = g | (g >> 6);
b = b | (b >> 5); b = b | (b >> 5);
dst[x] = (0xffu << 24) | (r << 16) | (g << 8) | b; dst[x] = (r << 16) | (g << 8) | b;
} }
rgb565 += 2 * width; rgb565 += 2 * width;
dst += pic->argb_stride;
} }
return 1; return 1;
} }
int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) { int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) {
int x, y; int x, y;
uint32_t* dst;
if (pic == NULL || rgb4444 == NULL) return 0; if (pic == NULL || rgb4444 == NULL) return 0;
pic->colorspace = WEBP_YUV420; pic->colorspace = WEBP_YUV420;
pic->use_argb = 1; pic->use_argb = 1;
if (!WebPPictureAlloc(pic)) return 0; if (!WebPPictureAlloc(pic)) return 0;
dst = pic->argb;
for (y = 0; y < pic->height; ++y) { for (y = 0; y < pic->height; ++y) {
const int width = pic->width; const int width = pic->width;
uint32_t* dst = pic->argb + y * pic->argb_stride;
for (x = 0; x < width; ++x) { for (x = 0; x < width; ++x) {
#if defined(WEBP_SWAP_16BIT_CSP) && (WEBP_SWAP_16BIT_CSP == 1) #ifdef WEBP_SWAP_16BIT_CSP
const uint32_t rg = rgb4444[2 * x + 1]; const uint32_t rg = rgb4444[2 * x + 1];
const uint32_t ba = rgb4444[2 * x + 0]; const uint32_t ba = rgb4444[2 * x + 0];
#else #else
@ -110,7 +106,6 @@ int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) {
dst[x] = (a << 24) | (r << 16) | (g << 8) | b; dst[x] = (a << 24) | (r << 16) | (g << 8) | b;
} }
rgb4444 += 2 * width; rgb4444 += 2 * width;
dst += pic->argb_stride;
} }
return 1; return 1;
} }
@ -145,18 +140,3 @@ int WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride,
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int WebPUnmultiplyARGB(WebPPicture* pic) {
int y;
uint32_t* dst;
if (pic == NULL || pic->use_argb != 1 || pic->argb == NULL) return 0;
WebPInitAlphaProcessing();
dst = pic->argb;
for (y = 0; y < pic->height; ++y) {
WebPMultARGBRow(dst, pic->width, /*inverse=*/1);
dst += pic->argb_stride;
}
return 1;
}
//------------------------------------------------------------------------------

View File

@ -19,45 +19,38 @@ extern "C" {
#include "webp/encode.h" #include "webp/encode.h"
#define WEBP_EXTRAS_ABI_VERSION 0x0002 // MAJOR(8b) + MINOR(8b) #define WEBP_EXTRAS_ABI_VERSION 0x0001 // MAJOR(8b) + MINOR(8b)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Returns the version number of the extras library, packed in hexadecimal using // Returns the version number of the extras library, packed in hexadecimal using
// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. // 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.
WEBP_EXTERN int WebPGetExtrasVersion(void); WEBP_EXTERN(int) WebPGetExtrasVersion(void);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Ad-hoc colorspace importers. // Ad-hoc colorspace importers.
// Import luma sample (gray scale image) into 'picture'. The 'picture' // Import luma sample (gray scale image) into 'picture'. The 'picture'
// width and height must be set prior to calling this function. // width and height must be set prior to calling this function.
WEBP_EXTERN int WebPImportGray(const uint8_t* gray, WebPPicture* picture); WEBP_EXTERN(int) WebPImportGray(const uint8_t* gray, WebPPicture* picture);
// Import rgb sample in RGB565 packed format into 'picture'. The 'picture' // Import rgb sample in RGB565 packed format into 'picture'. The 'picture'
// width and height must be set prior to calling this function. // width and height must be set prior to calling this function.
WEBP_EXTERN int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic); WEBP_EXTERN(int) WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic);
// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture' // Import rgb sample in RGB4444 packed format into 'picture'. The 'picture'
// width and height must be set prior to calling this function. // width and height must be set prior to calling this function.
WEBP_EXTERN int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic); WEBP_EXTERN(int) WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic);
// Import a color mapped image. The number of colors is less or equal to // Import a color mapped image. The number of colors is less or equal to
// MAX_PALETTE_SIZE. 'pic' must have been initialized. Its content, if any, // MAX_PALETTE_SIZE. 'pic' must have been initialized. Its content, if any,
// will be discarded. Returns 'false' in case of error, or if indexed[] contains // will be discarded. Returns 'false' in case of error, or if indexed[] contains
// invalid indices. // invalid indices.
WEBP_EXTERN int WEBP_EXTERN(int)
WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride, WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride,
const uint32_t palette[], int palette_size, const uint32_t palette[], int palette_size,
WebPPicture* pic); WebPPicture* pic);
// Convert the ARGB content of 'pic' from associated to unassociated.
// 'pic' can be for instance the result of calling of some WebPPictureImportXXX
// functions, with pic->use_argb set to 'true'. It is assumed (and not checked)
// that the pre-multiplied r/g/b values as less or equal than the alpha value.
// Return false in case of error (invalid parameter, ...).
WEBP_EXTERN int WebPUnmultiplyARGB(WebPPicture* pic);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Parse a bitstream, search for VP8 (lossy) header and report a // Parse a bitstream, search for VP8 (lossy) header and report a
@ -66,7 +59,7 @@ WEBP_EXTERN int WebPUnmultiplyARGB(WebPPicture* pic);
// Otherwise (lossy bitstream), the returned value is in the range [0..100]. // Otherwise (lossy bitstream), the returned value is in the range [0..100].
// Any error (invalid bitstream, animated WebP, incomplete header, etc.) // Any error (invalid bitstream, animated WebP, incomplete header, etc.)
// will return a value of -1. // will return a value of -1.
WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size); WEBP_EXTERN(int) VP8EstimateQuality(const uint8_t* const data, size_t size);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -74,4 +67,4 @@ WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size);
} // extern "C" } // extern "C"
#endif #endif
#endif // WEBP_EXTRAS_EXTRAS_H_ #endif /* WEBP_EXTRAS_EXTRAS_H_ */

View File

@ -24,9 +24,8 @@
#include <string.h> #include <string.h>
#include "webp/encode.h" #include "webp/encode.h"
#include "imageio/image_dec.h" #include "../imageio/image_dec.h"
#include "imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "../examples/unicode.h"
static size_t ReadPicture(const char* const filename, WebPPicture* const pic, static size_t ReadPicture(const char* const filename, WebPPicture* const pic,
int keep_alpha) { int keep_alpha) {
@ -49,8 +48,7 @@ static size_t ReadPicture(const char* const filename, WebPPicture* const pic,
End: End:
if (!ok) { if (!ok) {
WFPRINTF(stderr, "Error! Could not process file %s\n", fprintf(stderr, "Error! Could not process file %s\n", filename);
(const W_CHAR*)filename);
} }
free((void*)data); free((void*)data);
return ok ? data_size : 0; return ok ? data_size : 0;
@ -226,7 +224,7 @@ static void Help(void) {
" Also handles PNG, JPG and TIFF files, in addition to WebP.\n"); " Also handles PNG, JPG and TIFF files, in addition to WebP.\n");
} }
int main(int argc, const char* argv[]) { int main(int argc, const char *argv[]) {
WebPPicture pic1, pic2; WebPPicture pic1, pic2;
size_t size1 = 0, size2 = 0; size_t size1 = 0, size2 = 0;
int ret = 1; int ret = 1;
@ -241,11 +239,9 @@ int main(int argc, const char* argv[]) {
const char* name2 = NULL; const char* name2 = NULL;
const char* output = NULL; const char* output = NULL;
INIT_WARGV(argc, argv);
if (!WebPPictureInit(&pic1) || !WebPPictureInit(&pic2)) { if (!WebPPictureInit(&pic1) || !WebPPictureInit(&pic2)) {
fprintf(stderr, "Can't init pictures\n"); fprintf(stderr, "Can't init pictures\n");
FREE_WARGV_AND_RETURN(1); return 1;
} }
for (c = 1; c < argc; ++c) { for (c = 1; c < argc; ++c) {
@ -267,11 +263,11 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "missing file name after %s option.\n", argv[c - 1]); fprintf(stderr, "missing file name after %s option.\n", argv[c - 1]);
goto End; goto End;
} }
output = (const char*)GET_WARGV(argv, c); output = argv[c];
} else if (name1 == NULL) { } else if (name1 == NULL) {
name1 = (const char*)GET_WARGV(argv, c); name1 = argv[c];
} else { } else {
name2 = (const char*)GET_WARGV(argv, c); name2 = argv[c];
} }
} }
if (help || name1 == NULL || name2 == NULL) { if (help || name1 == NULL || name2 == NULL) {
@ -282,7 +278,7 @@ int main(int argc, const char* argv[]) {
goto End; goto End;
} }
size1 = ReadPicture(name1, &pic1, 1); size1 = ReadPicture(name1, &pic1, 1);
size2 = ReadPicture(name2, &pic2, 1); size2 = ReadPicture(name1, &pic2, 1);
if (size1 == 0 || size2 == 0) goto End; if (size1 == 0 || size2 == 0) goto End;
if (!keep_alpha) { if (!keep_alpha) {
@ -294,10 +290,9 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error while computing the distortion.\n"); fprintf(stderr, "Error while computing the distortion.\n");
goto End; goto End;
} }
printf("%u %.2f %.2f %.2f %.2f %.2f [ %.2f bpp ]\n", printf("%u %.2f %.2f %.2f %.2f %.2f\n",
(unsigned int)size1, (unsigned int)size1,
disto[4], disto[0], disto[1], disto[2], disto[3], disto[4], disto[0], disto[1], disto[2], disto[3]);
8.f * size1 / pic1.width / pic1.height);
if (output != NULL) { if (output != NULL) {
uint8_t* data = NULL; uint8_t* data = NULL;
@ -327,7 +322,6 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Can only compute the difference map in ARGB format.\n"); fprintf(stderr, "Can only compute the difference map in ARGB format.\n");
goto End; goto End;
} }
#if !defined(WEBP_REDUCE_CSP)
data_size = WebPEncodeLosslessBGRA((const uint8_t*)pic1.argb, data_size = WebPEncodeLosslessBGRA((const uint8_t*)pic1.argb,
pic1.width, pic1.height, pic1.width, pic1.height,
pic1.argb_stride * 4, pic1.argb_stride * 4,
@ -339,17 +333,11 @@ int main(int argc, const char* argv[]) {
ret = ImgIoUtilWriteFile(output, data, data_size) ? 0 : 1; ret = ImgIoUtilWriteFile(output, data, data_size) ? 0 : 1;
WebPFree(data); WebPFree(data);
if (ret) goto End; if (ret) goto End;
#else
(void)data;
(void)data_size;
fprintf(stderr, "Cannot save the difference map. Please recompile "
"without the WEBP_REDUCE_CSP flag.\n");
#endif // WEBP_REDUCE_CSP
} }
ret = 0; ret = 0;
End: End:
WebPPictureFree(&pic1); WebPPictureFree(&pic1);
WebPPictureFree(&pic2); WebPPictureFree(&pic2);
FREE_WARGV_AND_RETURN(ret); return ret;
} }

View File

@ -11,7 +11,7 @@
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include "extras/extras.h" #include "./extras.h"
#include "webp/decode.h" #include "webp/decode.h"
#include <math.h> #include <math.h>
@ -73,7 +73,7 @@ int VP8EstimateQuality(const uint8_t* const data, size_t size) {
pos += 4; pos += 4;
bit_pos = pos * 8; bit_pos = pos * 8;
GET_BIT(2); // colorspace + clamp type GET_BIT(2); // color_space + clamp type
// Segment header // Segment header
if (GET_BIT(1)) { // use_segment_ if (GET_BIT(1)) { // use_segment_

View File

@ -1,101 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Simple SDL-based WebP file viewer.
// Does not support animation, just static images.
//
// Press 'q' to exit.
//
// Author: James Zern (jzern@google.com)
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
#endif
#if defined(WEBP_HAVE_SDL)
#include "webp_to_sdl.h"
#include "webp/decode.h"
#include "imageio/imageio_util.h"
#include "../examples/unicode.h"
#if defined(WEBP_HAVE_JUST_SDL_H)
#include <SDL.h>
#else
#include <SDL/SDL.h>
#endif
static void ProcessEvents(void) {
int done = 0;
SDL_Event event;
while (!done && SDL_WaitEvent(&event)) {
switch (event.type) {
case SDL_KEYUP:
switch (event.key.keysym.sym) {
case SDLK_q: done = 1; break;
default: break;
}
break;
default: break;
}
}
}
int main(int argc, char* argv[]) {
int c;
int ok = 0;
INIT_WARGV(argc, argv);
for (c = 1; c < argc; ++c) {
const char* file = NULL;
const uint8_t* webp = NULL;
size_t webp_size = 0;
if (!strcmp(argv[c], "-h")) {
printf("Usage: %s [-h] image.webp [more_files.webp...]\n", argv[0]);
FREE_WARGV_AND_RETURN(0);
} else {
file = (const char*)GET_WARGV(argv, c);
}
if (file == NULL) continue;
if (!ImgIoUtilReadFile(file, &webp, &webp_size)) {
WFPRINTF(stderr, "Error opening file: %s\n", (const W_CHAR*)file);
goto Error;
}
if (webp_size != (size_t)(int)webp_size) {
free((void*)webp);
fprintf(stderr, "File too large.\n");
goto Error;
}
ok = WebpToSDL((const char*)webp, (int)webp_size);
free((void*)webp);
if (!ok) {
WFPRINTF(stderr, "Error decoding file %s\n", (const W_CHAR*)file);
goto Error;
}
ProcessEvents();
}
ok = 1;
Error:
SDL_Quit();
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
}
#else // !WEBP_HAVE_SDL
int main(int argc, const char* argv[]) {
fprintf(stderr, "SDL support not enabled in %s.\n", argv[0]);
(void)argc;
return 0;
}
#endif

View File

@ -11,32 +11,28 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "extras/extras.h" #include "./extras.h"
#include "imageio/imageio_util.h" #include "../imageio/imageio_util.h"
#include "../examples/unicode.h"
int main(int argc, const char* argv[]) { int main(int argc, const char *argv[]) {
int c; int c;
int quiet = 0; int quiet = 0;
int ok = 1; int ok = 1;
INIT_WARGV(argc, argv);
for (c = 1; ok && c < argc; ++c) { for (c = 1; ok && c < argc; ++c) {
if (!strcmp(argv[c], "-quiet")) { if (!strcmp(argv[c], "-quiet")) {
quiet = 1; quiet = 1;
} else if (!strcmp(argv[c], "-help") || !strcmp(argv[c], "-h")) { } else if (!strcmp(argv[c], "-help") || !strcmp(argv[c], "-h")) {
printf("webp_quality [-h][-quiet] webp_files...\n"); printf("webp_quality [-h][-quiet] webp_files...\n");
FREE_WARGV_AND_RETURN(0); return 0;
} else { } else {
const char* const filename = (const char*)GET_WARGV(argv, c); const char* const filename = argv[c];
const uint8_t* data = NULL; const uint8_t* data = NULL;
size_t data_size = 0; size_t data_size = 0;
int q; int q;
ok = ImgIoUtilReadFile(filename, &data, &data_size); ok = ImgIoUtilReadFile(filename, &data, &data_size);
if (!ok) break; if (!ok) break;
q = VP8EstimateQuality(data, data_size); q = VP8EstimateQuality(data, data_size);
if (!quiet) WPRINTF("[%s] ", (const W_CHAR*)filename); if (!quiet) printf("[%s] ", filename);
if (q < 0) { if (q < 0) {
fprintf(stderr, "Not a WebP file, or not a lossy WebP file.\n"); fprintf(stderr, "Not a WebP file, or not a lossy WebP file.\n");
ok = 0; ok = 0;
@ -50,5 +46,5 @@ int main(int argc, const char* argv[]) {
free((void*)data); free((void*)data);
} }
} }
FREE_WARGV_AND_RETURN(ok ? 0 : 1); return ok ? 0 : 1;
} }

View File

@ -1,110 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Simple WebP-to-SDL wrapper. Useful for emscripten.
//
// Author: James Zern (jzern@google.com)
#ifdef HAVE_CONFIG_H
#include "src/webp/config.h"
#endif
#if defined(WEBP_HAVE_SDL)
#include "webp_to_sdl.h"
#include <stdio.h>
#include "src/webp/decode.h"
#if defined(WEBP_HAVE_JUST_SDL_H)
#include <SDL.h>
#else
#include <SDL/SDL.h>
#endif
static int init_ok = 0;
int WebpToSDL(const char* data, unsigned int data_size) {
int ok = 0;
VP8StatusCode status;
WebPDecoderConfig config;
WebPBitstreamFeatures* const input = &config.input;
WebPDecBuffer* const output = &config.output;
SDL_Surface* screen = NULL;
SDL_Surface* surface = NULL;
if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n");
return 0;
}
if (!init_ok) {
SDL_Init(SDL_INIT_VIDEO);
init_ok = 1;
}
status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &config.input);
if (status != VP8_STATUS_OK) goto Error;
screen = SDL_SetVideoMode(input->width, input->height, 32, SDL_SWSURFACE);
if (screen == NULL) {
fprintf(stderr, "Unable to set video mode (32bpp %dx%d)!\n",
input->width, input->height);
goto Error;
}
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
input->width, input->height, 32,
0x000000ffu, // R mask
0x0000ff00u, // G mask
0x00ff0000u, // B mask
0xff000000u); // A mask
if (surface == NULL) {
fprintf(stderr, "Unable to create %dx%d RGBA surface!\n",
input->width, input->height);
goto Error;
}
if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
output->colorspace = MODE_BGRA;
#else
output->colorspace = MODE_RGBA;
#endif
output->width = surface->w;
output->height = surface->h;
output->u.RGBA.rgba = surface->pixels;
output->u.RGBA.stride = surface->pitch;
output->u.RGBA.size = surface->pitch * surface->h;
output->is_external_memory = 1;
status = WebPDecode((const uint8_t*)data, (size_t)data_size, &config);
if (status != VP8_STATUS_OK) {
fprintf(stderr, "Error decoding image (%d)\n", status);
goto Error;
}
if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
if (SDL_BlitSurface(surface, NULL, screen, NULL) ||
SDL_Flip(screen)) {
goto Error;
}
ok = 1;
Error:
SDL_FreeSurface(surface);
SDL_FreeSurface(screen);
WebPFreeDecBuffer(output);
return ok;
}
//------------------------------------------------------------------------------
#endif // WEBP_HAVE_SDL

View File

@ -1,22 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Simple WebP-to-SDL wrapper. Useful for emscripten.
//
// Author: James Zern (jzern@google.com)
#ifndef WEBP_EXTRAS_WEBP_TO_SDL_H_
#define WEBP_EXTRAS_WEBP_TO_SDL_H_
// Exports the method WebpToSDL(const char* data, int data_size) which decodes
// a WebP bitstream into an RGBA SDL surface.
// Return false on failure.
extern int WebpToSDL(const char* data, unsigned int data_size);
#endif // WEBP_EXTRAS_WEBP_TO_SDL_H_

Binary file not shown.

View File

@ -1,5 +1,6 @@
#Thu May 12 17:06:25 CEST 2016
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip

65
gradlew vendored
View File

@ -1,20 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/env bash
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
############################################################################## ##############################################################################
## ##
@ -44,16 +28,16 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
warn () { warn ( ) {
echo "$*" echo "$*"
} }
die () { die ( ) {
echo echo
echo "$*" echo "$*"
echo echo
@ -125,8 +109,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi fi
# For Cygwin or MSYS, switch paths to Windows format before running java # For Cygwin, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`
@ -154,30 +138,27 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else else
eval `echo args$i`="\"$arg\"" eval `echo args$i`="\"$arg\""
fi fi
i=`expr $i + 1` i=$((i+1))
done done
case $i in case $i in
0) set -- ;; (0) set -- ;;
1) set -- "$args0" ;; (1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;; (2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;; (3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac esac
fi fi
# Escape application args # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
save () { function splitJvmOpts() {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done JVM_OPTS=("$@")
echo " "
} }
APP_ARGS=`save "$@"` eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Collect all arguments for the java command, following the shell quoting and substitution rules exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

190
gradlew.bat vendored
View File

@ -1,100 +1,90 @@
@rem @if "%DEBUG%" == "" @echo off
@rem Copyright 2015 the original author or authors. @rem ##########################################################################
@rem @rem
@rem Licensed under the Apache License, Version 2.0 (the "License"); @rem Gradle startup script for Windows
@rem you may not use this file except in compliance with the License. @rem
@rem You may obtain a copy of the License at @rem ##########################################################################
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0 @rem Set local scope for the variables with windows NT shell
@rem if "%OS%"=="Windows_NT" setlocal
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS, set DIRNAME=%~dp0
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. if "%DIRNAME%" == "" set DIRNAME=.
@rem See the License for the specific language governing permissions and set APP_BASE_NAME=%~n0
@rem limitations under the License. set APP_HOME=%DIRNAME%
@rem
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
@if "%DEBUG%" == "" @echo off set DEFAULT_JVM_OPTS=
@rem ##########################################################################
@rem @rem Find java.exe
@rem Gradle startup script for Windows if defined JAVA_HOME goto findJavaFromJavaHome
@rem
@rem ########################################################################## set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
@rem Set local scope for the variables with windows NT shell if "%ERRORLEVEL%" == "0" goto init
if "%OS%"=="Windows_NT" setlocal
echo.
set DIRNAME=%~dp0 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if "%DIRNAME%" == "" set DIRNAME=. echo.
set APP_BASE_NAME=%~n0 echo Please set the JAVA_HOME variable in your environment to match the
set APP_HOME=%DIRNAME% echo location of your Java installation.
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. goto fail
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
:findJavaFromJavaHome
@rem Find java.exe set JAVA_HOME=%JAVA_HOME:"=%
if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=%JAVA_HOME%/bin/java.exe
set JAVA_EXE=java.exe if exist "%JAVA_EXE%" goto init
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo Please set the JAVA_HOME variable in your environment to match the
echo. echo location of your Java installation.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. goto fail
goto fail :init
@rem Get command-line arguments, handling Windows variants
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=% if not "%OS%" == "Windows_NT" goto win9xME_args
set JAVA_EXE=%JAVA_HOME%/bin/java.exe if "%@eval[2+2]" == "4" goto 4NT_args
if exist "%JAVA_EXE%" goto init :win9xME_args
@rem Slurp the command line arguments.
echo. set CMD_LINE_ARGS=
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% set _SKIP=2
echo.
echo Please set the JAVA_HOME variable in your environment to match the :win9xME_args_slurp
echo location of your Java installation. if "x%~1" == "x" goto execute
goto fail set CMD_LINE_ARGS=%*
goto execute
:init
@rem Get command-line arguments, handling Windows variants :4NT_args
@rem Get arguments from the 4NT Shell from JP Software
if not "%OS%" == "Windows_NT" goto win9xME_args set CMD_LINE_ARGS=%$
:win9xME_args :execute
@rem Slurp the command line arguments. @rem Setup the command line
set CMD_LINE_ARGS=
set _SKIP=2 set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:win9xME_args_slurp @rem Execute Gradle
if "x%~1" == "x" goto execute "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
set CMD_LINE_ARGS=%* :end
@rem End local scope for the variables with windows NT shell
:execute if "%ERRORLEVEL%"=="0" goto mainEnd
@rem Setup the command line
:fail
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
@rem Execute Gradle if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% exit /b 1
:end :mainEnd
@rem End local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" endlocal
if "%ERRORLEVEL%"=="0" goto mainEnd
:omega
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -25,7 +25,6 @@ LOCAL_SRC_FILES := \
jpegdec.c \ jpegdec.c \
metadata.c \ metadata.c \
pngdec.c \ pngdec.c \
pnmdec.c \
tiffdec.c \ tiffdec.c \
webpdec.c \ webpdec.c \

View File

@ -1,32 +1,22 @@
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
noinst_LTLIBRARIES = noinst_LTLIBRARIES = libimageio_util.la libimagedec.la libimageenc.la
noinst_LTLIBRARIES += libimageio_util.la
if BUILD_DEMUX
noinst_LTLIBRARIES += libimagedec.la
endif
noinst_LTLIBRARIES += libimageenc.la
noinst_HEADERS = noinst_HEADERS =
noinst_HEADERS += ../src/webp/decode.h noinst_HEADERS += ../src/webp/decode.h
noinst_HEADERS += ../src/webp/types.h noinst_HEADERS += ../src/webp/types.h
libimageio_util_la_SOURCES = libimageio_util_la_SOURCES = imageio_util.c imageio_util.h
libimageio_util_la_SOURCES += imageio_util.c imageio_util.h
libimagedec_la_SOURCES = libimagedec_la_SOURCES = image_dec.c image_dec.h
libimagedec_la_SOURCES += image_dec.c image_dec.h
libimagedec_la_SOURCES += jpegdec.c jpegdec.h libimagedec_la_SOURCES += jpegdec.c jpegdec.h
libimagedec_la_SOURCES += metadata.c metadata.h libimagedec_la_SOURCES += metadata.c metadata.h
libimagedec_la_SOURCES += pngdec.c pngdec.h libimagedec_la_SOURCES += pngdec.c pngdec.h
libimagedec_la_SOURCES += pnmdec.c pnmdec.h
libimagedec_la_SOURCES += tiffdec.c tiffdec.h libimagedec_la_SOURCES += tiffdec.c tiffdec.h
libimagedec_la_SOURCES += webpdec.c webpdec.h libimagedec_la_SOURCES += webpdec.c webpdec.h
libimagedec_la_SOURCES += wicdec.c wicdec.h libimagedec_la_SOURCES += wicdec.c wicdec.h
libimagedec_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES) libimagedec_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES)
libimagedec_la_CPPFLAGS += $(AM_CPPFLAGS) libimagedec_la_CPPFLAGS += $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
libimagedec_la_LIBADD = ../src/demux/libwebpdemux.la
libimageenc_la_SOURCES = libimageenc_la_SOURCES = image_enc.c image_enc.h
libimageenc_la_SOURCES += image_enc.c image_enc.h
libimageenc_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES) libimageenc_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES)
libimageenc_la_CPPFLAGS += $(AM_CPPFLAGS) libimageenc_la_CPPFLAGS += $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)

View File

@ -29,10 +29,6 @@ WebPInputFileFormat WebPGuessImageType(const uint8_t* const data,
format = WEBP_TIFF_FORMAT; format = WEBP_TIFF_FORMAT;
} else if (magic1 == 0x52494646 && magic2 == 0x57454250) { } else if (magic1 == 0x52494646 && magic2 == 0x57454250) {
format = WEBP_WEBP_FORMAT; format = WEBP_WEBP_FORMAT;
} else if (((magic1 >> 24) & 0xff) == 'P') {
const int type = (magic1 >> 16) & 0xff;
// we only support 'P5 -> P7' for now.
if (type >= '5' && type <= '7') format = WEBP_PNM_FORMAT;
} }
} }
return format; return format;
@ -55,7 +51,6 @@ WebPImageReader WebPGetImageReader(WebPInputFileFormat format) {
case WEBP_JPEG_FORMAT: return ReadJPEG; case WEBP_JPEG_FORMAT: return ReadJPEG;
case WEBP_TIFF_FORMAT: return ReadTIFF; case WEBP_TIFF_FORMAT: return ReadTIFF;
case WEBP_WEBP_FORMAT: return ReadWebP; case WEBP_WEBP_FORMAT: return ReadWebP;
case WEBP_PNM_FORMAT: return ReadPNM;
default: return FailReader; default: return FailReader;
} }
} }

View File

@ -23,7 +23,6 @@
#include "./metadata.h" #include "./metadata.h"
#include "./jpegdec.h" #include "./jpegdec.h"
#include "./pngdec.h" #include "./pngdec.h"
#include "./pnmdec.h"
#include "./tiffdec.h" #include "./tiffdec.h"
#include "./webpdec.h" #include "./webpdec.h"
#include "./wicdec.h" #include "./wicdec.h"
@ -37,7 +36,6 @@ typedef enum {
WEBP_JPEG_FORMAT, WEBP_JPEG_FORMAT,
WEBP_TIFF_FORMAT, WEBP_TIFF_FORMAT,
WEBP_WEBP_FORMAT, WEBP_WEBP_FORMAT,
WEBP_PNM_FORMAT,
WEBP_UNSUPPORTED_FORMAT WEBP_UNSUPPORTED_FORMAT
} WebPInputFileFormat; } WebPInputFileFormat;

View File

@ -29,13 +29,11 @@
// code with COBJMACROS. // code with COBJMACROS.
#include <ole2.h> // CreateStreamOnHGlobal() #include <ole2.h> // CreateStreamOnHGlobal()
#include <shlwapi.h> #include <shlwapi.h>
#include <tchar.h>
#include <windows.h> #include <windows.h>
#include <wincodec.h> #include <wincodec.h>
#endif #endif
#include "./imageio_util.h" #include "./imageio_util.h"
#include "../examples/unicode.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// PNG // PNG
@ -63,12 +61,11 @@ static HRESULT CreateOutputStream(const char* out_file_name,
// Output to a memory buffer. This is freed when 'stream' is released. // Output to a memory buffer. This is freed when 'stream' is released.
IFS(CreateStreamOnHGlobal(NULL, TRUE, stream)); IFS(CreateStreamOnHGlobal(NULL, TRUE, stream));
} else { } else {
IFS(SHCreateStreamOnFile((const LPTSTR)out_file_name, IFS(SHCreateStreamOnFileA(out_file_name, STGM_WRITE | STGM_CREATE, stream));
STGM_WRITE | STGM_CREATE, stream));
} }
if (FAILED(hr)) { if (FAILED(hr)) {
_ftprintf(stderr, _T("Error opening output file %s (%08lx)\n"), fprintf(stderr, "Error opening output file %s (%08lx)\n",
(const LPTSTR)out_file_name, hr); out_file_name, hr);
} }
return hr; return hr;
} }
@ -161,8 +158,14 @@ static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp dummy) {
} }
int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) { int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
png_bytep row = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
volatile png_structp png; volatile png_structp png;
volatile png_infop info; volatile png_infop info;
png_uint_32 y;
if (out_file == NULL || buffer == NULL) return 0; if (out_file == NULL || buffer == NULL) return 0;
@ -181,23 +184,14 @@ int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
return 0; return 0;
} }
png_init_io(png, out_file); png_init_io(png, out_file);
{ png_set_IHDR(png, info, width, height, 8,
const uint32_t width = buffer->width; has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
const uint32_t height = buffer->height; PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
png_bytep row = buffer->u.RGBA.rgba; PNG_FILTER_TYPE_DEFAULT);
const int stride = buffer->u.RGBA.stride; png_write_info(png, info);
const int has_alpha = WebPIsAlphaMode(buffer->colorspace); for (y = 0; y < height; ++y) {
uint32_t y; png_write_rows(png, &row, 1);
row += stride;
png_set_IHDR(png, info, width, height, 8,
has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_write_info(png, info);
for (y = 0; y < height; ++y) {
png_write_rows(png, &row, 1);
row += stride;
}
} }
png_write_end(png, info); png_write_end(png, info);
png_destroy_write_struct((png_structpp)&png, (png_infopp)&info); png_destroy_write_struct((png_structpp)&png, (png_infopp)&info);
@ -367,8 +361,6 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
const uint8_t* rgba = buffer->u.RGBA.rgba; const uint8_t* rgba = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride; const int stride = buffer->u.RGBA.stride;
const uint8_t bytes_per_px = has_alpha ? 4 : 3; const uint8_t bytes_per_px = has_alpha ? 4 : 3;
const uint8_t assoc_alpha =
WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2;
// For non-alpha case, we omit tag 0x152 (ExtraSamples). // For non-alpha case, we omit tag 0x152 (ExtraSamples).
const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES
: NUM_IFD_ENTRIES - 1; : NUM_IFD_ENTRIES - 1;
@ -396,8 +388,7 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
EXTRA_DATA_OFFSET + 8, 0, 0, 0, EXTRA_DATA_OFFSET + 8, 0, 0, 0,
0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration 0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch) 0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
0x52, 0x01, 3, 0, 1, 0, 0, 0, 0x52, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 178: ExtraSamples: rgbA
assoc_alpha, 0, 0, 0, // 178: ExtraSamples: rgbA/RGBA
0, 0, 0, 0, // 190: IFD terminator 0, 0, 0, 0, // 190: IFD terminator
// EXTRA_DATA_OFFSET: // EXTRA_DATA_OFFSET:
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample 8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
@ -548,26 +539,22 @@ int WebPWriteYUV(FILE* fout, const WebPDecBuffer* const buffer) {
// Generic top-level call // Generic top-level call
int WebPSaveImage(const WebPDecBuffer* const buffer, int WebPSaveImage(const WebPDecBuffer* const buffer,
WebPOutputFileFormat format, WebPOutputFileFormat format, const char* const out_file) {
const char* const out_file_name) {
FILE* fout = NULL; FILE* fout = NULL;
int needs_open_file = 1; int needs_open_file = 1;
const int use_stdout = const int use_stdout = (out_file != NULL) && !strcmp(out_file, "-");
(out_file_name != NULL) && !WSTRCMP(out_file_name, "-");
int ok = 1; int ok = 1;
if (buffer == NULL || out_file_name == NULL) return 0; if (buffer == NULL || out_file == NULL) return 0;
#ifdef HAVE_WINCODEC_H #ifdef HAVE_WINCODEC_H
needs_open_file = (format != PNG); needs_open_file = (format != PNG);
#endif #endif
if (needs_open_file) { if (needs_open_file) {
fout = use_stdout ? ImgIoUtilSetBinaryMode(stdout) fout = use_stdout ? ImgIoUtilSetBinaryMode(stdout) : fopen(out_file, "wb");
: WFOPEN(out_file_name, "wb");
if (fout == NULL) { if (fout == NULL) {
WFPRINTF(stderr, "Error opening output file %s\n", fprintf(stderr, "Error opening output file %s\n", out_file);
(const W_CHAR*)out_file_name);
return 0; return 0;
} }
} }
@ -576,7 +563,7 @@ int WebPSaveImage(const WebPDecBuffer* const buffer,
format == RGBA || format == BGRA || format == ARGB || format == RGBA || format == BGRA || format == ARGB ||
format == rgbA || format == bgrA || format == Argb) { format == rgbA || format == bgrA || format == Argb) {
#ifdef HAVE_WINCODEC_H #ifdef HAVE_WINCODEC_H
ok &= WebPWritePNG(out_file_name, use_stdout, buffer); ok &= WebPWritePNG(out_file, use_stdout, buffer);
#else #else
ok &= WebPWritePNG(fout, buffer); ok &= WebPWritePNG(fout, buffer);
#endif #endif

View File

@ -18,7 +18,6 @@
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "../examples/unicode.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// File I/O // File I/O
@ -48,8 +47,7 @@ int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
while (!feof(stdin)) { while (!feof(stdin)) {
// We double the buffer size each time and read as much as possible. // We double the buffer size each time and read as much as possible.
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size; const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;
// we allocate one extra byte for the \0 terminator void* const new_data = realloc(input, max_size + extra_size);
void* const new_data = realloc(input, max_size + extra_size + 1);
if (new_data == NULL) goto Error; if (new_data == NULL) goto Error;
input = (uint8_t*)new_data; input = (uint8_t*)new_data;
max_size += extra_size; max_size += extra_size;
@ -57,7 +55,6 @@ int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
if (size < max_size) break; if (size < max_size) break;
} }
if (ferror(stdin)) goto Error; if (ferror(stdin)) goto Error;
if (input != NULL) input[size] = '\0'; // convenient 0-terminator
*data = input; *data = input;
*data_size = size; *data_size = size;
return 1; return 1;
@ -71,10 +68,10 @@ int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
int ImgIoUtilReadFile(const char* const file_name, int ImgIoUtilReadFile(const char* const file_name,
const uint8_t** data, size_t* data_size) { const uint8_t** data, size_t* data_size) {
int ok; int ok;
uint8_t* file_data; void* file_data;
size_t file_size; size_t file_size;
FILE* in; FILE* in;
const int from_stdin = (file_name == NULL) || !WSTRCMP(file_name, "-"); const int from_stdin = (file_name == NULL) || !strcmp(file_name, "-");
if (from_stdin) return ImgIoUtilReadFromStdin(data, data_size); if (from_stdin) return ImgIoUtilReadFromStdin(data, data_size);
@ -82,52 +79,42 @@ int ImgIoUtilReadFile(const char* const file_name,
*data = NULL; *data = NULL;
*data_size = 0; *data_size = 0;
in = WFOPEN(file_name, "rb"); in = fopen(file_name, "rb");
if (in == NULL) { if (in == NULL) {
WFPRINTF(stderr, "cannot open input file '%s'\n", (const W_CHAR*)file_name); fprintf(stderr, "cannot open input file '%s'\n", file_name);
return 0; return 0;
} }
fseek(in, 0, SEEK_END); fseek(in, 0, SEEK_END);
file_size = ftell(in); file_size = ftell(in);
fseek(in, 0, SEEK_SET); fseek(in, 0, SEEK_SET);
// we allocate one extra byte for the \0 terminator file_data = malloc(file_size);
file_data = (uint8_t*)WebPMalloc(file_size + 1); if (file_data == NULL) return 0;
if (file_data == NULL) {
fclose(in);
WFPRINTF(stderr, "memory allocation failure when reading file %s\n",
(const W_CHAR*)file_name);
return 0;
}
ok = (fread(file_data, file_size, 1, in) == 1); ok = (fread(file_data, file_size, 1, in) == 1);
fclose(in); fclose(in);
if (!ok) { if (!ok) {
WFPRINTF(stderr, "Could not read %d bytes of data from file %s\n", fprintf(stderr, "Could not read %d bytes of data from file %s\n",
(int)file_size, (const W_CHAR*)file_name); (int)file_size, file_name);
WebPFree(file_data); free(file_data);
return 0; return 0;
} }
file_data[file_size] = '\0'; // convenient 0-terminator *data = (uint8_t*)file_data;
*data = file_data;
*data_size = file_size; *data_size = file_size;
return 1; return 1;
} }
// -----------------------------------------------------------------------------
int ImgIoUtilWriteFile(const char* const file_name, int ImgIoUtilWriteFile(const char* const file_name,
const uint8_t* data, size_t data_size) { const uint8_t* data, size_t data_size) {
int ok; int ok;
FILE* out; FILE* out;
const int to_stdout = (file_name == NULL) || !WSTRCMP(file_name, "-"); const int to_stdout = (file_name == NULL) || !strcmp(file_name, "-");
if (data == NULL) { if (data == NULL) {
return 0; return 0;
} }
out = to_stdout ? ImgIoUtilSetBinaryMode(stdout) : WFOPEN(file_name, "wb"); out = to_stdout ? stdout : fopen(file_name, "wb");
if (out == NULL) { if (out == NULL) {
WFPRINTF(stderr, "Error! Cannot open output file '%s'\n", fprintf(stderr, "Error! Cannot open output file '%s'\n", file_name);
(const W_CHAR*)file_name);
return 0; return 0;
} }
ok = (fwrite(data, data_size, 1, out) == 1); ok = (fwrite(data, data_size, 1, out) == 1);
@ -150,11 +137,7 @@ void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) { int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
const uint64_t total_size = nmemb * size; const uint64_t total_size = nmemb * size;
int ok = (total_size == (size_t)total_size); return (total_size == (size_t)total_size);
#if defined(WEBP_MAX_IMAGE_SIZE)
ok = ok && (total_size <= (uint64_t)WEBP_MAX_IMAGE_SIZE);
#endif
return ok;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -29,10 +29,7 @@ FILE* ImgIoUtilSetBinaryMode(FILE* file);
// Allocates storage for entire file 'file_name' and returns contents and size // Allocates storage for entire file 'file_name' and returns contents and size
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should // in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
// be deleted using WebPFree(). // be deleted using free().
// Note: for convenience, the data will be null-terminated with an extra byte
// (not accounted for in *data_size), in case the file is text and intended
// to be used as a C-string.
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling // If 'file_name' is NULL or equal to "-", input is read from stdin by calling
// the function ImgIoUtilReadFromStdin(). // the function ImgIoUtilReadFromStdin().
int ImgIoUtilReadFile(const char* const file_name, int ImgIoUtilReadFile(const char* const file_name,

View File

@ -206,7 +206,6 @@ struct my_error_mgr {
static void my_error_exit(j_common_ptr dinfo) { static void my_error_exit(j_common_ptr dinfo) {
struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err; struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err;
fprintf(stderr, "libjpeg error: ");
dinfo->err->output_message(dinfo); dinfo->err->output_message(dinfo);
longjmp(myerr->setjmp_buffer, 1); longjmp(myerr->setjmp_buffer, 1);
} }
@ -305,18 +304,18 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
if (stride != (int)stride || if (stride != (int)stride ||
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) { !ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
goto Error; goto End;
} }
rgb = (uint8_t*)malloc((size_t)stride * height); rgb = (uint8_t*)malloc((size_t)stride * height);
if (rgb == NULL) { if (rgb == NULL) {
goto Error; goto End;
} }
buffer[0] = (JSAMPLE*)rgb; buffer[0] = (JSAMPLE*)rgb;
while (dinfo.output_scanline < dinfo.output_height) { while (dinfo.output_scanline < dinfo.output_height) {
if (jpeg_read_scanlines((j_decompress_ptr)&dinfo, buffer, 1) != 1) { if (jpeg_read_scanlines((j_decompress_ptr)&dinfo, buffer, 1) != 1) {
goto Error; goto End;
} }
buffer[0] += stride; buffer[0] += stride;
} }

View File

@ -18,9 +18,6 @@
#include <stdio.h> #include <stdio.h>
#ifdef WEBP_HAVE_PNG #ifdef WEBP_HAVE_PNG
#ifndef PNG_USER_MEM_SUPPORTED
#define PNG_USER_MEM_SUPPORTED // for png_create_read_struct_2
#endif
#include <png.h> #include <png.h>
#include <setjmp.h> // note: this must be included *after* png.h #include <setjmp.h> // note: this must be included *after* png.h
#include <stdlib.h> #include <stdlib.h>
@ -30,33 +27,11 @@
#include "./imageio_util.h" #include "./imageio_util.h"
#include "./metadata.h" #include "./metadata.h"
#define LOCAL_PNG_VERSION ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR)
#define LOCAL_PNG_PREREQ(maj, min) \
(LOCAL_PNG_VERSION >= (((maj) << 8) | (min)))
static void PNGAPI error_function(png_structp png, png_const_charp error) { static void PNGAPI error_function(png_structp png, png_const_charp error) {
if (error != NULL) fprintf(stderr, "libpng error: %s\n", error); if (error != NULL) fprintf(stderr, "libpng error: %s\n", error);
longjmp(png_jmpbuf(png), 1); longjmp(png_jmpbuf(png), 1);
} }
#if LOCAL_PNG_PREREQ(1,4)
typedef png_alloc_size_t LocalPngAllocSize;
#else
typedef png_size_t LocalPngAllocSize;
#endif
static png_voidp MallocFunc(png_structp png_ptr, LocalPngAllocSize size) {
(void)png_ptr;
if (size != (size_t)size) return NULL;
if (!ImgIoUtilCheckSizeArgumentsOverflow(size, 1)) return NULL;
return (png_voidp)malloc((size_t)size);
}
static void FreeFunc(png_structp png_ptr, png_voidp ptr) {
(void)png_ptr;
free(ptr);
}
// Converts the NULL terminated 'hexstring' which contains 2-byte character // Converts the NULL terminated 'hexstring' which contains 2-byte character
// representations of hex values to raw data. // representations of hex values to raw data.
// 'hexstring' may contain values consisting of [A-F][a-f][0-9] in pairs, // 'hexstring' may contain values consisting of [A-F][a-f][0-9] in pairs,
@ -196,10 +171,11 @@ static int ExtractMetadataFromPNG(png_structp png,
{ {
png_charp name; png_charp name;
int comp_type; int comp_type;
#if LOCAL_PNG_PREREQ(1,5) #if ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR << 0) < \
png_bytep profile; ((1 << 8) | (5 << 0))
#else
png_charp profile; png_charp profile;
#else // >= libpng 1.5.0
png_bytep profile;
#endif #endif
png_uint_32 len; png_uint_32 len;
@ -209,6 +185,7 @@ static int ExtractMetadataFromPNG(png_structp png,
} }
} }
} }
return 1; return 1;
} }
@ -248,8 +225,7 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
context.data = data; context.data = data;
context.data_size = data_size; context.data_size = data_size;
png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
NULL, MallocFunc, FreeFunc);
if (png == NULL) goto End; if (png == NULL) goto End;
png_set_error_fn(png, 0, error_function, NULL); png_set_error_fn(png, 0, error_function, NULL);
@ -259,12 +235,6 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
goto End; goto End;
} }
// If it looks like the bitstream is going to need more memory than libpng's
// internal limit (default: 8M), try to (reasonably) raise it.
if (data_size > png_get_chunk_malloc_max(png) && data_size < (1u << 24)) {
png_set_chunk_malloc_max(png, data_size);
}
info = png_create_info_struct(png); info = png_create_info_struct(png);
if (info == NULL) goto Error; if (info == NULL) goto Error;
end_info = png_create_info_struct(png); end_info = png_create_info_struct(png);
@ -295,16 +265,6 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA); has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
} }
// Apply gamma correction if needed.
{
double image_gamma = 1 / 2.2, screen_gamma = 2.2;
int srgb_intent;
if (png_get_sRGB(png, info, &srgb_intent) ||
png_get_gAMA(png, info, &image_gamma)) {
png_set_gamma(png, screen_gamma, image_gamma);
}
}
if (!keep_alpha) { if (!keep_alpha) {
png_set_strip_alpha(png); png_set_strip_alpha(png);
has_alpha = 0; has_alpha = 0;

View File

@ -1,296 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// (limited) PNM decoder
#include "./pnmdec.h"
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "webp/encode.h"
#include "./imageio_util.h"
typedef enum {
WIDTH_FLAG = 1 << 0,
HEIGHT_FLAG = 1 << 1,
DEPTH_FLAG = 1 << 2,
MAXVAL_FLAG = 1 << 3,
TUPLE_FLAG = 1 << 4,
ALL_NEEDED_FLAGS = WIDTH_FLAG | HEIGHT_FLAG | DEPTH_FLAG | MAXVAL_FLAG
} PNMFlags;
typedef struct {
const uint8_t* data;
size_t data_size;
int width, height;
int bytes_per_px;
int depth; // 1 (grayscale), 2 (grayscale + alpha), 3 (rgb), 4 (rgba)
int max_value;
int type; // 5, 6 or 7
int seen_flags;
} PNMInfo;
// -----------------------------------------------------------------------------
// PNM decoding
#define MAX_LINE_SIZE 1024
static const size_t kMinPNMHeaderSize = 3;
static size_t ReadLine(const uint8_t* const data, size_t off, size_t data_size,
char out[MAX_LINE_SIZE + 1], size_t* const out_size) {
size_t i = 0;
*out_size = 0;
redo:
for (i = 0; i < MAX_LINE_SIZE && off < data_size; ++i) {
out[i] = data[off++];
if (out[i] == '\n') break;
}
if (off < data_size) {
if (i == 0) goto redo; // empty line
if (out[0] == '#') goto redo; // skip comment
}
out[i] = 0; // safety sentinel
*out_size = i;
return off;
}
static size_t FlagError(const char flag[]) {
fprintf(stderr, "PAM header error: flags '%s' already seen.\n", flag);
return 0;
}
// inspired from http://netpbm.sourceforge.net/doc/pam.html
static size_t ReadPAMFields(PNMInfo* const info, size_t off) {
char out[MAX_LINE_SIZE + 1];
size_t out_size;
int tmp;
int expected_depth = -1;
assert(info != NULL);
while (1) {
off = ReadLine(info->data, off, info->data_size, out, &out_size);
if (off == 0) return 0;
if (sscanf(out, "WIDTH %d", &tmp) == 1) {
if (info->seen_flags & WIDTH_FLAG) return FlagError("WIDTH");
info->seen_flags |= WIDTH_FLAG;
info->width = tmp;
} else if (sscanf(out, "HEIGHT %d", &tmp) == 1) {
if (info->seen_flags & HEIGHT_FLAG) return FlagError("HEIGHT");
info->seen_flags |= HEIGHT_FLAG;
info->height = tmp;
} else if (sscanf(out, "DEPTH %d", &tmp) == 1) {
if (info->seen_flags & DEPTH_FLAG) return FlagError("DEPTH");
info->seen_flags |= DEPTH_FLAG;
info->depth = tmp;
} else if (sscanf(out, "MAXVAL %d", &tmp) == 1) {
if (info->seen_flags & MAXVAL_FLAG) return FlagError("MAXVAL");
info->seen_flags |= MAXVAL_FLAG;
info->max_value = tmp;
} else if (!strcmp(out, "TUPLTYPE RGB_ALPHA")) {
expected_depth = 4;
info->seen_flags |= TUPLE_FLAG;
} else if (!strcmp(out, "TUPLTYPE RGB")) {
expected_depth = 3;
info->seen_flags |= TUPLE_FLAG;
} else if (!strcmp(out, "TUPLTYPE GRAYSCALE_ALPHA")) {
expected_depth = 2;
info->seen_flags |= TUPLE_FLAG;
} else if (!strcmp(out, "TUPLTYPE GRAYSCALE")) {
expected_depth = 1;
info->seen_flags |= TUPLE_FLAG;
} else if (!strcmp(out, "ENDHDR")) {
break;
} else {
static const char kEllipsis[] = " ...";
int i;
if (out_size > 20) sprintf(out + 20 - strlen(kEllipsis), kEllipsis);
for (i = 0; i < (int)strlen(out); ++i) {
// isprint() might trigger a "char-subscripts" warning if given a char.
if (!isprint((int)out[i])) out[i] = ' ';
}
fprintf(stderr, "PAM header error: unrecognized entry [%s]\n", out);
return 0;
}
}
if (!(info->seen_flags & ALL_NEEDED_FLAGS)) {
fprintf(stderr, "PAM header error: missing tags%s%s%s%s\n",
(info->seen_flags & WIDTH_FLAG) ? "" : " WIDTH",
(info->seen_flags & HEIGHT_FLAG) ? "" : " HEIGHT",
(info->seen_flags & DEPTH_FLAG) ? "" : " DEPTH",
(info->seen_flags & MAXVAL_FLAG) ? "" : " MAXVAL");
return 0;
}
if (expected_depth != -1 && info->depth != expected_depth) {
fprintf(stderr, "PAM header error: expected DEPTH %d but got DEPTH %d\n",
expected_depth, info->depth);
return 0;
}
return off;
}
static size_t ReadHeader(PNMInfo* const info) {
size_t off = 0;
char out[MAX_LINE_SIZE + 1];
size_t out_size;
if (info == NULL) return 0;
if (info->data == NULL || info->data_size < kMinPNMHeaderSize) return 0;
info->width = info->height = 0;
info->type = -1;
info->seen_flags = 0;
info->bytes_per_px = 0;
info->depth = 0;
info->max_value = 0;
off = ReadLine(info->data, off, info->data_size, out, &out_size);
if (off == 0 || sscanf(out, "P%d", &info->type) != 1) return 0;
if (info->type == 7) {
off = ReadPAMFields(info, off);
} else {
off = ReadLine(info->data, off, info->data_size, out, &out_size);
if (off == 0 || sscanf(out, "%d %d", &info->width, &info->height) != 2) {
return 0;
}
off = ReadLine(info->data, off, info->data_size, out, &out_size);
if (off == 0 || sscanf(out, "%d", &info->max_value) != 1) return 0;
// finish initializing missing fields
info->depth = (info->type == 5) ? 1 : 3;
}
// perform some basic numerical validation
if (info->width <= 0 || info->height <= 0 ||
info->type <= 0 || info->type >= 9 ||
info->depth <= 0 || info->depth > 4 ||
info->max_value <= 0 || info->max_value >= 65536) {
return 0;
}
info->bytes_per_px = info->depth * (info->max_value > 255 ? 2 : 1);
return off;
}
int ReadPNM(const uint8_t* const data, size_t data_size,
WebPPicture* const pic, int keep_alpha,
struct Metadata* const metadata) {
int ok = 0;
int i, j;
uint64_t stride, pixel_bytes, sample_size, depth;
uint8_t* rgb = NULL, *tmp_rgb;
size_t offset;
PNMInfo info;
info.data = data;
info.data_size = data_size;
offset = ReadHeader(&info);
if (offset == 0) {
fprintf(stderr, "Error parsing PNM header.\n");
goto End;
}
if (info.type < 5 || info.type > 7) {
fprintf(stderr, "Unsupported P%d PNM format.\n", info.type);
goto End;
}
// Some basic validations.
if (pic == NULL) goto End;
if (info.width > WEBP_MAX_DIMENSION || info.height > WEBP_MAX_DIMENSION) {
fprintf(stderr, "Invalid %dx%d dimension for PNM\n",
info.width, info.height);
goto End;
}
pixel_bytes = (uint64_t)info.width * info.height * info.bytes_per_px;
if (data_size < offset + pixel_bytes) {
fprintf(stderr, "Truncated PNM file (P%d).\n", info.type);
goto End;
}
sample_size = (info.max_value > 255) ? 2 : 1;
// final depth
depth = (info.depth == 1 || info.depth == 3 || !keep_alpha) ? 3 : 4;
stride = depth * info.width;
if (stride != (size_t)stride ||
!ImgIoUtilCheckSizeArgumentsOverflow(stride, info.height)) {
goto End;
}
rgb = (uint8_t*)malloc((size_t)stride * info.height);
if (rgb == NULL) goto End;
// Convert input.
// We only optimize for the sample_size=1, max_value=255, depth=1 case.
tmp_rgb = rgb;
for (j = 0; j < info.height; ++j) {
const uint8_t* in = data + offset;
offset += info.bytes_per_px * info.width;
assert(offset <= data_size);
if (info.max_value == 255 && info.depth >= 3) {
// RGB or RGBA
if (info.depth == 3 || keep_alpha) {
memcpy(tmp_rgb, in, info.depth * info.width * sizeof(*in));
} else {
assert(info.depth == 4 && !keep_alpha);
for (i = 0; i < info.width; ++i) {
tmp_rgb[3 * i + 0] = in[4 * i + 0];
tmp_rgb[3 * i + 1] = in[4 * i + 1];
tmp_rgb[3 * i + 2] = in[4 * i + 2];
}
}
} else {
// Unoptimized case, we need to handle non-trivial operations:
// * convert 16b to 8b (if max_value > 255)
// * rescale to [0..255] range (if max_value != 255)
// * drop the alpha channel (if keep_alpha is false)
const uint32_t round = info.max_value / 2;
int k = 0;
for (i = 0; i < info.width * info.depth; ++i) {
uint32_t v = (sample_size == 2) ? 256u * in[2 * i + 0] + in[2 * i + 1]
: in[i];
if (info.max_value != 255) v = (v * 255u + round) / info.max_value;
if (v > 255u) v = 255u;
if (info.depth > 2) {
if (!keep_alpha && info.depth == 4 && (i % 4) == 3) {
// skip alpha
} else {
tmp_rgb[k] = v;
k += 1;
}
} else if (info.depth == 1 || (i % 2) == 0) {
tmp_rgb[k + 0] = tmp_rgb[k + 1] = tmp_rgb[k + 2] = v;
k += 3;
} else if (keep_alpha && info.depth == 2) {
tmp_rgb[k] = v;
k += 1;
} else {
// skip alpha
}
}
}
tmp_rgb += stride;
}
// WebP conversion.
pic->width = info.width;
pic->height = info.height;
ok = (depth == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride)
: WebPPictureImportRGB(pic, rgb, (int)stride);
if (!ok) goto End;
ok = 1;
End:
free((void*)rgb);
(void)metadata;
(void)keep_alpha;
return ok;
}
// -----------------------------------------------------------------------------

View File

@ -1,37 +0,0 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// partial PNM format decoder (ppm/pgm)
#ifndef WEBP_IMAGEIO_PNMDEC_H_
#define WEBP_IMAGEIO_PNMDEC_H_
#include "webp/types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Metadata;
struct WebPPicture;
// Reads a PNM file from 'data', returning the decoded output in 'pic'.
// The output is RGB or YUV depending on pic->use_argb value.
// Returns true on success.
// 'metadata' has no effect, but is kept for coherence with other signatures
// for image readers.
int ReadPNM(const uint8_t* const data, size_t data_size,
struct WebPPicture* const pic, int keep_alpha,
struct Metadata* const metadata);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_IMAGEIO_PNMDEC_H_

View File

@ -15,7 +15,6 @@
#include "webp/config.h" #include "webp/config.h"
#endif #endif
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -108,7 +107,7 @@ static void MyUnmapFile(thandle_t opaque, void* base, toff_t size) {
static tsize_t MyRead(thandle_t opaque, void* dst, tsize_t size) { static tsize_t MyRead(thandle_t opaque, void* dst, tsize_t size) {
MyData* const my_data = (MyData*)opaque; MyData* const my_data = (MyData*)opaque;
if (my_data->pos + size > my_data->size) { if (my_data->pos + size > my_data->size) {
size = (tsize_t)(my_data->size - my_data->pos); size = my_data->size - my_data->pos;
} }
if (size > 0) { if (size > 0) {
memcpy(dst, my_data->data + my_data->pos, size); memcpy(dst, my_data->data + my_data->pos, size);
@ -117,57 +116,18 @@ static tsize_t MyRead(thandle_t opaque, void* dst, tsize_t size) {
return size; return size;
} }
// Unmultiply Argb data. Taken from dsp/alpha_processing
// (we don't want to force a dependency to a libdspdec library).
#define MFIX 24 // 24bit fixed-point arithmetic
#define HALF ((1u << MFIX) >> 1)
static uint32_t Unmult(uint8_t x, uint32_t mult) {
const uint32_t v = (x * mult + HALF) >> MFIX;
return (v > 255u) ? 255u : v;
}
static WEBP_INLINE uint32_t GetScale(uint32_t a) {
return (255u << MFIX) / a;
}
#undef MFIX
#undef HALF
static void MultARGBRow(uint8_t* ptr, int width) {
int x;
for (x = 0; x < width; ++x, ptr += 4) {
const uint32_t alpha = ptr[3];
if (alpha < 255) {
if (alpha == 0) { // alpha == 0
ptr[0] = ptr[1] = ptr[2] = 0;
} else {
const uint32_t scale = GetScale(alpha);
ptr[0] = Unmult(ptr[0], scale);
ptr[1] = Unmult(ptr[1], scale);
ptr[2] = Unmult(ptr[2], scale);
}
}
}
}
int ReadTIFF(const uint8_t* const data, size_t data_size, int ReadTIFF(const uint8_t* const data, size_t data_size,
WebPPicture* const pic, int keep_alpha, WebPPicture* const pic, int keep_alpha,
Metadata* const metadata) { Metadata* const metadata) {
MyData my_data = { data, (toff_t)data_size, 0 }; MyData my_data = { data, (toff_t)data_size, 0 };
TIFF* tif; TIFF* tif;
uint32_t image_width, image_height, tile_width, tile_height; uint32 width, height;
uint16_t samples_per_px = 0; uint32* raster;
uint16_t extra_samples = 0;
uint16_t* extra_samples_ptr = NULL;
uint32_t* raster;
int64_t alloc_size; int64_t alloc_size;
int ok = 0; int ok = 0;
tdir_t dircount; tdir_t dircount;
if (data == NULL || data_size == 0 || data_size > INT_MAX || pic == NULL) { if (data == NULL || data_size == 0 || pic == NULL) return 0;
return 0;
}
tif = TIFFClientOpen("Memory", "r", &my_data, tif = TIFFClientOpen("Memory", "r", &my_data,
MyRead, MyRead, MySeek, MyClose, MyRead, MyRead, MySeek, MyClose,
@ -183,63 +143,32 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
"Only the first will be used, %d will be ignored.\n", "Only the first will be used, %d will be ignored.\n",
dircount - 1); dircount - 1);
} }
if (!TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_px)) {
fprintf(stderr, "Error! Cannot retrieve TIFF samples-per-pixel info.\n");
goto End;
}
if (samples_per_px < 3 || samples_per_px > 4) goto End; // not supported
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width) && if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) &&
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height))) { TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))) {
fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n"); fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
goto End; goto End;
} }
if (!ImgIoUtilCheckSizeArgumentsOverflow((uint64_t)image_width * image_height,
if (!ImgIoUtilCheckSizeArgumentsOverflow((uint64_t)width * height,
sizeof(*raster))) { sizeof(*raster))) {
goto End; goto End;
} }
// According to spec, a tile can be bigger than the image. However it should
// be a multiple of 16 and not way too large, so check that it's not more than
// twice the image size, for dimensions above some arbitrary minimum 32.
if ((TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) &&
tile_width > 32 && tile_width / 2 > image_width) ||
(TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height) &&
tile_height > 32 && tile_height / 2 > image_height)) {
fprintf(stderr, "Error! TIFF tile dimensions are too big.\n");
goto End;
}
if (samples_per_px > 3 && !TIFFGetField(tif, TIFFTAG_EXTRASAMPLES,
&extra_samples, &extra_samples_ptr)) {
fprintf(stderr, "Error! Cannot retrieve TIFF ExtraSamples info.\n");
goto End;
}
// _Tiffmalloc uses a signed type for size. // _Tiffmalloc uses a signed type for size.
alloc_size = alloc_size = (int64_t)((uint64_t)width * height * sizeof(*raster));
(int64_t)((uint64_t)image_width * image_height * sizeof(*raster));
if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End; if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End;
raster = (uint32*)_TIFFmalloc((tsize_t)alloc_size); raster = (uint32*)_TIFFmalloc((tsize_t)alloc_size);
if (raster != NULL) { if (raster != NULL) {
if (TIFFReadRGBAImageOriented(tif, image_width, image_height, raster, if (TIFFReadRGBAImageOriented(tif, width, height, raster,
ORIENTATION_TOPLEFT, 1)) { ORIENTATION_TOPLEFT, 1)) {
const int stride = image_width * sizeof(*raster); const int stride = width * sizeof(*raster);
pic->width = image_width; pic->width = width;
pic->height = image_height; pic->height = height;
// TIFF data is ABGR // TIFF data is ABGR
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
TIFFSwabArrayOfLong(raster, image_width * image_height); TIFFSwabArrayOfLong(raster, width * height);
#endif #endif
// if we have an alpha channel, we must un-multiply from rgbA to RGBA
if (extra_samples == 1 && extra_samples_ptr != NULL &&
extra_samples_ptr[0] == EXTRASAMPLE_ASSOCALPHA) {
uint32_t y;
uint8_t* tmp = (uint8_t*)raster;
for (y = 0; y < image_height; ++y) {
MultARGBRow(tmp, image_width);
tmp += stride;
}
}
ok = keep_alpha ok = keep_alpha
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride) ? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride); : WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);

View File

@ -9,20 +9,13 @@
// //
// WebP decode. // WebP decode.
#ifdef HAVE_CONFIG_H
#include "webp/config.h"
#endif
#include "./webpdec.h" #include "./webpdec.h"
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "webp/decode.h" #include "webp/decode.h"
#include "webp/demux.h"
#include "webp/encode.h" #include "webp/encode.h"
#include "../examples/unicode.h"
#include "./imageio_util.h" #include "./imageio_util.h"
#include "./metadata.h" #include "./metadata.h"
@ -44,7 +37,7 @@ static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
} }
void PrintWebPError(const char* const in_file, int status) { void PrintWebPError(const char* const in_file, int status) {
WFPRINTF(stderr, "Decoding of %s failed.\n", (const W_CHAR*)in_file); fprintf(stderr, "Decoding of %s failed.\n", in_file);
fprintf(stderr, "Status: %d", status); fprintf(stderr, "Status: %d", status);
if (status >= VP8_STATUS_OK && status <= VP8_STATUS_NOT_ENOUGH_DATA) { if (status >= VP8_STATUS_OK && status <= VP8_STATUS_NOT_ENOUGH_DATA) {
fprintf(stderr, "(%s)", kStatusMessages[status]); fprintf(stderr, "(%s)", kStatusMessages[status]);
@ -65,7 +58,7 @@ int LoadWebP(const char* const in_file,
status = WebPGetFeatures(*data, *data_size, bitstream); status = WebPGetFeatures(*data, *data_size, bitstream);
if (status != VP8_STATUS_OK) { if (status != VP8_STATUS_OK) {
WebPFree((void*)*data); free((void*)*data);
*data = NULL; *data = NULL;
*data_size = 0; *data_size = 0;
PrintWebPError(in_file, status); PrintWebPError(in_file, status);
@ -98,47 +91,25 @@ VP8StatusCode DecodeWebPIncremental(
fprintf(stderr, "Failed during WebPINewDecoder().\n"); fprintf(stderr, "Failed during WebPINewDecoder().\n");
return VP8_STATUS_OUT_OF_MEMORY; return VP8_STATUS_OUT_OF_MEMORY;
} else { } else {
#ifdef WEBP_EXPERIMENTAL_FEATURES
size_t size = 0;
const size_t incr = 2 + (data_size / 20);
while (size < data_size) {
size_t next_size = size + (rand() % incr);
if (next_size > data_size) next_size = data_size;
status = WebPIUpdate(idec, data, next_size);
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) break;
size = next_size;
}
#else
status = WebPIUpdate(idec, data, data_size); status = WebPIUpdate(idec, data, data_size);
#endif
WebPIDelete(idec); WebPIDelete(idec);
} }
} }
return status; 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, int ReadWebP(const uint8_t* const data, size_t data_size,
@ -152,6 +123,11 @@ int ReadWebP(const uint8_t* const data, size_t data_size,
if (data == NULL || data_size == 0 || pic == NULL) return 0; 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)) { if (!WebPInitDecoderConfig(&config)) {
fprintf(stderr, "Library version mismatch!\n"); fprintf(stderr, "Library version mismatch!\n");
return 0; return 0;
@ -162,82 +138,52 @@ int ReadWebP(const uint8_t* const data, size_t data_size,
PrintWebPError("input data", status); PrintWebPError("input data", status);
return 0; return 0;
} }
{
do {
const int has_alpha = keep_alpha && bitstream->has_alpha; const int has_alpha = keep_alpha && bitstream->has_alpha;
uint64_t stride;
pic->width = bitstream->width;
pic->height = bitstream->height;
if (pic->use_argb) { if (pic->use_argb) {
stride = (uint64_t)bitstream->width * 4; output_buffer->colorspace = has_alpha ? MODE_RGBA : MODE_RGB;
} else {
stride = (uint64_t)bitstream->width * (has_alpha ? 5 : 3) / 2;
pic->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420;
}
if (!ImgIoUtilCheckSizeArgumentsOverflow(stride, bitstream->height)) {
status = VP8_STATUS_OUT_OF_MEMORY;
break;
}
ok = WebPPictureAlloc(pic);
if (!ok) {
status = VP8_STATUS_OUT_OF_MEMORY;
break;
}
if (pic->use_argb) {
#ifdef WORDS_BIGENDIAN
output_buffer->colorspace = MODE_ARGB;
#else
output_buffer->colorspace = MODE_BGRA;
#endif
output_buffer->u.RGBA.rgba = (uint8_t*)pic->argb;
output_buffer->u.RGBA.stride = pic->argb_stride * sizeof(uint32_t);
output_buffer->u.RGBA.size = output_buffer->u.RGBA.stride * pic->height;
} else { } else {
output_buffer->colorspace = has_alpha ? MODE_YUVA : MODE_YUV; output_buffer->colorspace = has_alpha ? MODE_YUVA : MODE_YUV;
output_buffer->u.YUVA.y = pic->y;
output_buffer->u.YUVA.u = pic->u;
output_buffer->u.YUVA.v = pic->v;
output_buffer->u.YUVA.a = has_alpha ? pic->a : NULL;
output_buffer->u.YUVA.y_stride = pic->y_stride;
output_buffer->u.YUVA.u_stride = pic->uv_stride;
output_buffer->u.YUVA.v_stride = pic->uv_stride;
output_buffer->u.YUVA.a_stride = has_alpha ? pic->a_stride : 0;
output_buffer->u.YUVA.y_size = pic->height * pic->y_stride;
output_buffer->u.YUVA.u_size = (pic->height + 1) / 2 * pic->uv_stride;
output_buffer->u.YUVA.v_size = (pic->height + 1) / 2 * pic->uv_stride;
output_buffer->u.YUVA.a_size = pic->height * pic->a_stride;
} }
output_buffer->is_external_memory = 1;
status = DecodeWebP(data, data_size, &config); status = DecodeWebP(data, data_size, &config);
ok = (status == VP8_STATUS_OK); if (status == VP8_STATUS_OK) {
if (ok && !keep_alpha && pic->use_argb) { pic->width = output_buffer->width;
// Need to wipe out the alpha value, as requested. pic->height = output_buffer->height;
int x, y; if (pic->use_argb) {
uint32_t* argb = pic->argb; const uint8_t* const rgba = output_buffer->u.RGBA.rgba;
for (y = 0; y < pic->height; ++y) { const int stride = output_buffer->u.RGBA.stride;
for (x = 0; x < pic->width; ++x) argb[x] |= 0xff000000u; ok = has_alpha ? WebPPictureImportRGBA(pic, rgba, stride)
argb += pic->argb_stride; : WebPPictureImportRGB(pic, rgba, stride);
} else {
pic->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420;
ok = WebPPictureAlloc(pic);
if (!ok) {
status = VP8_STATUS_OUT_OF_MEMORY;
} else {
const WebPYUVABuffer* const yuva = &output_buffer->u.YUVA;
const int uv_width = (pic->width + 1) >> 1;
const int uv_height = (pic->height + 1) >> 1;
ImgIoUtilCopyPlane(yuva->y, yuva->y_stride,
pic->y, pic->y_stride, pic->width, pic->height);
ImgIoUtilCopyPlane(yuva->u, yuva->u_stride,
pic->u, pic->uv_stride, uv_width, uv_height);
ImgIoUtilCopyPlane(yuva->v, yuva->v_stride,
pic->v, pic->uv_stride, uv_width, uv_height);
if (has_alpha) {
ImgIoUtilCopyPlane(yuva->a, yuva->a_stride,
pic->a, pic->a_stride, pic->width, pic->height);
}
}
} }
} }
} while (0); // <- so we can 'break' out of the loop }
if (status != VP8_STATUS_OK) { if (status != VP8_STATUS_OK) {
PrintWebPError("input data", status); PrintWebPError("input data", status);
ok = 0;
} }
WebPFreeDecBuffer(output_buffer); 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; return ok;
} }

View File

@ -51,7 +51,7 @@ VP8StatusCode DecodeWebPIncremental(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Decodes a WebP contained in 'data', returning the decoded output in 'pic'. // Reads a WebP from 'in_file', returning the decoded output in 'pic'.
// Output is RGBA or YUVA, depending on pic->use_argb value. // Output is RGBA or YUVA, depending on pic->use_argb value.
// If 'keep_alpha' is true and the WebP has an alpha channel, the output is RGBA // If 'keep_alpha' is true and the WebP has an alpha channel, the output is RGBA
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV. // or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.

View File

@ -29,14 +29,12 @@
// code with COBJMACROS. // code with COBJMACROS.
#include <ole2.h> // CreateStreamOnHGlobal() #include <ole2.h> // CreateStreamOnHGlobal()
#include <shlwapi.h> #include <shlwapi.h>
#include <tchar.h>
#include <windows.h> #include <windows.h>
#include <wincodec.h> #include <wincodec.h>
#include "../examples/unicode.h" #include "webp/encode.h"
#include "./imageio_util.h" #include "./imageio_util.h"
#include "./metadata.h" #include "./metadata.h"
#include "webp/encode.h"
#define IFS(fn) \ #define IFS(fn) \
do { \ do { \
@ -87,7 +85,7 @@ WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppRGBA_,
static HRESULT OpenInputStream(const char* filename, IStream** stream) { static HRESULT OpenInputStream(const char* filename, IStream** stream) {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (!WSTRCMP(filename, "-")) { if (!strcmp(filename, "-")) {
const uint8_t* data = NULL; const uint8_t* data = NULL;
size_t data_size = 0; size_t data_size = 0;
const int ok = ImgIoUtilReadFile(filename, &data, &data_size); const int ok = ImgIoUtilReadFile(filename, &data, &data_size);
@ -110,12 +108,11 @@ static HRESULT OpenInputStream(const char* filename, IStream** stream) {
hr = E_FAIL; hr = E_FAIL;
} }
} else { } else {
IFS(SHCreateStreamOnFile((const LPTSTR)filename, STGM_READ, stream)); IFS(SHCreateStreamOnFileA(filename, STGM_READ, stream));
} }
if (FAILED(hr)) { if (FAILED(hr)) {
_ftprintf(stderr, _T("Error opening input file %s (%08lx)\n"), fprintf(stderr, "Error opening input file %s (%08lx)\n", filename, hr);
(const LPTSTR)filename, hr);
} }
return hr; return hr;
} }
@ -298,15 +295,9 @@ int ReadPictureWithWIC(const char* const filename,
factory, stream, NULL, factory, stream, NULL,
WICDecodeMetadataCacheOnDemand, &decoder)); WICDecodeMetadataCacheOnDemand, &decoder));
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count)); IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr) && frame_count == 0) {
if (frame_count == 0) { fprintf(stderr, "No frame found in input file.\n");
fprintf(stderr, "No frame found in input file.\n"); hr = E_FAIL;
hr = E_FAIL;
} else if (frame_count > 1) {
// WIC will be tried before native WebP decoding so avoid duplicating the
// error message.
hr = E_FAIL;
}
} }
IFS(IWICBitmapDecoder_GetFrame(decoder, 0, &frame)); IFS(IWICBitmapDecoder_GetFrame(decoder, 0, &frame));
IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format)); IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format));

View File

@ -1,9 +1,8 @@
#!/bin/bash #!/bin/bash
# #
# This script generates 'WebP.framework' and 'WebPDecoder.framework', # This script generates 'WebP.framework' and 'WebPDecoder.framework'. An iOS
# 'WebPDemux.framework' and 'WebPMux.framework'. # app can decode WebP images by including 'WebPDecoder.framework' and both
# An iOS app can decode WebP images by including 'WebPDecoder.framework' and # encode and decode WebP images by including 'WebP.framework'.
# both encode and decode WebP images by including 'WebP.framework'.
# #
# Run ./iosbuild.sh to generate the frameworks under the current directory # Run ./iosbuild.sh to generate the frameworks under the current directory
# (the previous build will be erased if it exists). # (the previous build will be erased if it exists).
@ -13,9 +12,6 @@
set -e set -e
# Set this variable based on the desired minimum deployment target.
readonly IOS_MIN_VERSION=6.0
# Extract the latest SDK version from the final field of the form: iphoneosX.Y # Extract the latest SDK version from the final field of the form: iphoneosX.Y
readonly SDK=$(xcodebuild -showsdks \ readonly SDK=$(xcodebuild -showsdks \
| grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}' | grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
@ -39,55 +35,35 @@ readonly TOPDIR=$(pwd)
readonly BUILDDIR="${TOPDIR}/iosbuild" readonly BUILDDIR="${TOPDIR}/iosbuild"
readonly TARGETDIR="${TOPDIR}/WebP.framework" readonly TARGETDIR="${TOPDIR}/WebP.framework"
readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.framework" readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.framework"
readonly MUXTARGETDIR="${TOPDIR}/WebPMux.framework"
readonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.framework"
readonly DEVELOPER=$(xcode-select --print-path) readonly DEVELOPER=$(xcode-select --print-path)
readonly PLATFORMSROOT="${DEVELOPER}/Platforms" readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo) readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
LIBLIST='' LIBLIST=''
DECLIBLIST='' DECLIBLIST=''
MUXLIBLIST=''
DEMUXLIBLIST=''
if [[ -z "${SDK}" ]]; then if [[ -z "${SDK}" ]]; then
echo "iOS SDK not available" echo "iOS SDK not available"
exit 1 exit 1
elif [[ ${SDK%%.*} -gt 8 ]]; then elif [[ ${SDK%%.*} -gt 8 ]]; then
EXTRA_CFLAGS="-fembed-bitcode" EXTRA_CFLAGS="-fembed-bitcode"
elif [[ ${SDK%%.*} -le 6 ]]; then elif [[ ${SDK} < 6.0 ]]; then
echo "You need iOS SDK version 6.0 or above" echo "You need iOS SDK version 6.0 or above"
exit 1 exit 1
else
echo "iOS SDK Version ${SDK}"
fi fi
echo "Xcode Version: ${XCODE}" rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR}
echo "iOS SDK Version: ${SDK}" mkdir -p ${BUILDDIR} ${TARGETDIR}/Headers/ ${DECTARGETDIR}/Headers/
if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \
|| -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" ]]; then
cat << EOF
WARNING: The following directories will be deleted:
WARNING: ${BUILDDIR}
WARNING: ${TARGETDIR}
WARNING: ${DECTARGETDIR}
WARNING: ${MUXTARGETDIR}
WARNING: ${DEMUXTARGETDIR}
WARNING: The build will continue in 5 seconds...
EOF
sleep 5
fi
rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \
${MUXTARGETDIR} ${DEMUXTARGETDIR}
mkdir -p ${BUILDDIR} ${TARGETDIR}/Headers/ ${DECTARGETDIR}/Headers/ \
${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/
if [[ ! -e ${SRCDIR}/configure ]]; then if [[ ! -e ${SRCDIR}/configure ]]; then
if ! (cd ${SRCDIR} && sh autogen.sh); then if ! (cd ${SRCDIR} && sh autogen.sh); then
cat << EOF cat <<EOT
Error creating configure script! Error creating configure script!
This script requires the autoconf/automake and libtool to build. MacPorts can This script requires the autoconf/automake and libtool to build. MacPorts can
be used to obtain these: be used to obtain these:
http://www.macports.org/install.php http://www.macports.org/install.php
EOF EOT
exit 1 exit 1
fi fi
fi fi
@ -121,7 +97,7 @@ for PLATFORM in ${PLATFORMS}; do
SDKROOT="${PLATFORMSROOT}/" SDKROOT="${PLATFORMSROOT}/"
SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/" SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG" CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
CFLAGS+=" -miphoneos-version-min=${IOS_MIN_VERSION} ${EXTRA_CFLAGS}" CFLAGS+=" -miphoneos-version-min=6.0 ${EXTRA_CFLAGS}"
set -x set -x
export PATH="${DEVROOT}/usr/bin:${OLDPATH}" export PATH="${DEVROOT}/usr/bin:${OLDPATH}"
@ -129,7 +105,6 @@ for PLATFORM in ${PLATFORMS}; do
--build=$(${SRCDIR}/config.guess) \ --build=$(${SRCDIR}/config.guess) \
--disable-shared --enable-static \ --disable-shared --enable-static \
--enable-libwebpdecoder --enable-swap-16bit-csp \ --enable-libwebpdecoder --enable-swap-16bit-csp \
--enable-libwebpmux \
CFLAGS="${CFLAGS}" CFLAGS="${CFLAGS}"
set +x set +x
@ -140,8 +115,6 @@ for PLATFORM in ${PLATFORMS}; do
LIBLIST+=" ${ROOTDIR}/lib/libwebp.a" LIBLIST+=" ${ROOTDIR}/lib/libwebp.a"
DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a" DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a"
MUXLIBLIST+=" ${ROOTDIR}/lib/libwebpmux.a"
DEMUXLIBLIST+=" ${ROOTDIR}/lib/libwebpdemux.a"
make clean make clean
cd .. cd ..
@ -149,22 +122,8 @@ for PLATFORM in ${PLATFORMS}; do
export PATH=${OLDPATH} export PATH=${OLDPATH}
done done
echo "LIBLIST = ${LIBLIST}"
cp -a ${SRCDIR}/src/webp/{decode,encode,types}.h ${TARGETDIR}/Headers/ cp -a ${SRCDIR}/src/webp/{decode,encode,types}.h ${TARGETDIR}/Headers/
${LIPO} -create ${LIBLIST} -output ${TARGETDIR}/WebP ${LIPO} -create ${LIBLIST} -output ${TARGETDIR}/WebP
echo "DECLIBLIST = ${DECLIBLIST}"
cp -a ${SRCDIR}/src/webp/{decode,types}.h ${DECTARGETDIR}/Headers/ cp -a ${SRCDIR}/src/webp/{decode,types}.h ${DECTARGETDIR}/Headers/
${LIPO} -create ${DECLIBLIST} -output ${DECTARGETDIR}/WebPDecoder ${LIPO} -create ${DECLIBLIST} -output ${DECTARGETDIR}/WebPDecoder
echo "MUXLIBLIST = ${MUXLIBLIST}"
cp -a ${SRCDIR}/src/webp/{types,mux,mux_types}.h \
${MUXTARGETDIR}/Headers/
${LIPO} -create ${MUXLIBLIST} -output ${MUXTARGETDIR}/WebPMux
echo "DEMUXLIBLIST = ${DEMUXLIBLIST}"
cp -a ${SRCDIR}/src/webp/{decode,types,mux_types,demux}.h \
${DEMUXTARGETDIR}/Headers/
${LIPO} -create ${DEMUXLIBLIST} -output ${DEMUXTARGETDIR}/WebPDemux
echo "SUCCESS"

View File

@ -25,26 +25,13 @@ ifeq ($(strip $(shell uname)), Darwin)
# Failure observed with: gcc 4.2.1 and 4.0.1. # Failure observed with: gcc 4.2.1 and 4.0.1.
EXTRA_FLAGS += -fno-common EXTRA_FLAGS += -fno-common
EXTRA_FLAGS += -DHAVE_GLUT_GLUT_H EXTRA_FLAGS += -DHAVE_GLUT_GLUT_H
EXTRA_FLAGS += -Wno-deprecated-declarations
EXTRA_FLAGS += -I/opt/local/include EXTRA_FLAGS += -I/opt/local/include
EXTRA_LIBS += -L/opt/local/lib EXTRA_LIBS += -L/opt/local/lib
GL_LIBS = -framework GLUT -framework OpenGL GL_LIBS = -framework GLUT -framework OpenGL
else else
EXTRA_FLAGS += -I/usr/local/include
EXTRA_LIBS += -L/usr/local/lib
GL_LIBS = -lglut -lGL GL_LIBS = -lglut -lGL
endif endif
# SDL flags: use sdl-config if it exists
SDL_CONFIG = $(shell sdl-config --version 2> /dev/null)
ifneq ($(SDL_CONFIG),)
SDL_LIBS = $(shell sdl-config --libs)
SDL_FLAGS = $(shell sdl-config --cflags)
else
# use best-guess
SDL_LIBS = -lSDL
SDL_FLAGS =
endif
# To install libraries on Mac OS X: # To install libraries on Mac OS X:
# 1. Install MacPorts (http://www.macports.org/install.php) # 1. Install MacPorts (http://www.macports.org/install.php)
@ -64,8 +51,11 @@ endif
# 'make -f makefile.unix EXTRA_FLAGS=-m32' to that effect. # 'make -f makefile.unix EXTRA_FLAGS=-m32' to that effect.
# EXTRA_FLAGS += -m32 # EXTRA_FLAGS += -m32
# Extra flags to enable experimental features and code
# EXTRA_FLAGS += -DWEBP_EXPERIMENTAL_FEATURES
# Extra flags to enable byte swap for 16 bit colorspaces. # Extra flags to enable byte swap for 16 bit colorspaces.
# EXTRA_FLAGS += -DWEBP_SWAP_16BIT_CSP=1 # EXTRA_FLAGS += -DWEBP_SWAP_16BIT_CSP
# Extra flags to enable multi-threading # Extra flags to enable multi-threading
EXTRA_FLAGS += -DWEBP_USE_THREAD EXTRA_FLAGS += -DWEBP_USE_THREAD
@ -89,6 +79,12 @@ EXTRA_FLAGS += -DWEBP_HAVE_SSE41
src/dsp/%_sse41.o: EXTRA_FLAGS += -msse4.1 src/dsp/%_sse41.o: EXTRA_FLAGS += -msse4.1
endif endif
# AVX2-specific flags:
ifeq ($(HAVE_AVX2), 1)
EXTRA_FLAGS += -DWEBP_HAVE_AVX2
src/dsp/%_avx2.o: EXTRA_FLAGS += -mavx2
endif
# NEON-specific flags: # NEON-specific flags:
# EXTRA_FLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8 # EXTRA_FLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8
# -> seems to make the overall lib slower: -fno-split-wide-types # -> seems to make the overall lib slower: -fno-split-wide-types
@ -105,23 +101,14 @@ endif
AR = ar AR = ar
ARFLAGS = r ARFLAGS = r
CPPFLAGS = -I. -Isrc/ -Wall CPPFLAGS = -Isrc/ -Wall
ifeq ($(DEBUG), 1) CFLAGS = -O3 -DNDEBUG $(EXTRA_FLAGS)
CFLAGS = -g
else
CFLAGS = -O3 -DNDEBUG
endif
CFLAGS += $(EXTRA_FLAGS)
CC = gcc CC = gcc
INSTALL = install INSTALL = install
GROFF = /usr/bin/groff GROFF = /usr/bin/groff
COL = /usr/bin/col COL = /usr/bin/col
LDFLAGS = $(EXTRA_LIBS) $(EXTRA_FLAGS) -lm LDFLAGS = $(EXTRA_LIBS) $(EXTRA_FLAGS) -lm
ifdef BITTRACE
CFLAGS += -DBITTRACE=$(BITTRACE)
endif
ANIM_UTIL_OBJS = \ ANIM_UTIL_OBJS = \
examples/anim_util.o \ examples/anim_util.o \
@ -177,21 +164,21 @@ DSP_DEC_OBJS = \
src/dsp/upsampling_msa.o \ src/dsp/upsampling_msa.o \
src/dsp/upsampling_neon.o \ src/dsp/upsampling_neon.o \
src/dsp/upsampling_sse2.o \ src/dsp/upsampling_sse2.o \
src/dsp/upsampling_sse41.o \
src/dsp/yuv.o \ src/dsp/yuv.o \
src/dsp/yuv_mips32.o \ src/dsp/yuv_mips32.o \
src/dsp/yuv_mips_dsp_r2.o \ src/dsp/yuv_mips_dsp_r2.o \
src/dsp/yuv_neon.o \
src/dsp/yuv_sse2.o \ src/dsp/yuv_sse2.o \
src/dsp/yuv_sse41.o \
DSP_ENC_OBJS = \ DSP_ENC_OBJS = \
src/dsp/argb.o \
src/dsp/argb_mips_dsp_r2.o \
src/dsp/argb_sse2.o \
src/dsp/cost.o \ src/dsp/cost.o \
src/dsp/cost_mips32.o \ src/dsp/cost_mips32.o \
src/dsp/cost_mips_dsp_r2.o \ src/dsp/cost_mips_dsp_r2.o \
src/dsp/cost_neon.o \
src/dsp/cost_sse2.o \ src/dsp/cost_sse2.o \
src/dsp/enc.o \ src/dsp/enc.o \
src/dsp/enc_avx2.o \
src/dsp/enc_mips32.o \ src/dsp/enc_mips32.o \
src/dsp/enc_mips_dsp_r2.o \ src/dsp/enc_mips_dsp_r2.o \
src/dsp/enc_msa.o \ src/dsp/enc_msa.o \
@ -205,16 +192,14 @@ DSP_ENC_OBJS = \
src/dsp/lossless_enc_neon.o \ src/dsp/lossless_enc_neon.o \
src/dsp/lossless_enc_sse2.o \ src/dsp/lossless_enc_sse2.o \
src/dsp/lossless_enc_sse41.o \ src/dsp/lossless_enc_sse41.o \
src/dsp/ssim.o \
src/dsp/ssim_sse2.o \
ENC_OBJS = \ ENC_OBJS = \
src/enc/alpha_enc.o \ src/enc/alpha_enc.o \
src/enc/analysis_enc.o \ src/enc/analysis_enc.o \
src/enc/backward_references_cost_enc.o \
src/enc/backward_references_enc.o \ src/enc/backward_references_enc.o \
src/enc/config_enc.o \ src/enc/config_enc.o \
src/enc/cost_enc.o \ src/enc/cost_enc.o \
src/enc/delta_palettization_enc.o \
src/enc/filter_enc.o \ src/enc/filter_enc.o \
src/enc/frame_enc.o \ src/enc/frame_enc.o \
src/enc/histogram_enc.o \ src/enc/histogram_enc.o \
@ -238,7 +223,6 @@ EX_FORMAT_DEC_OBJS = \
imageio/jpegdec.o \ imageio/jpegdec.o \
imageio/metadata.o \ imageio/metadata.o \
imageio/pngdec.o \ imageio/pngdec.o \
imageio/pnmdec.o \
imageio/tiffdec.o \ imageio/tiffdec.o \
imageio/webpdec.o \ imageio/webpdec.o \
@ -312,6 +296,7 @@ HDRS = \
src/dsp/yuv.h \ src/dsp/yuv.h \
src/enc/backward_references_enc.h \ src/enc/backward_references_enc.h \
src/enc/cost_enc.h \ src/enc/cost_enc.h \
src/enc/delta_palettization_enc.h \
src/enc/histogram_enc.h \ src/enc/histogram_enc.h \
src/enc/vp8i_enc.h \ src/enc/vp8i_enc.h \
src/enc/vp8li_enc.h \ src/enc/vp8li_enc.h \
@ -343,9 +328,8 @@ OUT_LIBS += src/libwebp.a
EXTRA_LIB = extras/libwebpextras.a EXTRA_LIB = extras/libwebpextras.a
OUT_EXAMPLES = examples/cwebp examples/dwebp OUT_EXAMPLES = examples/cwebp examples/dwebp
EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux \ EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux \
examples/anim_diff examples/anim_dump \ examples/anim_diff examples/img2webp
examples/img2webp examples/webpinfo OTHER_EXAMPLES = extras/get_disto extras/webp_quality
OTHER_EXAMPLES = extras/get_disto extras/webp_quality extras/vwebp_sdl
OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES) OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES)
ifeq ($(MAKECMDGOALS),clean) ifeq ($(MAKECMDGOALS),clean)
@ -372,7 +356,7 @@ src/utils/bit_reader_utils.o: src/utils/endian_inl_utils.h
src/utils/bit_writer_utils.o: src/utils/endian_inl_utils.h src/utils/bit_writer_utils.o: src/utils/endian_inl_utils.h
%.o: %.c $(HDRS) %.o: %.c $(HDRS)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
examples/libanim_util.a: $(ANIM_UTIL_OBJS) examples/libanim_util.a: $(ANIM_UTIL_OBJS)
examples/libexample_util.a: $(EX_UTIL_OBJS) examples/libexample_util.a: $(EX_UTIL_OBJS)
@ -390,76 +374,52 @@ src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS)
$(AR) $(ARFLAGS) $@ $^ $(AR) $(ARFLAGS) $@ $^
examples/anim_diff: examples/anim_diff.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS) examples/anim_diff: examples/anim_diff.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS)
examples/anim_dump: examples/anim_dump.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS)
examples/cwebp: examples/cwebp.o examples/cwebp: examples/cwebp.o
examples/dwebp: examples/dwebp.o examples/dwebp: examples/dwebp.o
examples/gif2webp: examples/gif2webp.o $(GIFDEC_OBJS) examples/gif2webp: examples/gif2webp.o $(GIFDEC_OBJS)
examples/vwebp: examples/vwebp.o examples/vwebp: examples/vwebp.o
examples/webpmux: examples/webpmux.o examples/webpmux: examples/webpmux.o
examples/img2webp: examples/img2webp.o examples/img2webp: examples/img2webp.o
examples/webpinfo: examples/webpinfo.o
examples/anim_diff: examples/libanim_util.a examples/libgifdec.a examples/anim_diff: examples/libanim_util.a examples/libgifdec.a
examples/anim_diff: src/demux/libwebpdemux.a examples/libexample_util.a examples/anim_diff: src/demux/libwebpdemux.a examples/libexample_util.a
examples/anim_diff: imageio/libimageio_util.a src/libwebp.a examples/anim_diff: imageio/libimageio_util.a src/libwebp.a
examples/anim_diff: override EXTRA_LIBS += $(GIF_LIBS) examples/anim_diff: EXTRA_LIBS += $(GIF_LIBS)
examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF
examples/anim_dump: examples/libanim_util.a examples/libgifdec.a
examples/anim_dump: src/demux/libwebpdemux.a
examples/anim_dump: examples/libexample_util.a
examples/anim_dump: imageio/libimageio_util.a
examples/anim_dump: imageio/libimageenc.a
examples/anim_dump: src/libwebp.a
examples/anim_dump: override EXTRA_LIBS += $(GIF_LIBS) $(DWEBP_LIBS)
examples/cwebp: examples/libexample_util.a examples/cwebp: examples/libexample_util.a
examples/cwebp: imageio/libimagedec.a examples/cwebp: imageio/libimagedec.a
examples/cwebp: src/demux/libwebpdemux.a
examples/cwebp: imageio/libimageio_util.a examples/cwebp: imageio/libimageio_util.a
examples/cwebp: src/libwebp.a examples/cwebp: src/libwebp.a
examples/cwebp: override EXTRA_LIBS += $(CWEBP_LIBS) examples/cwebp: EXTRA_LIBS += $(CWEBP_LIBS)
examples/dwebp: examples/libexample_util.a examples/dwebp: examples/libexample_util.a
examples/dwebp: imageio/libimagedec.a examples/dwebp: imageio/libimagedec.a
examples/dwebp: src/demux/libwebpdemux.a
examples/dwebp: imageio/libimageenc.a examples/dwebp: imageio/libimageenc.a
examples/dwebp: imageio/libimageio_util.a examples/dwebp: imageio/libimageio_util.a
examples/dwebp: src/libwebp.a examples/dwebp: src/libwebp.a
examples/dwebp: override EXTRA_LIBS += $(DWEBP_LIBS) examples/dwebp: EXTRA_LIBS += $(DWEBP_LIBS)
examples/gif2webp: examples/libexample_util.a imageio/libimageio_util.a examples/gif2webp: examples/libexample_util.a imageio/libimageio_util.a
examples/gif2webp: examples/libgifdec.a src/mux/libwebpmux.a src/libwebp.a examples/gif2webp: examples/libgifdec.a src/mux/libwebpmux.a src/libwebp.a
examples/gif2webp: override EXTRA_LIBS += $(GIF_LIBS) examples/gif2webp: EXTRA_LIBS += $(GIF_LIBS)
examples/gif2webp: EXTRA_FLAGS += -DWEBP_HAVE_GIF examples/gif2webp: EXTRA_FLAGS += -DWEBP_HAVE_GIF
examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a
examples/vwebp: imageio/libimageio_util.a src/libwebp.a examples/vwebp: imageio/libimageio_util.a src/libwebp.a
examples/vwebp: override EXTRA_LIBS += $(GL_LIBS) examples/vwebp: EXTRA_LIBS += $(GL_LIBS)
examples/vwebp: EXTRA_FLAGS += -DWEBP_HAVE_GL examples/vwebp: EXTRA_FLAGS += -DWEBP_HAVE_GL
examples/webpmux: examples/libexample_util.a imageio/libimageio_util.a examples/webpmux: examples/libexample_util.a imageio/libimageio_util.a
examples/webpmux: src/mux/libwebpmux.a src/libwebpdecoder.a examples/webpmux: src/mux/libwebpmux.a src/libwebpdecoder.a
examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a
examples/img2webp: imageio/libimagedec.a examples/img2webp: imageio/libimagedec.a
examples/img2webp: src/demux/libwebpdemux.a
examples/img2webp: src/mux/libwebpmux.a src/libwebp.a examples/img2webp: src/mux/libwebpmux.a src/libwebp.a
examples/img2webp: override EXTRA_LIBS += $(CWEBP_LIBS) 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: extras/get_disto.o
extras/get_disto: imageio/libimagedec.a extras/get_disto: imageio/libimagedec.a imageio/libimageio_util.a src/libwebp.a
extras/get_disto: src/demux/libwebpdemux.a extras/get_disto: EXTRA_LIBS += $(CWEBP_LIBS)
extras/get_disto: imageio/libimageio_util.a
extras/get_disto: src/libwebp.a
extras/get_disto: override EXTRA_LIBS += $(CWEBP_LIBS)
extras/webp_quality: extras/webp_quality.o extras/webp_quality: extras/webp_quality.o
extras/webp_quality: imageio/libimageio_util.a extras/webp_quality: imageio/libimageio_util.a
extras/webp_quality: $(EXTRA_LIB) src/libwebp.a extras/webp_quality: $(EXTRA_LIB) src/libwebp.a
extras/vwebp_sdl: extras/vwebp_sdl.o
extras/vwebp_sdl: extras/webp_to_sdl.o
extras/vwebp_sdl: imageio/libimageio_util.a
extras/vwebp_sdl: src/libwebp.a
extras/vwebp_sdl: EXTRA_FLAGS += -DWEBP_HAVE_SDL $(SDL_FLAGS)
extras/vwebp_sdl: override EXTRA_LIBS += $(SDL_LIBS)
$(OUT_EXAMPLES) $(EXTRA_EXAMPLES) $(OTHER_EXAMPLES): $(OUT_EXAMPLES) $(EXTRA_EXAMPLES) $(OTHER_EXAMPLES):
$(CC) -o $@ $^ $(LDFLAGS) $(CC) -o $@ $^ $(LDFLAGS)
@ -475,9 +435,9 @@ dist: all
$(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib $(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib
umask 022; \ umask 022; \
for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1 \ for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1 \
man/img2webp.1 man/webpinfo.1; do \ man/img2webp.1; do \
basenam=$$(basename $$m .1); \ basenam=$$(basename $$m .1); \
$(GROFF) -t -e -man -T ascii $$m \ $(GROFF) -t -e -man -T utf8 $$m \
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \ | $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \
$(GROFF) -t -e -man -T html $$m \ $(GROFF) -t -e -man -T html $$m \
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.html; \ | $(COL) -bx >$(DESTDIR)/doc/$${basenam}.html; \

View File

@ -1,17 +1,11 @@
man_MANS = cwebp.1 dwebp.1 man_MANS = cwebp.1 dwebp.1
if BUILD_MUX if WANT_MUX
man_MANS += webpmux.1 man_MANS += webpmux.1
endif endif
if BUILD_GIF2WEBP if BUILD_GIF2WEBP
man_MANS += gif2webp.1 man_MANS += gif2webp.1
endif endif
if BUILD_IMG2WEBP
man_MANS += img2webp.1
endif
if BUILD_VWEBP if BUILD_VWEBP
man_MANS += vwebp.1 man_MANS += vwebp.1
endif endif
if BUILD_WEBPINFO
man_MANS += webpinfo.1
endif
EXTRA_DIST = $(man_MANS) EXTRA_DIST = $(man_MANS)

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH CWEBP 1 "November 19, 2020" .TH CWEBP 1 "January 20, 2017"
.SH NAME .SH NAME
cwebp \- compress an image file to a WebP file cwebp \- compress an image file to a WebP file
.SH SYNOPSIS .SH SYNOPSIS
@ -13,7 +13,6 @@ command.
.PP .PP
\fBcwebp\fP compresses an image using the WebP format. \fBcwebp\fP compresses an image using the WebP format.
Input format can be either PNG, JPEG, TIFF, WebP or raw Y'CbCr samples. Input format can be either PNG, JPEG, TIFF, WebP or raw Y'CbCr samples.
Note: Animated PNG and WebP files are not supported.
.SH OPTIONS .SH OPTIONS
The basic options are: The basic options are:
.TP .TP
@ -42,12 +41,10 @@ the invisible pixel values (R/G/B or Y/U/V) will be preserved only if the
\-exact option is used. \-exact option is used.
.TP .TP
.BI \-near_lossless " int .BI \-near_lossless " int
Specify the level of near\-lossless image preprocessing. This option adjusts Use near\-lossless image preprocessing. This option adjusts pixel values
pixel values to help compressibility, but has minimal impact on the visual to help compressibility, but has minimal impact on the visual quality.
quality. It triggers lossless compression mode automatically. The range is 0 It triggers lossless compression mode automatically.
(maximum preprocessing) to 100 (no preprocessing, the default). The typical Range is 0 (maximum preprocessing) to 100 (no preprocessing, the default).
value is around 60. Note that lossy with \fB\-q 100\fP can at times yield
better results.
.TP .TP
.BI \-q " float .BI \-q " float
Specify the compression factor for RGB channels between 0 and 100. The default Specify the compression factor for RGB channels between 0 and 100. The default
@ -101,7 +98,8 @@ Crop the source to a rectangle with top\-left corner at coordinates
This cropping area must be fully contained within the source rectangle. This cropping area must be fully contained within the source rectangle.
.TP .TP
.B \-mt .B \-mt
Use multi\-threading for encoding, if possible. Use multi\-threading for encoding, if possible. This option is only effective
when using lossy compression on a source with a transparency channel.
.TP .TP
.B \-low_memory .B \-low_memory
Reduce memory usage of lossy encoding by saving four times the compressed Reduce memory usage of lossy encoding by saving four times the compressed
@ -135,13 +133,6 @@ options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10, default is 1.
If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't
specified, a default value of '6' passes will be used. specified, a default value of '6' passes will be used.
.TP .TP
.BI \-qrange " int int
Specifies the permissible interval for the quality factor. This is particularly
useful when using multi-pass (\fB\-size\fP or \fB\-psnr\fP options).
Default is 0 100.
If the quality factor is outside this range, it will be clamped.
If the minimum value must be less or equal to the maximum one.
.TP
.B \-af .B \-af
Turns auto\-filter on. This algorithm will spend additional time optimizing Turns auto\-filter on. This algorithm will spend additional time optimizing
the filtering strength to reach a well\-balanced quality. the filtering strength to reach a well\-balanced quality.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH DWEBP 1 "November 19, 2020" .TH DWEBP 1 "June 23, 2016"
.SH NAME .SH NAME
dwebp \- decompress a WebP file to an image file dwebp \- decompress a WebP file to an image file
.SH SYNOPSIS .SH SYNOPSIS
@ -12,7 +12,6 @@ This manual page documents the
command. command.
.PP .PP
\fBdwebp\fP decompresses WebP files into PNG, PAM, PPM or PGM images. \fBdwebp\fP decompresses WebP files into PNG, PAM, PPM or PGM images.
Note: Animated WebP files are not supported.
.SH OPTIONS .SH OPTIONS
The basic options are: The basic options are:
.TP .TP

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH GIF2WEBP 1 "May 1, 2020" .TH GIF2WEBP 1 "January 25, 2017"
.SH NAME .SH NAME
gif2webp \- Convert a GIF image to WebP gif2webp \- Convert a GIF image to WebP
.SH SYNOPSIS .SH SYNOPSIS
@ -20,12 +20,6 @@ Specify the name of the output WebP file. If omitted, \fBgif2webp\fP will
perform conversion but only report statistics. perform conversion but only report statistics.
Using "\-" as output name will direct output to 'stdout'. Using "\-" as output name will direct output to 'stdout'.
.TP .TP
.BI \-\- " string
Explicitly specify the input file. This option is useful if the input
file starts with an '\-' for instance. This option must appear \fBlast\fP.
Any other options afterward will be ignored. If the input file is "\-",
the data will be read from \fIstdin\fP instead of a file.
.TP
.B \-h, \-help .B \-h, \-help
Usage information. Usage information.
.TP .TP
@ -62,9 +56,9 @@ larger file size and lower compression quality.
.TP .TP
.BI \-min_size .BI \-min_size
Encode image to achieve smallest size. This disables key frame insertion and Encode image to achieve smallest size. This disables key frame insertion and
picks the dispose method resulting in the smallest output for each frame. It picks the dispose method resulting in smallest output for each frame. It uses
uses lossless compression by default, but can be combined with \-q, \-m, lossless compression by default, but can be combined with \-q, \-m, \-lossy or
\-lossy or \-mixed options. \-mixed options.
.TP .TP
.BI \-kmin " int .BI \-kmin " int
.TP .TP
@ -114,11 +108,8 @@ the value the smoother the picture will appear. Typical values are usually in
the range of 20 to 50. the range of 20 to 50.
.TP .TP
.B \-mt .B \-mt
Use multi-threading for encoding, if possible. Use multi-threading for encoding, if possible. This option is only effective
.TP when using lossy compression.
.B \-loop_compatibility
If enabled, handle the loop information in a compatible fashion for Chrome
version prior to M62 (inclusive) and Firefox.
.TP .TP
.B \-v .B \-v
Print extra information. Print extra information.
@ -143,8 +134,6 @@ gif2webp \-lossy \-m 3 picture.gif \-o picture_lossy.webp
gif2webp \-lossy \-f 50 picture.gif \-o picture.webp gif2webp \-lossy \-f 50 picture.gif \-o picture.webp
.br .br
gif2webp \-q 70 \-o picture.webp \-\- \-\-\-picture.gif gif2webp \-q 70 \-o picture.webp \-\- \-\-\-picture.gif
.br
cat picture.gif | gif2webp \-o \- \-\- \- > output.webp
.SH AUTHORS .SH AUTHORS
\fBgif2webp\fP is a part of libwebp and was written by the WebP team. \fBgif2webp\fP is a part of libwebp and was written by the WebP team.

View File

@ -1,13 +1,11 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH IMG2WEBP 1 "May 1, 2020" .TH IMG2WEBP 1 "January 23, 2017"
.SH NAME .SH NAME
img2webp \- create animated WebP file from a sequence of input images. img2webp \- create animated WebP file from a sequence of input images.
.SH SYNOPSIS .SH SYNOPSIS
.B img2webp .B img2webp
[file_level_options] [files] [per_frame_options...] [file_level_options] [files] [per_frame_options...]
.br .br
.B img2webp argument_file_name
.br
.SH DESCRIPTION .SH DESCRIPTION
This manual page documents the This manual page documents the
.B img2webp .B img2webp
@ -15,9 +13,6 @@ command.
.PP .PP
\fBimg2webp\fP compresses a sequence of images using the animated WebP format. \fBimg2webp\fP compresses a sequence of images using the animated WebP format.
Input images can either be PNG, JPEG, TIFF or WebP. Input images can either be PNG, JPEG, TIFF or WebP.
If a single file name (not starting with the character '\-') is supplied as
the argument, the command line arguments are actually tokenized from this file.
This allows for easy scripting or using a large number of arguments.
.SH FILE-LEVEL OPTIONS .SH FILE-LEVEL OPTIONS
The file-level options are applied at the beginning of the compression process, The file-level options are applied at the beginning of the compression process,
before the input frames are read. before the input frames are read.
@ -27,7 +22,7 @@ Specify the name of the output WebP file.
.TP .TP
.BI \-min_size .BI \-min_size
Encode images to achieve smallest size. This disables key frame insertion and Encode images to achieve smallest size. This disables key frame insertion and
picks the parameters resulting in the smallest output for each frame. It uses picks the parameters resulting in smallest output for each frame. It uses
lossless compression by default, but can be combined with \-q, \-m, \-lossy or lossless compression by default, but can be combined with \-q, \-m, \-lossy or
\-mixed options. \-mixed options.
.TP .TP
@ -45,17 +40,14 @@ lossy or lossless compression for each frame heuristically. This global
option disables the local option \fB-lossy\fP and \fB-lossless\fP . option disables the local option \fB-lossy\fP and \fB-lossless\fP .
.TP .TP
.BI \-loop " int .BI \-loop " int
Specifies the number of times the animation should loop. Using '0' Specifies the number of times the animation should loop. Using '0' means
means 'loop indefinitely'. 'loop indefinitely'.
.TP .TP
.BI \-v .BI \-v
Be more verbose. Be more verbose.
.TP .TP
.B \-h, \-help .B \-h, \-help
A short usage summary. A short usage summary.
.TP
.B \-version
Print the version numbers of the relevant libraries used.
.SH PER-FRAME OPTIONS .SH PER-FRAME OPTIONS
The per-frame options are applied for the images following as arguments in the The per-frame options are applied for the images following as arguments in the

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH VWEBP 1 "June 5, 2019" .TH VWEBP 1 "November 25, 2016"
.SH NAME .SH NAME
vwebp \- decompress a WebP file and display it in a window vwebp \- decompress a WebP file and display it in a window
.SH SYNOPSIS .SH SYNOPSIS
@ -38,10 +38,6 @@ It helps by smoothing gradients and avoiding banding artifacts. Default: 50.
By default, quantized transparency planes are dithered during decompression, By default, quantized transparency planes are dithered during decompression,
to smooth the gradients. This flag will prevent this dithering. to smooth the gradients. This flag will prevent this dithering.
.TP .TP
.B \-usebgcolor
Fill transparent areas with the bitstream's own background color instead of
checkerboard only. Default is white for non-animated images.
.TP
.B \-mt .B \-mt
Use multi-threading for decoding, if possible. Use multi-threading for decoding, if possible.
.TP .TP
@ -60,9 +56,6 @@ the data will be read from \fIstdin\fP instead of a file.
.B 'c' .B 'c'
Toggle use of color profile. Toggle use of color profile.
.TP .TP
.B 'b'
Toggle display of background color.
.TP
.B 'i' .B 'i'
Overlay file information. Overlay file information.
.TP .TP

View File

@ -1,80 +0,0 @@
.\" Hey, EMACS: -*- nroff -*-
.TH WEBPINFO 1 "November 24, 2017"
.SH NAME
webpinfo \- print out the chunk level structure of WebP files
along with basic integrity checks.
.SH SYNOPSIS
.B webpinfo
.I OPTIONS
.I INPUT
.br
.B webpinfo [\-h|\-help|\-H|\-longhelp]
.br
.SH DESCRIPTION
This manual page documents the
.B webpinfo
command.
.PP
\fBwebpinfo\fP can be used to print out the chunk level structure and bitstream
header information of WebP files. It can also check if the files are of valid
WebP format.
.SH OPTIONS
.TP
.B \-version
Print the version number (as major.minor.revision) and exit.
.TP
.B \-quiet
Do not show chunk parsing information.
.TP
.B \-diag
Show parsing error diagnosis.
.TP
.B \-summary
Show chunk stats summary.
.TP
.BI \-bitstream_info
Parse bitstream header.
.TP
.B \-h, \-help
A short usage summary.
.TP
.B \-H, \-longhelp
Detailed usage instructions.
.SH INPUT
Input files in WebP format. Input files must come last, following
options (if any). There can be multiple input files.
.SH BUGS
Please report all bugs to the issue tracker:
https://bugs.chromium.org/p/webp
.br
Patches welcome! See this page to get started:
http://www.webmproject.org/code/contribute/submitting\-patches/
.SH EXAMPLES
.br
webpinfo \-h
.br
webpinfo \-diag \-summary input_file.webp
.br
webpinfo \-bitstream_info input_file_1.webp input_file_2.webp
.br
webpinfo *.webp
.SH AUTHORS
\fBwebpinfo\fP is a part of libwebp and was written by the WebP team.
.br
The latest source tree is available at
https://chromium.googlesource.com/webm/libwebp
.PP
This manual page was written by Hui Su <huisu@google.com>,
for the Debian project (and may be used by others).
.SH SEE ALSO
.BR webpmux (1)
.br
Please refer to http://developers.google.com/speed/webp/ for additional
information.

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH WEBPMUX 1 "December 12, 2020" .TH WEBPMUX 1 "November 10, 2016"
.SH NAME .SH NAME
webpmux \- create animated WebP files from non\-animated WebP images, extract webpmux \- create animated WebP files from non\-animated WebP images, extract
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile. frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
@ -48,8 +48,6 @@ frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
.B webpmux [\-h|\-help] .B webpmux [\-h|\-help]
.br .br
.B webpmux \-version .B webpmux \-version
.br
.B webpmux argument_file_name
.SH DESCRIPTION .SH DESCRIPTION
This manual page documents the This manual page documents the
.B webpmux .B webpmux
@ -57,9 +55,6 @@ command.
.PP .PP
\fBwebpmux\fP can be used to create/extract from animated WebP files, as well as \fBwebpmux\fP can be used to create/extract from animated WebP files, as well as
to add/extract/strip XMP/EXIF metadata and ICC profile. to add/extract/strip XMP/EXIF metadata and ICC profile.
If a single file name (not starting with the character '\-') is supplied as
the argument, the command line arguments are actually tokenized from this file.
This allows for easy scripting or using a large number of arguments.
.SH OPTIONS .SH OPTIONS
.SS GET_OPTIONS (\-get): .SS GET_OPTIONS (\-get):
.TP .TP
@ -77,11 +72,6 @@ Get nth frame from an animated image. (n = 0 has a special meaning: last frame).
.SS SET_OPTIONS (\-set) .SS SET_OPTIONS (\-set)
.TP .TP
.BI loop " loop_count
Set loop count on an animated file.
.P
Where: 'loop_count' must be in range [0, 65535].
.TP
.BI icc " file.icc .BI icc " file.icc
Set ICC profile. Set ICC profile.
.P .P

View File

@ -1,10 +1,10 @@
# The mux and demux libraries depend on libwebp, thus the '.' to force # The mux and demux libraries depend on libwebp, thus the '.' to force
# the build order so it's available to them. # the build order so it's available to them.
SUBDIRS = dec enc dsp utils . SUBDIRS = dec enc dsp utils .
if BUILD_MUX if WANT_MUX
SUBDIRS += mux SUBDIRS += mux
endif endif
if BUILD_DEMUX if WANT_DEMUX
SUBDIRS += demux SUBDIRS += demux
endif endif
@ -22,7 +22,6 @@ commondir = $(includedir)/webp
libwebp_la_SOURCES = libwebp_la_SOURCES =
libwebpinclude_HEADERS = libwebpinclude_HEADERS =
libwebpinclude_HEADERS += webp/encode.h libwebpinclude_HEADERS += webp/encode.h
noinst_HEADERS = noinst_HEADERS =
noinst_HEADERS += webp/format_constants.h noinst_HEADERS += webp/format_constants.h
@ -36,7 +35,7 @@ libwebp_la_LIBADD += utils/libwebputils.la
# other than the ones listed on the command line, i.e., after linking, it will # other than the ones listed on the command line, i.e., after linking, it will
# not have unresolved symbols. Some platforms (Windows among them) require all # not have unresolved symbols. Some platforms (Windows among them) require all
# symbols in shared libraries to be resolved at library creation. # symbols in shared libraries to be resolved at library creation.
libwebp_la_LDFLAGS = -no-undefined -version-info 8:1:1 libwebp_la_LDFLAGS = -no-undefined -version-info 7:0:0
libwebpincludedir = $(includedir)/webp libwebpincludedir = $(includedir)/webp
pkgconfig_DATA = libwebp.pc pkgconfig_DATA = libwebp.pc
@ -48,7 +47,7 @@ if BUILD_LIBWEBPDECODER
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:1:1 libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 3:0:0
pkgconfig_DATA += libwebpdecoder.pc pkgconfig_DATA += libwebpdecoder.pc
endif endif

View File

@ -1,4 +1,3 @@
AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir)
noinst_LTLIBRARIES = libwebpdecode.la noinst_LTLIBRARIES = libwebpdecode.la
libwebpdecode_la_SOURCES = libwebpdecode_la_SOURCES =
@ -25,5 +24,5 @@ libwebpdecodeinclude_HEADERS += ../webp/types.h
noinst_HEADERS = noinst_HEADERS =
noinst_HEADERS += ../webp/format_constants.h noinst_HEADERS += ../webp/format_constants.h
libwebpdecode_la_CPPFLAGS = $(AM_CPPFLAGS) libwebpdecode_la_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
libwebpdecodeincludedir = $(includedir)/webp libwebpdecodeincludedir = $(includedir)/webp

View File

@ -12,13 +12,13 @@
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include <stdlib.h> #include <stdlib.h>
#include "src/dec/alphai_dec.h" #include "./alphai_dec.h"
#include "src/dec/vp8i_dec.h" #include "./vp8i_dec.h"
#include "src/dec/vp8li_dec.h" #include "./vp8li_dec.h"
#include "src/dsp/dsp.h" #include "../dsp/dsp.h"
#include "src/utils/quant_levels_dec_utils.h" #include "../utils/quant_levels_dec_utils.h"
#include "src/utils/utils.h" #include "../utils/utils.h"
#include "src/webp/format_constants.h" #include "../webp/format_constants.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// ALPHDecoder object. // ALPHDecoder object.

View File

@ -11,11 +11,11 @@
// //
// Author: Urvang (urvang@google.com) // Author: Urvang (urvang@google.com)
#ifndef WEBP_DEC_ALPHAI_DEC_H_ #ifndef WEBP_DEC_ALPHAI_H_
#define WEBP_DEC_ALPHAI_DEC_H_ #define WEBP_DEC_ALPHAI_H_
#include "src/dec/webpi_dec.h" #include "./webpi_dec.h"
#include "src/utils/filters_utils.h" #include "../utils/filters_utils.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -51,4 +51,4 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
} // extern "C" } // extern "C"
#endif #endif
#endif // WEBP_DEC_ALPHAI_DEC_H_ #endif /* WEBP_DEC_ALPHAI_H_ */

View File

@ -13,15 +13,15 @@
#include <stdlib.h> #include <stdlib.h>
#include "src/dec/vp8i_dec.h" #include "./vp8i_dec.h"
#include "src/dec/webpi_dec.h" #include "./webpi_dec.h"
#include "src/utils/utils.h" #include "../utils/utils.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// WebPDecBuffer // WebPDecBuffer
// Number of bytes per pixel for the different color-spaces. // Number of bytes per pixel for the different color-spaces.
static const uint8_t kModeBpp[MODE_LAST] = { static const int kModeBpp[MODE_LAST] = {
3, 4, 3, 4, 4, 2, 2, 3, 4, 3, 4, 4, 2, 2,
4, 4, 4, 2, // pre-multiplied modes 4, 4, 4, 2, // pre-multiplied modes
1, 1 }; 1, 1 };
@ -36,7 +36,7 @@ static int IsValidColorspace(int webp_csp_mode) {
// strictly speaking, the very last (or first, if flipped) row // strictly speaking, the very last (or first, if flipped) row
// doesn't require padding. // doesn't require padding.
#define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \ #define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \
((uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH)) (uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH)
static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
int ok = 1; int ok = 1;
@ -74,8 +74,7 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
} else { // RGB checks } else { // RGB checks
const WebPRGBABuffer* const buf = &buffer->u.RGBA; const WebPRGBABuffer* const buf = &buffer->u.RGBA;
const int stride = abs(buf->stride); const int stride = abs(buf->stride);
const uint64_t size = const uint64_t size = MIN_BUFFER_SIZE(width, height, stride);
MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride);
ok &= (size <= buf->size); ok &= (size <= buf->size);
ok &= (stride >= width * kModeBpp[mode]); ok &= (stride >= width * kModeBpp[mode]);
ok &= (buf->rgba != NULL); ok &= (buf->rgba != NULL);
@ -99,14 +98,9 @@ static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
uint64_t uv_size = 0, a_size = 0, total_size; uint64_t uv_size = 0, a_size = 0, total_size;
// We need memory and it hasn't been allocated yet. // We need memory and it hasn't been allocated yet.
// => initialize output buffer, now that dimensions are known. // => initialize output buffer, now that dimensions are known.
int stride; const int stride = w * kModeBpp[mode];
uint64_t size; const uint64_t size = (uint64_t)stride * h;
if ((uint64_t)w * kModeBpp[mode] >= (1ull << 32)) {
return VP8_STATUS_INVALID_PARAM;
}
stride = w * kModeBpp[mode];
size = (uint64_t)stride * h;
if (!WebPIsRGBMode(mode)) { if (!WebPIsRGBMode(mode)) {
uv_stride = (w + 1) / 2; uv_stride = (w + 1) / 2;
uv_size = (uint64_t)uv_stride * ((h + 1) / 2); uv_size = (uint64_t)uv_stride * ((h + 1) / 2);
@ -175,11 +169,11 @@ VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) {
return VP8_STATUS_OK; return VP8_STATUS_OK;
} }
VP8StatusCode WebPAllocateDecBuffer(int width, int height, VP8StatusCode WebPAllocateDecBuffer(int w, int h,
const WebPDecoderOptions* const options, const WebPDecoderOptions* const options,
WebPDecBuffer* const buffer) { WebPDecBuffer* const out) {
VP8StatusCode status; VP8StatusCode status;
if (buffer == NULL || width <= 0 || height <= 0) { if (out == NULL || w <= 0 || h <= 0) {
return VP8_STATUS_INVALID_PARAM; return VP8_STATUS_INVALID_PARAM;
} }
if (options != NULL) { // First, apply options if there is any. if (options != NULL) { // First, apply options if there is any.
@ -188,39 +182,33 @@ VP8StatusCode WebPAllocateDecBuffer(int width, int height,
const int ch = options->crop_height; const int ch = options->crop_height;
const int x = options->crop_left & ~1; const int x = options->crop_left & ~1;
const int y = options->crop_top & ~1; const int y = options->crop_top & ~1;
if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) {
x + cw > width || y + ch > height) {
return VP8_STATUS_INVALID_PARAM; // out of frame boundary. return VP8_STATUS_INVALID_PARAM; // out of frame boundary.
} }
width = cw; w = cw;
height = ch; h = ch;
} }
if (options->use_scaling) { if (options->use_scaling) {
#if !defined(WEBP_REDUCE_SIZE)
int scaled_width = options->scaled_width; int scaled_width = options->scaled_width;
int scaled_height = options->scaled_height; int scaled_height = options->scaled_height;
if (!WebPRescalerGetScaledDimensions( if (!WebPRescalerGetScaledDimensions(
width, height, &scaled_width, &scaled_height)) { w, h, &scaled_width, &scaled_height)) {
return VP8_STATUS_INVALID_PARAM; return VP8_STATUS_INVALID_PARAM;
} }
width = scaled_width; w = scaled_width;
height = scaled_height; h = scaled_height;
#else
return VP8_STATUS_INVALID_PARAM; // rescaling not supported
#endif
} }
} }
buffer->width = width; out->width = w;
buffer->height = height; out->height = h;
// Then, allocate buffer for real. // Then, allocate buffer for real.
status = AllocateBuffer(buffer); status = AllocateBuffer(out);
if (status != VP8_STATUS_OK) return status; if (status != VP8_STATUS_OK) return status;
// Use the stride trick if vertical flip is needed. // Use the stride trick if vertical flip is needed.
if (options != NULL && options->flip) { if (options != NULL && options->flip) {
status = WebPFlipBuffer(buffer); status = WebPFlipBuffer(out);
} }
return status; return status;
} }

View File

@ -11,8 +11,8 @@
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DEC_COMMON_DEC_H_ #ifndef WEBP_DEC_COMMON_H_
#define WEBP_DEC_COMMON_DEC_H_ #define WEBP_DEC_COMMON_H_
// intra prediction modes // intra prediction modes
enum { B_DC_PRED = 0, // 4x4 modes enum { B_DC_PRED = 0, // 4x4 modes
@ -51,4 +51,4 @@ enum { MB_FEATURE_TREE_PROBS = 3,
NUM_PROBAS = 11 NUM_PROBAS = 11
}; };
#endif // WEBP_DEC_COMMON_DEC_H_ #endif // WEBP_DEC_COMMON_H_

View File

@ -12,13 +12,13 @@
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include <stdlib.h> #include <stdlib.h>
#include "src/dec/vp8i_dec.h" #include "./vp8i_dec.h"
#include "src/utils/utils.h" #include "../utils/utils.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Main reconstruction function. // Main reconstruction function.
static const uint16_t kScan[16] = { static const int kScan[16] = {
0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS,
0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS,
0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS,
@ -320,7 +320,7 @@ static void PrecomputeFilterStrengths(VP8Decoder* const dec) {
#define MIN_DITHER_AMP 4 #define MIN_DITHER_AMP 4
#define DITHER_AMP_TAB_SIZE 12 #define DITHER_AMP_TAB_SIZE 12
static const uint8_t kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = { static const int kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = {
// roughly, it's dqm->uv_mat_[1] // roughly, it's dqm->uv_mat_[1]
8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1 8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1
}; };
@ -338,6 +338,7 @@ void VP8InitDithering(const WebPDecoderOptions* const options,
for (s = 0; s < NUM_MB_SEGMENTS; ++s) { for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
VP8QuantMatrix* const dqm = &dec->dqm_[s]; VP8QuantMatrix* const dqm = &dec->dqm_[s];
if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) { if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) {
// TODO(skal): should we specially dither more for uv_quant_ < 0?
const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_; const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_;
dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3; dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3;
} }
@ -399,9 +400,7 @@ static void DitherRow(VP8Decoder* const dec) {
#define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB #define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB
// Finalize and transmit a complete row. Return false in case of user-abort. // Finalize and transmit a complete row. Return false in case of user-abort.
static int FinishRow(void* arg1, void* arg2) { static int FinishRow(VP8Decoder* const dec, VP8Io* const io) {
VP8Decoder* const dec = (VP8Decoder*)arg1;
VP8Io* const io = (VP8Io*)arg2;
int ok = 1; int ok = 1;
const VP8ThreadContext* const ctx = &dec->thread_ctx_; const VP8ThreadContext* const ctx = &dec->thread_ctx_;
const int cache_id = ctx->id_; const int cache_id = ctx->id_;
@ -449,9 +448,10 @@ static int FinishRow(void* arg1, void* arg2) {
if (y_end > io->crop_bottom) { if (y_end > io->crop_bottom) {
y_end = io->crop_bottom; // make sure we don't overflow on last row. y_end = io->crop_bottom; // make sure we don't overflow on last row.
} }
// If dec->alpha_data_ is not NULL, we have some alpha plane present.
io->a = NULL; io->a = NULL;
if (dec->alpha_data_ != NULL && y_start < y_end) { if (dec->alpha_data_ != NULL && y_start < y_end) {
// TODO(skal): testing presence of alpha with dec->alpha_data_ is not a
// good idea.
io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start); io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start);
if (io->a == NULL) { if (io->a == NULL) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
@ -558,6 +558,7 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
if (io->bypass_filtering) { if (io->bypass_filtering) {
dec->filter_type_ = 0; dec->filter_type_ = 0;
} }
// TODO(skal): filter type / strength / sharpness forcing
// Define the area where we can skip in-loop filtering, in case of cropping. // Define the area where we can skip in-loop filtering, in case of cropping.
// //
@ -568,6 +569,8 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
// Means: there's a dependency chain that goes all the way up to the // Means: there's a dependency chain that goes all the way up to the
// top-left corner of the picture (MB #0). We must filter all the previous // top-left corner of the picture (MB #0). We must filter all the previous
// macroblocks. // macroblocks.
// TODO(skal): add an 'approximate_decoding' option, that won't produce
// a 1:1 bit-exactness for complex filtering?
{ {
const int extra_pixels = kFilterExtraRows[dec->filter_type_]; const int extra_pixels = kFilterExtraRows[dec->filter_type_];
if (dec->filter_type_ == 2) { if (dec->filter_type_ == 2) {
@ -648,7 +651,7 @@ static int InitThreadContext(VP8Decoder* const dec) {
} }
worker->data1 = dec; worker->data1 = dec;
worker->data2 = (void*)&dec->thread_ctx_.io_; worker->data2 = (void*)&dec->thread_ctx_.io_;
worker->hook = FinishRow; worker->hook = (WebPWorkerHook)FinishRow;
dec->num_caches_ = dec->num_caches_ =
(dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1; (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1;
} else { } else {
@ -668,9 +671,15 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options,
(void)height; (void)height;
assert(headers == NULL || !headers->is_lossless); assert(headers == NULL || !headers->is_lossless);
#if defined(WEBP_USE_THREAD) #if defined(WEBP_USE_THREAD)
if (width >= MIN_WIDTH_FOR_THREADS) return 2; if (width < MIN_WIDTH_FOR_THREADS) return 0;
// TODO(skal): tune the heuristic further
#if 0
if (height < 2 * width) return 2;
#endif #endif
return 2;
#else // !WEBP_USE_THREAD
return 0; return 0;
#endif
} }
#undef MT_CACHE_LINES #undef MT_CACHE_LINES
@ -719,7 +728,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
} }
mem = (uint8_t*)dec->mem_; mem = (uint8_t*)dec->mem_;
dec->intra_t_ = mem; dec->intra_t_ = (uint8_t*)mem;
mem += intra_pred_mode_size; mem += intra_pred_mode_size;
dec->yuv_t_ = (VP8TopSamples*)mem; dec->yuv_t_ = (VP8TopSamples*)mem;
@ -732,7 +741,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
mem += f_info_size; mem += f_info_size;
dec->thread_ctx_.id_ = 0; dec->thread_ctx_.id_ = 0;
dec->thread_ctx_.f_info_ = dec->f_info_; dec->thread_ctx_.f_info_ = dec->f_info_;
if (dec->filter_type_ > 0 && dec->mt_method_ > 0) { if (dec->mt_method_ > 0) {
// secondary cache line. The deblocking process need to make use of the // secondary cache line. The deblocking process need to make use of the
// filtering strength from previous macroblock row, while the new ones // filtering strength from previous macroblock row, while the new ones
// are being decoded in parallel. We'll just swap the pointers. // are being decoded in parallel. We'll just swap the pointers.
@ -741,7 +750,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
mem = (uint8_t*)WEBP_ALIGN(mem); mem = (uint8_t*)WEBP_ALIGN(mem);
assert((yuv_size & WEBP_ALIGN_CST) == 0); assert((yuv_size & WEBP_ALIGN_CST) == 0);
dec->yuv_b_ = mem; dec->yuv_b_ = (uint8_t*)mem;
mem += yuv_size; mem += yuv_size;
dec->mb_data_ = (VP8MBData*)mem; dec->mb_data_ = (VP8MBData*)mem;
@ -757,7 +766,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
const int extra_rows = kFilterExtraRows[dec->filter_type_]; const int extra_rows = kFilterExtraRows[dec->filter_type_];
const int extra_y = extra_rows * dec->cache_y_stride_; const int extra_y = extra_rows * dec->cache_y_stride_;
const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_; const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_;
dec->cache_y_ = mem + extra_y; dec->cache_y_ = ((uint8_t*)mem) + extra_y;
dec->cache_u_ = dec->cache_y_ dec->cache_u_ = dec->cache_y_
+ 16 * num_caches * dec->cache_y_stride_ + extra_uv; + 16 * num_caches * dec->cache_y_stride_ + extra_uv;
dec->cache_v_ = dec->cache_u_ dec->cache_v_ = dec->cache_u_
@ -767,7 +776,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
mem += cache_size; mem += cache_size;
// alpha plane // alpha plane
dec->alpha_plane_ = alpha_size ? mem : NULL; dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL;
mem += alpha_size; mem += alpha_size;
assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_); assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_);

View File

@ -15,10 +15,10 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "src/dec/alphai_dec.h" #include "./alphai_dec.h"
#include "src/dec/webpi_dec.h" #include "./webpi_dec.h"
#include "src/dec/vp8i_dec.h" #include "./vp8i_dec.h"
#include "src/utils/utils.h" #include "../utils/utils.h"
// In append mode, buffer allocations increase as multiples of this value. // In append mode, buffer allocations increase as multiples of this value.
// Needs to be a power of 2. // Needs to be a power of 2.
@ -140,9 +140,10 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
if (NeedCompressedAlpha(idec)) { if (NeedCompressedAlpha(idec)) {
ALPHDecoder* const alph_dec = dec->alph_dec_; ALPHDecoder* const alph_dec = dec->alph_dec_;
dec->alpha_data_ += offset; dec->alpha_data_ += offset;
if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) { if (alph_dec != NULL) {
if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) {
VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_;
assert(alph_vp8l_dec != NULL);
assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN);
VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_,
dec->alpha_data_ + ALPHA_HEADER_LEN, dec->alpha_data_ + ALPHA_HEADER_LEN,
@ -166,11 +167,9 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
VP8Decoder* const dec = (VP8Decoder*)idec->dec_; VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
MemBuffer* const mem = &idec->mem_; MemBuffer* const mem = &idec->mem_;
const int need_compressed_alpha = NeedCompressedAlpha(idec); const int need_compressed_alpha = NeedCompressedAlpha(idec);
const uint8_t* const old_start = const uint8_t* const old_start = mem->buf_ + mem->start_;
(mem->buf_ == NULL) ? NULL : mem->buf_ + mem->start_;
const uint8_t* const old_base = const uint8_t* const old_base =
need_compressed_alpha ? dec->alpha_data_ : old_start; need_compressed_alpha ? dec->alpha_data_ : old_start;
assert(mem->buf_ != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_APPEND); assert(mem->mode_ == MEM_MODE_APPEND);
if (data_size > MAX_CHUNK_PAYLOAD) { if (data_size > MAX_CHUNK_PAYLOAD) {
// security safeguard: trying to allocate more than what the format // security safeguard: trying to allocate more than what the format
@ -186,7 +185,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
uint8_t* const new_buf = uint8_t* const new_buf =
(uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
if (new_buf == NULL) return 0; if (new_buf == NULL) return 0;
if (old_base != NULL) memcpy(new_buf, old_base, current_size); memcpy(new_buf, old_base, current_size);
WebPSafeFree(mem->buf_); WebPSafeFree(mem->buf_);
mem->buf_ = new_buf; mem->buf_ = new_buf;
mem->buf_size_ = (size_t)extra_size; mem->buf_size_ = (size_t)extra_size;
@ -194,7 +193,6 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
mem->end_ = current_size; mem->end_ = current_size;
} }
assert(mem->buf_ != NULL);
memcpy(mem->buf_ + mem->end_, data, data_size); memcpy(mem->buf_ + mem->end_, data, data_size);
mem->end_ += data_size; mem->end_ += data_size;
assert(mem->end_ <= mem->buf_size_); assert(mem->end_ <= mem->buf_size_);
@ -207,9 +205,7 @@ static int RemapMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) { const uint8_t* const data, size_t data_size) {
MemBuffer* const mem = &idec->mem_; MemBuffer* const mem = &idec->mem_;
const uint8_t* const old_buf = mem->buf_; const uint8_t* const old_buf = mem->buf_;
const uint8_t* const old_start = const uint8_t* const old_start = old_buf + mem->start_;
(old_buf == NULL) ? NULL : old_buf + mem->start_;
assert(old_buf != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_MAP); assert(mem->mode_ == MEM_MODE_MAP);
if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
@ -287,8 +283,10 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
if (idec->state_ == STATE_VP8_DATA) { if (idec->state_ == STATE_VP8_DATA) {
// Synchronize the thread, clean-up and check for errors. VP8Io* const io = &idec->io_;
VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); if (io->teardown != NULL) {
io->teardown(io);
}
} }
idec->state_ = STATE_ERROR; idec->state_ = STATE_ERROR;
return error; return error;
@ -453,10 +451,7 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
VP8Decoder* const dec = (VP8Decoder*)idec->dec_; VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
VP8Io* const io = &idec->io_; VP8Io* const io = &idec->io_;
// Make sure partition #0 has been read before, to set dec to ready_. assert(dec->ready_);
if (!dec->ready_) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
}
for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
if (idec->last_mb_y_ != dec->mb_y_) { if (idec->last_mb_y_ != dec->mb_y_) {
if (!VP8ParseIntraModeRow(&dec->br_, dec)) { if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
@ -478,12 +473,6 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
MemDataSize(&idec->mem_) > MAX_MB_SIZE) { MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
} }
// Synchronize the threads.
if (dec->mt_method_ > 0) {
if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
}
}
RestoreContext(&context, dec, token_br); RestoreContext(&context, dec, token_br);
return VP8_STATUS_SUSPENDED; return VP8_STATUS_SUSPENDED;
} }
@ -502,7 +491,6 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
} }
// Synchronize the thread and check for errors. // Synchronize the thread and check for errors.
if (!VP8ExitCritical(dec, io)) { if (!VP8ExitCritical(dec, io)) {
idec->state_ = STATE_ERROR; // prevent re-entry in IDecError
return IDecError(idec, VP8_STATUS_USER_ABORT); return IDecError(idec, VP8_STATUS_USER_ABORT);
} }
dec->ready_ = 0; dec->ready_ = 0;
@ -583,10 +571,6 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) {
status = DecodePartition0(idec); status = DecodePartition0(idec);
} }
if (idec->state_ == STATE_VP8_DATA) { if (idec->state_ == STATE_VP8_DATA) {
const VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
if (dec == NULL) {
return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder.
}
status = DecodeRemaining(idec); status = DecodeRemaining(idec);
} }
if (idec->state_ == STATE_VP8L_HEADER) { if (idec->state_ == STATE_VP8L_HEADER) {
@ -689,12 +673,12 @@ void WebPIDelete(WebPIDecoder* idec) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Wrapper toward WebPINewDecoder // Wrapper toward WebPINewDecoder
WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE csp, uint8_t* output_buffer, WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer,
size_t output_buffer_size, int output_stride) { size_t output_buffer_size, int output_stride) {
const int is_external_memory = (output_buffer != NULL) ? 1 : 0; const int is_external_memory = (output_buffer != NULL) ? 1 : 0;
WebPIDecoder* idec; WebPIDecoder* idec;
if (csp >= MODE_YUV) return NULL; if (mode >= MODE_YUV) return NULL;
if (is_external_memory == 0) { // Overwrite parameters to sane values. if (is_external_memory == 0) { // Overwrite parameters to sane values.
output_buffer_size = 0; output_buffer_size = 0;
output_stride = 0; output_stride = 0;
@ -705,7 +689,7 @@ WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE csp, uint8_t* output_buffer,
} }
idec = WebPINewDecoder(NULL); idec = WebPINewDecoder(NULL);
if (idec == NULL) return NULL; if (idec == NULL) return NULL;
idec->output_.colorspace = csp; idec->output_.colorspace = mode;
idec->output_.is_external_memory = is_external_memory; idec->output_.is_external_memory = is_external_memory;
idec->output_.u.RGBA.rgba = output_buffer; idec->output_.u.RGBA.rgba = output_buffer;
idec->output_.u.RGBA.stride = output_stride; idec->output_.u.RGBA.stride = output_stride;

View File

@ -13,11 +13,11 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include "src/dec/vp8i_dec.h" #include "../dec/vp8i_dec.h"
#include "src/dec/webpi_dec.h" #include "./webpi_dec.h"
#include "src/dsp/dsp.h" #include "../dsp/dsp.h"
#include "src/dsp/yuv.h" #include "../dsp/yuv.h"
#include "src/utils/utils.h" #include "../utils/utils.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Main YUV<->RGB conversion functions // Main YUV<->RGB conversion functions
@ -25,16 +25,21 @@
static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) { static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
WebPDecBuffer* output = p->output; WebPDecBuffer* output = p->output;
const WebPYUVABuffer* const buf = &output->u.YUVA; const WebPYUVABuffer* const buf = &output->u.YUVA;
uint8_t* const y_dst = buf->y + (size_t)io->mb_y * buf->y_stride; uint8_t* const y_dst = buf->y + io->mb_y * buf->y_stride;
uint8_t* const u_dst = buf->u + (size_t)(io->mb_y >> 1) * buf->u_stride; uint8_t* const u_dst = buf->u + (io->mb_y >> 1) * buf->u_stride;
uint8_t* const v_dst = buf->v + (size_t)(io->mb_y >> 1) * buf->v_stride; uint8_t* const v_dst = buf->v + (io->mb_y >> 1) * buf->v_stride;
const int mb_w = io->mb_w; const int mb_w = io->mb_w;
const int mb_h = io->mb_h; const int mb_h = io->mb_h;
const int uv_w = (mb_w + 1) / 2; const int uv_w = (mb_w + 1) / 2;
const int uv_h = (mb_h + 1) / 2; const int uv_h = (mb_h + 1) / 2;
WebPCopyPlane(io->y, io->y_stride, y_dst, buf->y_stride, mb_w, mb_h); int j;
WebPCopyPlane(io->u, io->uv_stride, u_dst, buf->u_stride, uv_w, uv_h); for (j = 0; j < mb_h; ++j) {
WebPCopyPlane(io->v, io->uv_stride, v_dst, buf->v_stride, uv_w, uv_h); memcpy(y_dst + j * buf->y_stride, io->y + j * io->y_stride, mb_w);
}
for (j = 0; j < uv_h; ++j) {
memcpy(u_dst + j * buf->u_stride, io->u + j * io->uv_stride, uv_w);
memcpy(v_dst + j * buf->v_stride, io->v + j * io->uv_stride, uv_w);
}
return io->mb_h; return io->mb_h;
} }
@ -42,7 +47,7 @@ static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) { static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
WebPDecBuffer* const output = p->output; WebPDecBuffer* const output = p->output;
WebPRGBABuffer* const buf = &output->u.RGBA; WebPRGBABuffer* const buf = &output->u.RGBA;
uint8_t* const dst = buf->rgba + (size_t)io->mb_y * buf->stride; uint8_t* const dst = buf->rgba + io->mb_y * buf->stride;
WebPSamplerProcessPlane(io->y, io->y_stride, WebPSamplerProcessPlane(io->y, io->y_stride,
io->u, io->v, io->uv_stride, io->u, io->v, io->uv_stride,
dst, buf->stride, io->mb_w, io->mb_h, dst, buf->stride, io->mb_w, io->mb_h,
@ -57,7 +62,7 @@ static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) { static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
int num_lines_out = io->mb_h; // a priori guess int num_lines_out = io->mb_h; // a priori guess
const WebPRGBABuffer* const buf = &p->output->u.RGBA; const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* dst = buf->rgba + (size_t)io->mb_y * buf->stride; uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace]; WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace];
const uint8_t* cur_y = io->y; const uint8_t* cur_y = io->y;
const uint8_t* cur_u = io->u; const uint8_t* cur_u = io->u;
@ -128,7 +133,7 @@ static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
const WebPYUVABuffer* const buf = &p->output->u.YUVA; const WebPYUVABuffer* const buf = &p->output->u.YUVA;
const int mb_w = io->mb_w; const int mb_w = io->mb_w;
const int mb_h = io->mb_h; const int mb_h = io->mb_h;
uint8_t* dst = buf->a + (size_t)io->mb_y * buf->a_stride; uint8_t* dst = buf->a + io->mb_y * buf->a_stride;
int j; int j;
(void)expected_num_lines_out; (void)expected_num_lines_out;
assert(expected_num_lines_out == mb_h); assert(expected_num_lines_out == mb_h);
@ -181,7 +186,7 @@ static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
(colorspace == MODE_ARGB || colorspace == MODE_Argb); (colorspace == MODE_ARGB || colorspace == MODE_Argb);
const WebPRGBABuffer* const buf = &p->output->u.RGBA; const WebPRGBABuffer* const buf = &p->output->u.RGBA;
int num_rows; int num_rows;
const size_t start_y = GetAlphaSourceRow(io, &alpha, &num_rows); const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3); uint8_t* const dst = base_rgba + (alpha_first ? 0 : 3);
const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w, const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w,
@ -205,9 +210,9 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p,
const WEBP_CSP_MODE colorspace = p->output->colorspace; const WEBP_CSP_MODE colorspace = p->output->colorspace;
const WebPRGBABuffer* const buf = &p->output->u.RGBA; const WebPRGBABuffer* const buf = &p->output->u.RGBA;
int num_rows; int num_rows;
const size_t start_y = GetAlphaSourceRow(io, &alpha, &num_rows); const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
#if (WEBP_SWAP_16BIT_CSP == 1) #ifdef WEBP_SWAP_16BIT_CSP
uint8_t* alpha_dst = base_rgba; uint8_t* alpha_dst = base_rgba;
#else #else
uint8_t* alpha_dst = base_rgba + 1; uint8_t* alpha_dst = base_rgba + 1;
@ -236,7 +241,6 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// YUV rescaling (no final RGB conversion needed) // YUV rescaling (no final RGB conversion needed)
#if !defined(WEBP_REDUCE_SIZE)
static int Rescale(const uint8_t* src, int src_stride, static int Rescale(const uint8_t* src, int src_stride,
int new_lines, WebPRescaler* const wrk) { int new_lines, WebPRescaler* const wrk) {
int num_lines_out = 0; int num_lines_out = 0;
@ -271,9 +275,9 @@ static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p, static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
int expected_num_lines_out) { int expected_num_lines_out) {
const WebPYUVABuffer* const buf = &p->output->u.YUVA; const WebPYUVABuffer* const buf = &p->output->u.YUVA;
uint8_t* const dst_a = buf->a + (size_t)p->last_y * buf->a_stride; uint8_t* const dst_a = buf->a + p->last_y * buf->a_stride;
if (io->a != NULL) { if (io->a != NULL) {
uint8_t* const dst_y = buf->y + (size_t)p->last_y * buf->y_stride; uint8_t* const dst_y = buf->y + p->last_y * buf->y_stride;
const int num_lines_out = Rescale(io->a, io->width, io->mb_h, p->scaler_a); const int num_lines_out = Rescale(io->a, io->width, io->mb_h, p->scaler_a);
assert(expected_num_lines_out == num_lines_out); assert(expected_num_lines_out == num_lines_out);
if (num_lines_out > 0) { // unmultiply the Y if (num_lines_out > 0) { // unmultiply the Y
@ -351,7 +355,7 @@ static int ExportRGB(WebPDecParams* const p, int y_pos) {
const WebPYUV444Converter convert = const WebPYUV444Converter convert =
WebPYUV444Converters[p->output->colorspace]; WebPYUV444Converters[p->output->colorspace];
const WebPRGBABuffer* const buf = &p->output->u.RGBA; const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* dst = buf->rgba + (size_t)y_pos * buf->stride; uint8_t* dst = buf->rgba + y_pos * buf->stride;
int num_lines_out = 0; int num_lines_out = 0;
// For RGB rescaling, because of the YUV420, current scan position // For RGB rescaling, because of the YUV420, current scan position
// U/V can be +1/-1 line from the Y one. Hence the double test. // U/V can be +1/-1 line from the Y one. Hence the double test.
@ -378,15 +382,15 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
while (j < mb_h) { while (j < mb_h) {
const int y_lines_in = const int y_lines_in =
WebPRescalerImport(p->scaler_y, mb_h - j, WebPRescalerImport(p->scaler_y, mb_h - j,
io->y + (size_t)j * io->y_stride, io->y_stride); io->y + j * io->y_stride, io->y_stride);
j += y_lines_in; j += y_lines_in;
if (WebPRescaleNeededLines(p->scaler_u, uv_mb_h - uv_j)) { if (WebPRescaleNeededLines(p->scaler_u, uv_mb_h - uv_j)) {
const int u_lines_in = WebPRescalerImport( const int u_lines_in =
p->scaler_u, uv_mb_h - uv_j, io->u + (size_t)uv_j * io->uv_stride, WebPRescalerImport(p->scaler_u, uv_mb_h - uv_j,
io->uv_stride); io->u + uv_j * io->uv_stride, io->uv_stride);
const int v_lines_in = WebPRescalerImport( const int v_lines_in =
p->scaler_v, uv_mb_h - uv_j, io->v + (size_t)uv_j * io->uv_stride, WebPRescalerImport(p->scaler_v, uv_mb_h - uv_j,
io->uv_stride); io->v + uv_j * io->uv_stride, io->uv_stride);
(void)v_lines_in; // remove a gcc warning (void)v_lines_in; // remove a gcc warning
assert(u_lines_in == v_lines_in); assert(u_lines_in == v_lines_in);
uv_j += u_lines_in; uv_j += u_lines_in;
@ -398,7 +402,7 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) { static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
const WebPRGBABuffer* const buf = &p->output->u.RGBA; const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* const base_rgba = buf->rgba + (size_t)y_pos * buf->stride; uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
const WEBP_CSP_MODE colorspace = p->output->colorspace; const WEBP_CSP_MODE colorspace = p->output->colorspace;
const int alpha_first = const int alpha_first =
(colorspace == MODE_ARGB || colorspace == MODE_Argb); (colorspace == MODE_ARGB || colorspace == MODE_Argb);
@ -426,8 +430,8 @@ static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos, static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos,
int max_lines_out) { int max_lines_out) {
const WebPRGBABuffer* const buf = &p->output->u.RGBA; const WebPRGBABuffer* const buf = &p->output->u.RGBA;
uint8_t* const base_rgba = buf->rgba + (size_t)y_pos * buf->stride; uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
#if (WEBP_SWAP_16BIT_CSP == 1) #ifdef WEBP_SWAP_16BIT_CSP
uint8_t* alpha_dst = base_rgba; uint8_t* alpha_dst = base_rgba;
#else #else
uint8_t* alpha_dst = base_rgba + 1; uint8_t* alpha_dst = base_rgba + 1;
@ -465,7 +469,7 @@ static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
int lines_left = expected_num_out_lines; int lines_left = expected_num_out_lines;
const int y_end = p->last_y + lines_left; const int y_end = p->last_y + lines_left;
while (lines_left > 0) { while (lines_left > 0) {
const int64_t row_offset = (int64_t)scaler->src_y - io->mb_y; const int row_offset = scaler->src_y - io->mb_y;
WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y, WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y,
io->a + row_offset * io->width, io->width); io->a + row_offset * io->width, io->width);
lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left); lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left);
@ -537,8 +541,6 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
return 1; return 1;
} }
#endif // WEBP_REDUCE_SIZE
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Default custom functions // Default custom functions
@ -559,14 +561,10 @@ static int CustomSetup(VP8Io* io) {
WebPInitUpsamplers(); WebPInitUpsamplers();
} }
if (io->use_scaling) { if (io->use_scaling) {
#if !defined(WEBP_REDUCE_SIZE)
const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p); const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p);
if (!ok) { if (!ok) {
return 0; // memory error return 0; // memory error
} }
#else
return 0; // rescaling support not compiled
#endif
} else { } else {
if (is_rgb) { if (is_rgb) {
WebPInitSamplers(); WebPInitSamplers();
@ -600,6 +598,9 @@ static int CustomSetup(VP8Io* io) {
} }
} }
if (is_rgb) {
VP8YUVInit();
}
return 1; return 1;
} }

View File

@ -11,7 +11,7 @@
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include "src/dec/vp8i_dec.h" #include "./vp8i_dec.h"
static WEBP_INLINE int clip(int v, int M) { static WEBP_INLINE int clip(int v, int M) {
return v < 0 ? 0 : v > M ? M : v; return v < 0 ? 0 : v > M ? M : v;
@ -61,17 +61,12 @@ static const uint16_t kAcTable[128] = {
void VP8ParseQuant(VP8Decoder* const dec) { void VP8ParseQuant(VP8Decoder* const dec) {
VP8BitReader* const br = &dec->br_; VP8BitReader* const br = &dec->br_;
const int base_q0 = VP8GetValue(br, 7, "global-header"); const int base_q0 = VP8GetValue(br, 7);
const int dqy1_dc = VP8Get(br, "global-header") ? const int dqy1_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
VP8GetSignedValue(br, 4, "global-header") : 0; const int dqy2_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dqy2_dc = VP8Get(br, "global-header") ? const int dqy2_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
VP8GetSignedValue(br, 4, "global-header") : 0; const int dquv_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dqy2_ac = VP8Get(br, "global-header") ? const int dquv_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
VP8GetSignedValue(br, 4, "global-header") : 0;
const int dquv_dc = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 4, "global-header") : 0;
const int dquv_ac = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 4, "global-header") : 0;
const VP8SegmentHeader* const hdr = &dec->segment_hdr_; const VP8SegmentHeader* const hdr = &dec->segment_hdr_;
int i; int i;

View File

@ -11,19 +11,15 @@
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#include "src/dec/vp8i_dec.h" #include "./vp8i_dec.h"
#include "src/utils/bit_reader_inl_utils.h" #include "../utils/bit_reader_inl_utils.h"
#if !defined(USE_GENERIC_TREE)
#if !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__) #if !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__)
// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then. // using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then.
#define USE_GENERIC_TREE 1 // ALTERNATE_CODE #define USE_GENERIC_TREE
#else
#define USE_GENERIC_TREE 0
#endif #endif
#endif // USE_GENERIC_TREE
#if (USE_GENERIC_TREE == 1) #ifdef USE_GENERIC_TREE
static const int8_t kYModesIntra4[18] = { static const int8_t kYModesIntra4[18] = {
-B_DC_PRED, 1, -B_DC_PRED, 1,
-B_TM_PRED, 2, -B_TM_PRED, 2,
@ -296,21 +292,20 @@ static void ParseIntraMode(VP8BitReader* const br,
// to decode more than 1 keyframe. // to decode more than 1 keyframe.
if (dec->segment_hdr_.update_map_) { if (dec->segment_hdr_.update_map_) {
// Hardcoded tree parsing // Hardcoded tree parsing
block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0], "segments") block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0])
? VP8GetBit(br, dec->proba_.segments_[1], "segments") ? VP8GetBit(br, dec->proba_.segments_[1])
: VP8GetBit(br, dec->proba_.segments_[2], "segments") + 2; : 2 + VP8GetBit(br, dec->proba_.segments_[2]);
} else { } else {
block->segment_ = 0; // default for intra block->segment_ = 0; // default for intra
} }
if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_, "skip"); if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_);
block->is_i4x4_ = !VP8GetBit(br, 145, "block-size"); block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first
if (!block->is_i4x4_) { if (!block->is_i4x4_) {
// Hardcoded 16x16 intra-mode decision tree. // Hardcoded 16x16 intra-mode decision tree.
const int ymode = const int ymode =
VP8GetBit(br, 156, "pred-modes") ? VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED)
(VP8GetBit(br, 128, "pred-modes") ? TM_PRED : H_PRED) : : (VP8GetBit(br, 163) ? V_PRED : DC_PRED);
(VP8GetBit(br, 163, "pred-modes") ? V_PRED : DC_PRED);
block->imodes_[0] = ymode; block->imodes_[0] = ymode;
memset(top, ymode, 4 * sizeof(*top)); memset(top, ymode, 4 * sizeof(*top));
memset(left, ymode, 4 * sizeof(*left)); memset(left, ymode, 4 * sizeof(*left));
@ -322,28 +317,25 @@ static void ParseIntraMode(VP8BitReader* const br,
int x; int x;
for (x = 0; x < 4; ++x) { for (x = 0; x < 4; ++x) {
const uint8_t* const prob = kBModesProba[top[x]][ymode]; const uint8_t* const prob = kBModesProba[top[x]][ymode];
#if (USE_GENERIC_TREE == 1) #ifdef USE_GENERIC_TREE
// Generic tree-parsing // Generic tree-parsing
int i = kYModesIntra4[VP8GetBit(br, prob[0], "pred-modes")]; int i = kYModesIntra4[VP8GetBit(br, prob[0])];
while (i > 0) { while (i > 0) {
i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i], "pred-modes")]; i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
} }
ymode = -i; ymode = -i;
#else #else
// Hardcoded tree parsing // Hardcoded tree parsing
ymode = !VP8GetBit(br, prob[0], "pred-modes") ? B_DC_PRED : ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED :
!VP8GetBit(br, prob[1], "pred-modes") ? B_TM_PRED : !VP8GetBit(br, prob[1]) ? B_TM_PRED :
!VP8GetBit(br, prob[2], "pred-modes") ? B_VE_PRED : !VP8GetBit(br, prob[2]) ? B_VE_PRED :
!VP8GetBit(br, prob[3], "pred-modes") ? !VP8GetBit(br, prob[3]) ?
(!VP8GetBit(br, prob[4], "pred-modes") ? B_HE_PRED : (!VP8GetBit(br, prob[4]) ? B_HE_PRED :
(!VP8GetBit(br, prob[5], "pred-modes") ? B_RD_PRED (!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) :
: B_VR_PRED)) : (!VP8GetBit(br, prob[6]) ? B_LD_PRED :
(!VP8GetBit(br, prob[6], "pred-modes") ? B_LD_PRED : (!VP8GetBit(br, prob[7]) ? B_VL_PRED :
(!VP8GetBit(br, prob[7], "pred-modes") ? B_VL_PRED : (!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED)));
(!VP8GetBit(br, prob[8], "pred-modes") ? B_HD_PRED #endif // USE_GENERIC_TREE
: B_HU_PRED))
);
#endif // USE_GENERIC_TREE
top[x] = ymode; top[x] = ymode;
} }
memcpy(modes, top, 4 * sizeof(*top)); memcpy(modes, top, 4 * sizeof(*top));
@ -352,9 +344,9 @@ static void ParseIntraMode(VP8BitReader* const br,
} }
} }
// Hardcoded UVMode decision tree // Hardcoded UVMode decision tree
block->uvmode_ = !VP8GetBit(br, 142, "pred-modes-uv") ? DC_PRED block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
: !VP8GetBit(br, 114, "pred-modes-uv") ? V_PRED : !VP8GetBit(br, 114) ? V_PRED
: VP8GetBit(br, 183, "pred-modes-uv") ? TM_PRED : H_PRED; : VP8GetBit(br, 183) ? TM_PRED : H_PRED;
} }
int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) { int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) {
@ -506,7 +498,7 @@ static const uint8_t
// Paragraph 9.9 // Paragraph 9.9
static const uint8_t kBands[16 + 1] = { static const int kBands[16 + 1] = {
0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7,
0 // extra entry as sentinel 0 // extra entry as sentinel
}; };
@ -518,10 +510,8 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
for (b = 0; b < NUM_BANDS; ++b) { for (b = 0; b < NUM_BANDS; ++b) {
for (c = 0; c < NUM_CTX; ++c) { for (c = 0; c < NUM_CTX; ++c) {
for (p = 0; p < NUM_PROBAS; ++p) { for (p = 0; p < NUM_PROBAS; ++p) {
const int v = const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ?
VP8GetBit(br, CoeffsUpdateProba[t][b][c][p], "global-header") ? VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p];
VP8GetValue(br, 8, "global-header") :
CoeffsProba0[t][b][c][p];
proba->bands_[t][b].probas_[c][p] = v; proba->bands_[t][b].probas_[c][p] = v;
} }
} }
@ -530,8 +520,9 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]]; proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]];
} }
} }
dec->use_skip_proba_ = VP8Get(br, "global-header"); dec->use_skip_proba_ = VP8Get(br);
if (dec->use_skip_proba_) { if (dec->use_skip_proba_) {
dec->skip_p_ = VP8GetValue(br, 8, "global-header"); dec->skip_p_ = VP8GetValue(br, 8);
} }
} }

View File

@ -13,12 +13,12 @@
#include <stdlib.h> #include <stdlib.h>
#include "src/dec/alphai_dec.h" #include "./alphai_dec.h"
#include "src/dec/vp8i_dec.h" #include "./vp8i_dec.h"
#include "src/dec/vp8li_dec.h" #include "./vp8li_dec.h"
#include "src/dec/webpi_dec.h" #include "./webpi_dec.h"
#include "src/utils/bit_reader_inl_utils.h" #include "../utils/bit_reader_inl_utils.h"
#include "src/utils/utils.h" #include "../utils/utils.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -161,26 +161,23 @@ static int ParseSegmentHeader(VP8BitReader* br,
VP8SegmentHeader* hdr, VP8Proba* proba) { VP8SegmentHeader* hdr, VP8Proba* proba) {
assert(br != NULL); assert(br != NULL);
assert(hdr != NULL); assert(hdr != NULL);
hdr->use_segment_ = VP8Get(br, "global-header"); hdr->use_segment_ = VP8Get(br);
if (hdr->use_segment_) { if (hdr->use_segment_) {
hdr->update_map_ = VP8Get(br, "global-header"); hdr->update_map_ = VP8Get(br);
if (VP8Get(br, "global-header")) { // update data if (VP8Get(br)) { // update data
int s; int s;
hdr->absolute_delta_ = VP8Get(br, "global-header"); hdr->absolute_delta_ = VP8Get(br);
for (s = 0; s < NUM_MB_SEGMENTS; ++s) { for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
hdr->quantizer_[s] = VP8Get(br, "global-header") ? hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;
VP8GetSignedValue(br, 7, "global-header") : 0;
} }
for (s = 0; s < NUM_MB_SEGMENTS; ++s) { for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
hdr->filter_strength_[s] = VP8Get(br, "global-header") ? hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0;
VP8GetSignedValue(br, 6, "global-header") : 0;
} }
} }
if (hdr->update_map_) { if (hdr->update_map_) {
int s; int s;
for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) { for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
proba->segments_[s] = VP8Get(br, "global-header") ? proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u;
VP8GetValue(br, 8, "global-header") : 255u;
} }
} }
} else { } else {
@ -208,7 +205,7 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
size_t last_part; size_t last_part;
size_t p; size_t p;
dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2, "global-header")) - 1; dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2)) - 1;
last_part = dec->num_parts_minus_one_; last_part = dec->num_parts_minus_one_;
if (size < 3 * last_part) { if (size < 3 * last_part) {
// we can't even read the sizes with sz[]! That's a failure. // we can't even read the sizes with sz[]! That's a failure.
@ -232,21 +229,21 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
// Paragraph 9.4 // Paragraph 9.4
static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) {
VP8FilterHeader* const hdr = &dec->filter_hdr_; VP8FilterHeader* const hdr = &dec->filter_hdr_;
hdr->simple_ = VP8Get(br, "global-header"); hdr->simple_ = VP8Get(br);
hdr->level_ = VP8GetValue(br, 6, "global-header"); hdr->level_ = VP8GetValue(br, 6);
hdr->sharpness_ = VP8GetValue(br, 3, "global-header"); hdr->sharpness_ = VP8GetValue(br, 3);
hdr->use_lf_delta_ = VP8Get(br, "global-header"); hdr->use_lf_delta_ = VP8Get(br);
if (hdr->use_lf_delta_) { if (hdr->use_lf_delta_) {
if (VP8Get(br, "global-header")) { // update lf-delta? if (VP8Get(br)) { // update lf-delta?
int i; int i;
for (i = 0; i < NUM_REF_LF_DELTAS; ++i) { for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {
if (VP8Get(br, "global-header")) { if (VP8Get(br)) {
hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6);
} }
} }
for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) { for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
if (VP8Get(br, "global-header")) { if (VP8Get(br)) {
hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6);
} }
} }
} }
@ -355,8 +352,8 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
buf_size -= frm_hdr->partition_length_; buf_size -= frm_hdr->partition_length_;
if (frm_hdr->key_frame_) { if (frm_hdr->key_frame_) {
pic_hdr->colorspace_ = VP8Get(br, "global-header"); pic_hdr->colorspace_ = VP8Get(br);
pic_hdr->clamp_type_ = VP8Get(br, "global-header"); pic_hdr->clamp_type_ = VP8Get(br);
} }
if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) { if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
@ -381,7 +378,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
"Not a key frame."); "Not a key frame.");
} }
VP8Get(br, "global-header"); // ignore the value of update_proba_ VP8Get(br); // ignore the value of update_proba_
VP8ParseProba(br, dec); VP8ParseProba(br, dec);
@ -406,28 +403,28 @@ static const uint8_t kZigzag[16] = {
// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2 // See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2
static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
int v; int v;
if (!VP8GetBit(br, p[3], "coeffs")) { if (!VP8GetBit(br, p[3])) {
if (!VP8GetBit(br, p[4], "coeffs")) { if (!VP8GetBit(br, p[4])) {
v = 2; v = 2;
} else { } else {
v = 3 + VP8GetBit(br, p[5], "coeffs"); v = 3 + VP8GetBit(br, p[5]);
} }
} else { } else {
if (!VP8GetBit(br, p[6], "coeffs")) { if (!VP8GetBit(br, p[6])) {
if (!VP8GetBit(br, p[7], "coeffs")) { if (!VP8GetBit(br, p[7])) {
v = 5 + VP8GetBit(br, 159, "coeffs"); v = 5 + VP8GetBit(br, 159);
} else { } else {
v = 7 + 2 * VP8GetBit(br, 165, "coeffs"); v = 7 + 2 * VP8GetBit(br, 165);
v += VP8GetBit(br, 145, "coeffs"); v += VP8GetBit(br, 145);
} }
} else { } else {
const uint8_t* tab; const uint8_t* tab;
const int bit1 = VP8GetBit(br, p[8], "coeffs"); const int bit1 = VP8GetBit(br, p[8]);
const int bit0 = VP8GetBit(br, p[9 + bit1], "coeffs"); const int bit0 = VP8GetBit(br, p[9 + bit1]);
const int cat = 2 * bit1 + bit0; const int cat = 2 * bit1 + bit0;
v = 0; v = 0;
for (tab = kCat3456[cat]; *tab; ++tab) { for (tab = kCat3456[cat]; *tab; ++tab) {
v += v + VP8GetBit(br, *tab, "coeffs"); v += v + VP8GetBit(br, *tab);
} }
v += 3 + (8 << cat); v += 3 + (8 << cat);
} }
@ -441,24 +438,24 @@ static int GetCoeffsFast(VP8BitReader* const br,
int ctx, const quant_t dq, int n, int16_t* out) { int ctx, const quant_t dq, int n, int16_t* out) {
const uint8_t* p = prob[n]->probas_[ctx]; const uint8_t* p = prob[n]->probas_[ctx];
for (; n < 16; ++n) { for (; n < 16; ++n) {
if (!VP8GetBit(br, p[0], "coeffs")) { if (!VP8GetBit(br, p[0])) {
return n; // previous coeff was last non-zero coeff return n; // previous coeff was last non-zero coeff
} }
while (!VP8GetBit(br, p[1], "coeffs")) { // sequence of zero coeffs while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs
p = prob[++n]->probas_[0]; p = prob[++n]->probas_[0];
if (n == 16) return 16; if (n == 16) return 16;
} }
{ // non zero coeff { // non zero coeff
const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];
int v; int v;
if (!VP8GetBit(br, p[2], "coeffs")) { if (!VP8GetBit(br, p[2])) {
v = 1; v = 1;
p = p_ctx[1]; p = p_ctx[1];
} else { } else {
v = GetLargeValue(br, p); v = GetLargeValue(br, p);
p = p_ctx[2]; p = p_ctx[2];
} }
out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
} }
} }
return 16; return 16;
@ -471,34 +468,36 @@ static int GetCoeffsAlt(VP8BitReader* const br,
int ctx, const quant_t dq, int n, int16_t* out) { int ctx, const quant_t dq, int n, int16_t* out) {
const uint8_t* p = prob[n]->probas_[ctx]; const uint8_t* p = prob[n]->probas_[ctx];
for (; n < 16; ++n) { for (; n < 16; ++n) {
if (!VP8GetBitAlt(br, p[0], "coeffs")) { if (!VP8GetBitAlt(br, p[0])) {
return n; // previous coeff was last non-zero coeff return n; // previous coeff was last non-zero coeff
} }
while (!VP8GetBitAlt(br, p[1], "coeffs")) { // sequence of zero coeffs while (!VP8GetBitAlt(br, p[1])) { // sequence of zero coeffs
p = prob[++n]->probas_[0]; p = prob[++n]->probas_[0];
if (n == 16) return 16; if (n == 16) return 16;
} }
{ // non zero coeff { // non zero coeff
const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];
int v; int v;
if (!VP8GetBitAlt(br, p[2], "coeffs")) { if (!VP8GetBitAlt(br, p[2])) {
v = 1; v = 1;
p = p_ctx[1]; p = p_ctx[1];
} else { } else {
v = GetLargeValue(br, p); v = GetLargeValue(br, p);
p = p_ctx[2]; p = p_ctx[2];
} }
out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
} }
} }
return 16; return 16;
} }
WEBP_DSP_INIT_FUNC(InitGetCoeffs) { WEBP_TSAN_IGNORE_FUNCTION static void InitGetCoeffs(void) {
if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) { if (GetCoeffs == NULL) {
GetCoeffs = GetCoeffsAlt; if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
} else { GetCoeffs = GetCoeffsAlt;
GetCoeffs = GetCoeffsFast; } else {
GetCoeffs = GetCoeffsFast;
}
} }
} }

View File

@ -11,10 +11,10 @@
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DEC_VP8_DEC_H_ #ifndef WEBP_WEBP_DECODE_VP8_H_
#define WEBP_DEC_VP8_DEC_H_ #define WEBP_WEBP_DECODE_VP8_H_
#include "src/webp/decode.h" #include "../webp/decode.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -33,7 +33,7 @@ extern "C" {
// /* customize io's functions (setup()/put()/teardown()) if needed. */ // /* customize io's functions (setup()/put()/teardown()) if needed. */
// //
// VP8Decoder* dec = VP8New(); // VP8Decoder* dec = VP8New();
// int ok = VP8Decode(dec, &io); // bool ok = VP8Decode(dec);
// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); // if (!ok) printf("Error: %s\n", VP8StatusMessage(dec));
// VP8Delete(dec); // VP8Delete(dec);
// return ok; // return ok;
@ -157,24 +157,24 @@ void VP8Delete(VP8Decoder* const dec);
// Miscellaneous VP8/VP8L bitstream probing functions. // Miscellaneous VP8/VP8L bitstream probing functions.
// Returns true if the next 3 bytes in data contain the VP8 signature. // Returns true if the next 3 bytes in data contain the VP8 signature.
WEBP_EXTERN int VP8CheckSignature(const uint8_t* const data, size_t data_size); WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size);
// Validates the VP8 data-header and retrieves basic header information viz // Validates the VP8 data-header and retrieves basic header information viz
// width and height. Returns 0 in case of formatting error. *width/*height // width and height. Returns 0 in case of formatting error. *width/*height
// can be passed NULL. // can be passed NULL.
WEBP_EXTERN int VP8GetInfo( WEBP_EXTERN(int) VP8GetInfo(
const uint8_t* data, const uint8_t* data,
size_t data_size, // data available so far size_t data_size, // data available so far
size_t chunk_size, // total data size expected in the chunk size_t chunk_size, // total data size expected in the chunk
int* const width, int* const height); int* const width, int* const height);
// Returns true if the next byte(s) in data is a VP8L signature. // Returns true if the next byte(s) in data is a VP8L signature.
WEBP_EXTERN int VP8LCheckSignature(const uint8_t* const data, size_t size); WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size);
// Validates the VP8L data-header and retrieves basic header information viz // Validates the VP8L data-header and retrieves basic header information viz
// width, height and alpha. Returns 0 in case of formatting error. // width, height and alpha. Returns 0 in case of formatting error.
// width/height/has_alpha can be passed NULL. // width/height/has_alpha can be passed NULL.
WEBP_EXTERN int VP8LGetInfo( WEBP_EXTERN(int) VP8LGetInfo(
const uint8_t* data, size_t data_size, // data available so far const uint8_t* data, size_t data_size, // data available so far
int* const width, int* const height, int* const has_alpha); int* const width, int* const height, int* const has_alpha);
@ -182,4 +182,4 @@ WEBP_EXTERN int VP8LGetInfo(
} // extern "C" } // extern "C"
#endif #endif
#endif // WEBP_DEC_VP8_DEC_H_ #endif /* WEBP_WEBP_DECODE_VP8_H_ */

View File

@ -11,16 +11,16 @@
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DEC_VP8I_DEC_H_ #ifndef WEBP_DEC_VP8I_H_
#define WEBP_DEC_VP8I_DEC_H_ #define WEBP_DEC_VP8I_H_
#include <string.h> // for memcpy() #include <string.h> // for memcpy()
#include "src/dec/common_dec.h" #include "./common_dec.h"
#include "src/dec/vp8li_dec.h" #include "./vp8li_dec.h"
#include "src/utils/bit_reader_utils.h" #include "../utils/bit_reader_utils.h"
#include "src/utils/random_utils.h" #include "../utils/random_utils.h"
#include "src/utils/thread_utils.h" #include "../utils/thread_utils.h"
#include "src/dsp/dsp.h" #include "../dsp/dsp.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -30,8 +30,8 @@ extern "C" {
// Various defines and enums // Various defines and enums
// version numbers // version numbers
#define DEC_MAJ_VERSION 1 #define DEC_MAJ_VERSION 0
#define DEC_MIN_VERSION 2 #define DEC_MIN_VERSION 6
#define DEC_REV_VERSION 0 #define DEC_REV_VERSION 0
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
@ -57,6 +57,7 @@ extern "C" {
// '|' = left sample, '-' = top sample, '+' = top-left sample // '|' = left sample, '-' = top sample, '+' = top-left sample
// 't' = extra top-right sample for 4x4 modes // 't' = extra top-right sample for 4x4 modes
#define YUV_SIZE (BPS * 17 + BPS * 9) #define YUV_SIZE (BPS * 17 + BPS * 9)
#define Y_SIZE (BPS * 17)
#define Y_OFF (BPS * 1 + 8) #define Y_OFF (BPS * 1 + 8)
#define U_OFF (Y_OFF + BPS * 16 + BPS) #define U_OFF (Y_OFF + BPS * 16 + BPS)
#define V_OFF (U_OFF + 16) #define V_OFF (U_OFF + 16)
@ -316,4 +317,4 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
} // extern "C" } // extern "C"
#endif #endif
#endif // WEBP_DEC_VP8I_DEC_H_ #endif /* WEBP_DEC_VP8I_H_ */

View File

@ -14,22 +14,22 @@
#include <stdlib.h> #include <stdlib.h>
#include "src/dec/alphai_dec.h" #include "./alphai_dec.h"
#include "src/dec/vp8li_dec.h" #include "./vp8li_dec.h"
#include "src/dsp/dsp.h" #include "../dsp/dsp.h"
#include "src/dsp/lossless.h" #include "../dsp/lossless.h"
#include "src/dsp/lossless_common.h" #include "../dsp/lossless_common.h"
#include "src/dsp/yuv.h" #include "../dsp/yuv.h"
#include "src/utils/endian_inl_utils.h" #include "../utils/endian_inl_utils.h"
#include "src/utils/huffman_utils.h" #include "../utils/huffman_utils.h"
#include "src/utils/utils.h" #include "../utils/utils.h"
#define NUM_ARGB_CACHE_ROWS 16 #define NUM_ARGB_CACHE_ROWS 16
static const int kCodeLengthLiterals = 16; static const int kCodeLengthLiterals = 16;
static const int kCodeLengthRepeatCode = 16; static const int kCodeLengthRepeatCode = 16;
static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 }; static const int kCodeLengthExtraBits[3] = { 2, 3, 7 };
static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Five Huffman codes are used at each meta code: // Five Huffman codes are used at each meta code:
@ -86,7 +86,7 @@ static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
// All values computed for 8-bit first level lookup with Mark Adler's tool: // All values computed for 8-bit first level lookup with Mark Adler's tool:
// http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c // http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c
#define FIXED_TABLE_SIZE (630 * 3 + 410) #define FIXED_TABLE_SIZE (630 * 3 + 410)
static const uint16_t kTableSize[12] = { static const int kTableSize[12] = {
FIXED_TABLE_SIZE + 654, FIXED_TABLE_SIZE + 654,
FIXED_TABLE_SIZE + 656, FIXED_TABLE_SIZE + 656,
FIXED_TABLE_SIZE + 658, FIXED_TABLE_SIZE + 658,
@ -363,14 +363,11 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
uint32_t* huffman_image = NULL; uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL; HTreeGroup* htree_groups = NULL;
HuffmanCode* huffman_tables = NULL; HuffmanCode* huffman_tables = NULL;
HuffmanCode* huffman_table = NULL; HuffmanCode* next = NULL;
int num_htree_groups = 1; int num_htree_groups = 1;
int num_htree_groups_max = 1;
int max_alphabet_size = 0; int max_alphabet_size = 0;
int* code_lengths = NULL; int* code_lengths = NULL;
const int table_size = kTableSize[color_cache_bits]; const int table_size = kTableSize[color_cache_bits];
int* mapping = NULL;
int ok = 0;
if (allow_recursion && VP8LReadBits(br, 1)) { if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes. // use meta Huffman codes.
@ -387,36 +384,10 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
// The huffman data is stored in red and green bytes. // The huffman data is stored in red and green bytes.
const int group = (huffman_image[i] >> 8) & 0xffff; const int group = (huffman_image[i] >> 8) & 0xffff;
huffman_image[i] = group; huffman_image[i] = group;
if (group >= num_htree_groups_max) { if (group >= num_htree_groups) {
num_htree_groups_max = group + 1; num_htree_groups = group + 1;
} }
} }
// Check the validity of num_htree_groups_max. If it seems too big, use a
// smaller value for later. This will prevent big memory allocations to end
// up with a bad bitstream anyway.
// The value of 1000 is totally arbitrary. We know that num_htree_groups_max
// is smaller than (1 << 16) and should be smaller than the number of pixels
// (though the format allows it to be bigger).
if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) {
// Create a mapping from the used indices to the minimal set of used
// values [0, num_htree_groups)
mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));
if (mapping == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error;
}
// -1 means a value is unmapped, and therefore unused in the Huffman
// image.
memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping));
for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) {
// Get the current mapping for the group and remap the Huffman image.
int* const mapped_group = &mapping[huffman_image[i]];
if (*mapped_group == -1) *mapped_group = num_htree_groups++;
huffman_image[i] = *mapped_group;
}
} else {
num_htree_groups = num_htree_groups_max;
}
} }
if (br->eos_) goto Error; if (br->eos_) goto Error;
@ -432,106 +403,88 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
} }
} }
code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
sizeof(*code_lengths));
huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size, huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
sizeof(*huffman_tables)); sizeof(*huffman_tables));
htree_groups = VP8LHtreeGroupsNew(num_htree_groups); htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
sizeof(*code_lengths));
if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) { if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY; dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error; goto Error;
} }
huffman_table = huffman_tables; next = huffman_tables;
for (i = 0; i < num_htree_groups_max; ++i) { for (i = 0; i < num_htree_groups; ++i) {
// If the index "i" is unused in the Huffman image, just make sure the HTreeGroup* const htree_group = &htree_groups[i];
// coefficients are valid but do not store them. HuffmanCode** const htrees = htree_group->htrees;
if (mapping != NULL && mapping[i] == -1) { int size;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { int total_size = 0;
int alphabet_size = kAlphabetSize[j]; int is_trivial_literal = 1;
if (j == 0 && color_cache_bits > 0) { int max_bits = 0;
alphabet_size += (1 << color_cache_bits); for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
} int alphabet_size = kAlphabetSize[j];
// Passing in NULL so that nothing gets filled. htrees[j] = next;
if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) { if (j == 0 && color_cache_bits > 0) {
goto Error; alphabet_size += 1 << color_cache_bits;
}
} }
} else { size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next);
HTreeGroup* const htree_group = if (size == 0) {
&htree_groups[(mapping == NULL) ? i : mapping[i]]; goto Error;
HuffmanCode** const htrees = htree_group->htrees; }
int size; if (is_trivial_literal && kLiteralMap[j] == 1) {
int total_size = 0; is_trivial_literal = (next->bits == 0);
int is_trivial_literal = 1; }
int max_bits = 0; total_size += next->bits;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { next += size;
int alphabet_size = kAlphabetSize[j]; if (j <= ALPHA) {
htrees[j] = huffman_table; int local_max_bits = code_lengths[0];
if (j == 0 && color_cache_bits > 0) { int k;
alphabet_size += (1 << color_cache_bits); for (k = 1; k < alphabet_size; ++k) {
} if (code_lengths[k] > local_max_bits) {
size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table); local_max_bits = code_lengths[k];
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
is_trivial_literal = (huffman_table->bits == 0);
}
total_size += huffman_table->bits;
huffman_table += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
for (k = 1; k < alphabet_size; ++k) {
if (code_lengths[k] > local_max_bits) {
local_max_bits = code_lengths[k];
}
} }
max_bits += local_max_bits;
} }
max_bits += local_max_bits;
} }
htree_group->is_trivial_literal = is_trivial_literal;
htree_group->is_trivial_code = 0;
if (is_trivial_literal) {
const int red = htrees[RED][0].value;
const int blue = htrees[BLUE][0].value;
const int alpha = htrees[ALPHA][0].value;
htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
htree_group->is_trivial_code = 1;
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
}
}
htree_group->use_packed_table =
!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
} }
htree_group->is_trivial_literal = is_trivial_literal;
htree_group->is_trivial_code = 0;
if (is_trivial_literal) {
const int red = htrees[RED][0].value;
const int blue = htrees[BLUE][0].value;
const int alpha = htrees[ALPHA][0].value;
htree_group->literal_arb =
((uint32_t)alpha << 24) | (red << 16) | blue;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
htree_group->is_trivial_code = 1;
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
}
}
htree_group->use_packed_table = !htree_group->is_trivial_code &&
(max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
} }
ok = 1; WebPSafeFree(code_lengths);
// All OK. Finalize pointers. // All OK. Finalize pointers and return.
hdr->huffman_image_ = huffman_image; hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups; hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups; hdr->htree_groups_ = htree_groups;
hdr->huffman_tables_ = huffman_tables; hdr->huffman_tables_ = huffman_tables;
return 1;
Error: Error:
WebPSafeFree(code_lengths); WebPSafeFree(code_lengths);
WebPSafeFree(mapping); WebPSafeFree(huffman_image);
if (!ok) { WebPSafeFree(huffman_tables);
WebPSafeFree(huffman_image); VP8LHtreeGroupsFree(htree_groups);
WebPSafeFree(huffman_tables); return 0;
VP8LHtreeGroupsFree(htree_groups);
}
return ok;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Scaling. // Scaling.
#if !defined(WEBP_REDUCE_SIZE)
static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
const int num_channels = 4; const int num_channels = 4;
const int in_width = io->mb_w; const int in_width = io->mb_w;
@ -563,13 +516,10 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
out_width, out_height, 0, num_channels, work); out_width, out_height, 0, num_channels, work);
return 1; return 1;
} }
#endif // WEBP_REDUCE_SIZE
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Export to ARGB // Export to ARGB
#if !defined(WEBP_REDUCE_SIZE)
// We have special "export" function since we need to convert from BGRA // We have special "export" function since we need to convert from BGRA
static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
int rgba_stride, uint8_t* const rgba) { int rgba_stride, uint8_t* const rgba) {
@ -611,8 +561,6 @@ static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
return num_lines_out; return num_lines_out;
} }
#endif // WEBP_REDUCE_SIZE
// Emit rows without any scaling. // Emit rows without any scaling.
static int EmitRows(WEBP_CSP_MODE colorspace, static int EmitRows(WEBP_CSP_MODE colorspace,
const uint8_t* row_in, int in_stride, const uint8_t* row_in, int in_stride,
@ -754,11 +702,11 @@ static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
static void ApplyInverseTransforms(VP8LDecoder* const dec, static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
int start_row, int num_rows,
const uint32_t* const rows) { const uint32_t* const rows) {
int n = dec->next_transform_; int n = dec->next_transform_;
const int cache_pixs = dec->width_ * num_rows; const int cache_pixs = dec->width_ * num_rows;
const int start_row = dec->last_row_;
const int end_row = start_row + num_rows; const int end_row = start_row + num_rows;
const uint32_t* rows_in = rows; const uint32_t* rows_in = rows;
uint32_t* const rows_out = dec->argb_cache_; uint32_t* const rows_out = dec->argb_cache_;
@ -789,7 +737,8 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
VP8Io* const io = dec->io_; VP8Io* const io = dec->io_;
uint8_t* rows_data = (uint8_t*)dec->argb_cache_; uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows);
ApplyInverseTransforms(dec, num_rows, rows);
if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
// Nothing to output (this time). // Nothing to output (this time).
} else { } else {
@ -797,12 +746,9 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA
const WebPRGBABuffer* const buf = &output->u.RGBA; const WebPRGBABuffer* const buf = &output->u.RGBA;
uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
const int num_rows_out = const int num_rows_out = io->use_scaling ?
#if !defined(WEBP_REDUCE_SIZE)
io->use_scaling ?
EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
rgba, buf->stride) : rgba, buf->stride) :
#endif // WEBP_REDUCE_SIZE
EmitRows(output->colorspace, rows_data, in_stride, EmitRows(output->colorspace, rows_data, in_stride,
io->mb_w, io->mb_h, rgba, buf->stride); io->mb_w, io->mb_h, rgba, buf->stride);
// Update 'last_out_row_'. // Update 'last_out_row_'.
@ -929,11 +875,7 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
#endif #endif
break; break;
case 2: case 2:
#if !defined(WORDS_BIGENDIAN)
memcpy(&pattern, src, sizeof(uint16_t)); memcpy(&pattern, src, sizeof(uint16_t));
#else
pattern = ((uint32_t)src[0] << 8) | src[1];
#endif
#if defined(__arm__) || defined(_M_ARM) #if defined(__arm__) || defined(_M_ARM)
pattern |= pattern << 16; pattern |= pattern << 16;
#elif defined(WEBP_USE_MIPS_DSP_R2) #elif defined(WEBP_USE_MIPS_DSP_R2)
@ -947,6 +889,7 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
break; break;
default: default:
goto Copy; goto Copy;
break;
} }
CopySmallPattern8b(src, dst, length, pattern); CopySmallPattern8b(src, dst, length, pattern);
return; return;
@ -1069,13 +1012,12 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
ok = 0; ok = 0;
goto End; goto End;
} }
br->eos_ = VP8LIsEndOfStream(br); assert(br->eos_ == VP8LIsEndOfStream(br));
} }
// Process the remaining rows corresponding to last row-block. // Process the remaining rows corresponding to last row-block.
ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row); ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row);
End: End:
br->eos_ = VP8LIsEndOfStream(br);
if (!ok || (br->eos_ && pos < end)) { if (!ok || (br->eos_ && pos < end)) {
ok = 0; ok = 0;
dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
@ -1148,12 +1090,11 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
VP8LFillBitWindow(br); VP8LFillBitWindow(br);
if (htree_group->use_packed_table) { if (htree_group->use_packed_table) {
code = ReadPackedSymbols(htree_group, br, src); code = ReadPackedSymbols(htree_group, br, src);
if (VP8LIsEndOfStream(br)) break;
if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne; if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne;
} else { } else {
code = ReadSymbol(htree_group->htrees[GREEN], br); code = ReadSymbol(htree_group->htrees[GREEN], br);
} }
if (VP8LIsEndOfStream(br)) break; if (br->eos_) break; // early out
if (code < NUM_LITERAL_CODES) { // Literal if (code < NUM_LITERAL_CODES) { // Literal
if (htree_group->is_trivial_literal) { if (htree_group->is_trivial_literal) {
*src = htree_group->literal_arb | (code << 8); *src = htree_group->literal_arb | (code << 8);
@ -1163,7 +1104,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
VP8LFillBitWindow(br); VP8LFillBitWindow(br);
blue = ReadSymbol(htree_group->htrees[BLUE], br); blue = ReadSymbol(htree_group->htrees[BLUE], br);
alpha = ReadSymbol(htree_group->htrees[ALPHA], br); alpha = ReadSymbol(htree_group->htrees[ALPHA], br);
if (VP8LIsEndOfStream(br)) break; if (br->eos_) break;
*src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue; *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue;
} }
AdvanceByOne: AdvanceByOne:
@ -1191,8 +1132,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
VP8LFillBitWindow(br); VP8LFillBitWindow(br);
dist_code = GetCopyDistance(dist_symbol, br); dist_code = GetCopyDistance(dist_symbol, br);
dist = PlaneCodeToDistance(width, dist_code); dist = PlaneCodeToDistance(width, dist_code);
if (br->eos_) break;
if (VP8LIsEndOfStream(br)) break;
if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
goto Error; goto Error;
} else { } else {
@ -1229,9 +1169,9 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
} else { // Not reached } else { // Not reached
goto Error; goto Error;
} }
assert(br->eos_ == VP8LIsEndOfStream(br));
} }
br->eos_ = VP8LIsEndOfStream(br);
if (dec->incremental_ && br->eos_ && src < src_end) { if (dec->incremental_ && br->eos_ && src < src_end) {
RestoreState(dec); RestoreState(dec);
} else if (!br->eos_) { } else if (!br->eos_) {
@ -1552,7 +1492,7 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
const int cache_pixs = width * num_rows_to_process; const int cache_pixs = width * num_rows_to_process;
uint8_t* const dst = output + width * cur_row; uint8_t* const dst = output + width * cur_row;
const uint32_t* const src = dec->argb_cache_; const uint32_t* const src = dec->argb_cache_;
ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in); ApplyInverseTransforms(dec, num_rows_to_process, in);
WebPExtractGreen(src, dst, cache_pixs); WebPExtractGreen(src, dst, cache_pixs);
AlphaApplyFilter(alph_dec, AlphaApplyFilter(alph_dec,
cur_row, cur_row + num_rows_to_process, dst, width); cur_row, cur_row + num_rows_to_process, dst, width);
@ -1572,6 +1512,7 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (dec == NULL) return 0; if (dec == NULL) return 0;
assert(alph_dec != NULL); assert(alph_dec != NULL);
alph_dec->vp8l_dec_ = dec;
dec->width_ = alph_dec->width_; dec->width_ = alph_dec->width_;
dec->height_ = alph_dec->height_; dec->height_ = alph_dec->height_;
@ -1603,12 +1544,11 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (!ok) goto Err; if (!ok) goto Err;
// Only set here, once we are sure it is valid (to avoid thread races).
alph_dec->vp8l_dec_ = dec;
return 1; return 1;
Err: Err:
VP8LDelete(dec); VP8LDelete(alph_dec->vp8l_dec_);
alph_dec->vp8l_dec_ = NULL;
return 0; return 0;
} }
@ -1690,19 +1630,12 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
if (!AllocateInternalBuffers32b(dec, io->width)) goto Err; if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;
#if !defined(WEBP_REDUCE_SIZE)
if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
#else
if (io->use_scaling) {
dec->status_ = VP8_STATUS_INVALID_PARAM;
goto Err;
}
#endif
if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) { if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
// need the alpha-multiply functions for premultiplied output or rescaling // need the alpha-multiply functions for premultiplied output or rescaling
WebPInitAlphaProcessing(); WebPInitAlphaProcessing();
} }
if (!WebPIsRGBMode(dec->output_->colorspace)) { if (!WebPIsRGBMode(dec->output_->colorspace)) {
WebPInitConvertARGBToYUV(); WebPInitConvertARGBToYUV();
if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing(); if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing();

View File

@ -12,14 +12,14 @@
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
// Vikas Arora(vikaas.arora@gmail.com) // Vikas Arora(vikaas.arora@gmail.com)
#ifndef WEBP_DEC_VP8LI_DEC_H_ #ifndef WEBP_DEC_VP8LI_H_
#define WEBP_DEC_VP8LI_DEC_H_ #define WEBP_DEC_VP8LI_H_
#include <string.h> // for memcpy() #include <string.h> // for memcpy()
#include "src/dec/webpi_dec.h" #include "./webpi_dec.h"
#include "src/utils/bit_reader_utils.h" #include "../utils/bit_reader_utils.h"
#include "src/utils/color_cache_utils.h" #include "../utils/color_cache_utils.h"
#include "src/utils/huffman_utils.h" #include "../utils/huffman_utils.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -37,7 +37,7 @@ struct VP8LTransform {
int bits_; // subsampling bits defining transform window. int bits_; // subsampling bits defining transform window.
int xsize_; // transform window X index. int xsize_; // transform window X index.
int ysize_; // transform window Y index. int ysize_; // transform window Y index.
uint32_t* data_; // transform data. uint32_t *data_; // transform data.
}; };
typedef struct { typedef struct {
@ -48,23 +48,23 @@ typedef struct {
int huffman_mask_; int huffman_mask_;
int huffman_subsample_bits_; int huffman_subsample_bits_;
int huffman_xsize_; int huffman_xsize_;
uint32_t* huffman_image_; uint32_t *huffman_image_;
int num_htree_groups_; int num_htree_groups_;
HTreeGroup* htree_groups_; HTreeGroup *htree_groups_;
HuffmanCode* huffman_tables_; HuffmanCode *huffman_tables_;
} VP8LMetadata; } VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder; typedef struct VP8LDecoder VP8LDecoder;
struct VP8LDecoder { struct VP8LDecoder {
VP8StatusCode status_; VP8StatusCode status_;
VP8LDecodeState state_; VP8LDecodeState state_;
VP8Io* io_; VP8Io *io_;
const WebPDecBuffer* output_; // shortcut to io->opaque->output const WebPDecBuffer *output_; // shortcut to io->opaque->output
uint32_t* pixels_; // Internal data: either uint8_t* for alpha uint32_t *pixels_; // Internal data: either uint8_t* for alpha
// or uint32_t* for BGRA. // or uint32_t* for BGRA.
uint32_t* argb_cache_; // Scratch buffer for temporary BGRA storage. uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
VP8LBitReader br_; VP8LBitReader br_;
int incremental_; // if true, incremental decoding is expected int incremental_; // if true, incremental decoding is expected
@ -86,8 +86,8 @@ struct VP8LDecoder {
// or'd bitset storing the transforms types. // or'd bitset storing the transforms types.
uint32_t transforms_seen_; uint32_t transforms_seen_;
uint8_t* rescaler_memory; // Working memory for rescaling work. uint8_t *rescaler_memory; // Working memory for rescaling work.
WebPRescaler* rescaler; // Common rescaler for all channels. WebPRescaler *rescaler; // Common rescaler for all channels.
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -132,4 +132,4 @@ void VP8LDelete(VP8LDecoder* const dec);
} // extern "C" } // extern "C"
#endif #endif
#endif // WEBP_DEC_VP8LI_DEC_H_ #endif /* WEBP_DEC_VP8LI_H_ */

View File

@ -13,11 +13,11 @@
#include <stdlib.h> #include <stdlib.h>
#include "src/dec/vp8i_dec.h" #include "./vp8i_dec.h"
#include "src/dec/vp8li_dec.h" #include "./vp8li_dec.h"
#include "src/dec/webpi_dec.h" #include "./webpi_dec.h"
#include "src/utils/utils.h" #include "../utils/utils.h"
#include "src/webp/mux_types.h" // ALPHA_FLAG #include "../webp/mux_types.h" // ALPHA_FLAG
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// RIFF layout is: // RIFF layout is:
@ -421,9 +421,7 @@ VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) {
NULL, NULL, NULL, &has_animation, NULL, NULL, NULL, &has_animation,
NULL, headers); NULL, headers);
if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) {
// The WebPDemux API + libwebp can be used to decode individual // TODO(jzern): full support of animation frames will require API additions.
// uncomposited frames or the WebPAnimDecoder can be used to fully
// reconstruct them (see webp/demux.h).
if (has_animation) { if (has_animation) {
status = VP8_STATUS_UNSUPPORTED_FEATURE; status = VP8_STATUS_UNSUPPORTED_FEATURE;
} }

View File

@ -11,15 +11,15 @@
// //
// Author: somnath@google.com (Somnath Banerjee) // Author: somnath@google.com (Somnath Banerjee)
#ifndef WEBP_DEC_WEBPI_DEC_H_ #ifndef WEBP_DEC_WEBPI_H_
#define WEBP_DEC_WEBPI_DEC_H_ #define WEBP_DEC_WEBPI_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "src/utils/rescaler_utils.h" #include "../utils/rescaler_utils.h"
#include "src/dec/vp8_dec.h" #include "./vp8_dec.h"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// WebPDecParams: Decoding output parameters. Transient internal object. // WebPDecParams: Decoding output parameters. Transient internal object.
@ -130,4 +130,4 @@ int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
} // extern "C" } // extern "C"
#endif #endif
#endif // WEBP_DEC_WEBPI_DEC_H_ #endif /* WEBP_DEC_WEBPI_H_ */

View File

@ -1,18 +1,14 @@
AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir)
lib_LTLIBRARIES = libwebpdemux.la lib_LTLIBRARIES = libwebpdemux.la
libwebpdemux_la_SOURCES = libwebpdemux_la_SOURCES =
libwebpdemux_la_SOURCES += anim_decode.c demux.c libwebpdemux_la_SOURCES += anim_decode.c demux.c
libwebpdemuxinclude_HEADERS = libwebpdemuxinclude_HEADERS =
libwebpdemuxinclude_HEADERS += ../webp/decode.h
libwebpdemuxinclude_HEADERS += ../webp/demux.h libwebpdemuxinclude_HEADERS += ../webp/demux.h
libwebpdemuxinclude_HEADERS += ../webp/mux_types.h libwebpdemuxinclude_HEADERS += ../webp/mux_types.h
libwebpdemuxinclude_HEADERS += ../webp/types.h libwebpdemuxinclude_HEADERS += ../webp/types.h
noinst_HEADERS =
noinst_HEADERS += ../webp/format_constants.h
libwebpdemux_la_LIBADD = ../libwebp.la libwebpdemux_la_LIBADD = ../libwebp.la
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:7:0 libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:2:0
libwebpdemuxincludedir = $(includedir)/webp libwebpdemuxincludedir = $(includedir)/webp
pkgconfig_DATA = libwebpdemux.pc pkgconfig_DATA = libwebpdemux.pc

View File

@ -11,15 +11,15 @@
// //
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "src/webp/config.h" #include "../webp/config.h"
#endif #endif
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include "src/utils/utils.h" #include "../utils/utils.h"
#include "src/webp/decode.h" #include "../webp/decode.h"
#include "src/webp/demux.h" #include "../webp/demux.h"
#define NUM_CHANNELS 4 #define NUM_CHANNELS 4
@ -346,15 +346,12 @@ int WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
{ {
const uint8_t* in = iter.fragment.bytes; const uint8_t* in = iter.fragment.bytes;
const size_t in_size = iter.fragment.size; const size_t in_size = iter.fragment.size;
const uint32_t stride = width * NUM_CHANNELS; // at most 25 + 2 bits const size_t out_offset =
const uint64_t out_offset = (uint64_t)iter.y_offset * stride + (iter.y_offset * width + iter.x_offset) * NUM_CHANNELS;
(uint64_t)iter.x_offset * NUM_CHANNELS; // 53b
const uint64_t size = (uint64_t)iter.height * stride; // at most 25 + 27b
WebPDecoderConfig* const config = &dec->config_; WebPDecoderConfig* const config = &dec->config_;
WebPRGBABuffer* const buf = &config->output.u.RGBA; WebPRGBABuffer* const buf = &config->output.u.RGBA;
if ((size_t)size != size) goto Error; buf->stride = NUM_CHANNELS * width;
buf->stride = (int)stride; buf->size = buf->stride * iter.height;
buf->size = (size_t)size;
buf->rgba = dec->curr_frame_ + out_offset; buf->rgba = dec->curr_frame_ + out_offset;
if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) { if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) {

View File

@ -11,21 +11,21 @@
// //
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "src/webp/config.h" #include "../webp/config.h"
#endif #endif
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "src/utils/utils.h" #include "../utils/utils.h"
#include "src/webp/decode.h" // WebPGetFeatures #include "../webp/decode.h" // WebPGetFeatures
#include "src/webp/demux.h" #include "../webp/demux.h"
#include "src/webp/format_constants.h" #include "../webp/format_constants.h"
#define DMUX_MAJ_VERSION 1 #define DMUX_MAJ_VERSION 0
#define DMUX_MIN_VERSION 2 #define DMUX_MIN_VERSION 3
#define DMUX_REV_VERSION 0 #define DMUX_REV_VERSION 2
typedef struct { typedef struct {
size_t start_; // start location of the data size_t start_; // start location of the data
@ -205,14 +205,12 @@ static void SetFrameInfo(size_t start_offset, size_t size,
frame->complete_ = complete; frame->complete_ = complete;
} }
// Store image bearing chunks to 'frame'. 'min_size' is an optional size // Store image bearing chunks to 'frame'.
// requirement, it may be zero.
static ParseStatus StoreFrame(int frame_num, uint32_t min_size, static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
MemBuffer* const mem, Frame* const frame) { MemBuffer* const mem, Frame* const frame) {
int alpha_chunks = 0; int alpha_chunks = 0;
int image_chunks = 0; int image_chunks = 0;
int done = (MemDataSize(mem) < CHUNK_HEADER_SIZE || int done = (MemDataSize(mem) < min_size);
MemDataSize(mem) < min_size);
ParseStatus status = PARSE_OK; ParseStatus status = PARSE_OK;
if (done) return PARSE_NEED_MORE_DATA; if (done) return PARSE_NEED_MORE_DATA;
@ -312,7 +310,6 @@ static ParseStatus ParseAnimationFrame(
int bits; int bits;
MemBuffer* const mem = &dmux->mem_; MemBuffer* const mem = &dmux->mem_;
Frame* frame; Frame* frame;
size_t start_offset;
ParseStatus status = ParseStatus status =
NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame); NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame);
if (status != PARSE_OK) return status; if (status != PARSE_OK) return status;
@ -333,11 +330,7 @@ static ParseStatus ParseAnimationFrame(
// Store a frame only if the animation flag is set there is some data for // Store a frame only if the animation flag is set there is some data for
// this frame is available. // this frame is available.
start_offset = mem->start_;
status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame); status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame);
if (status != PARSE_ERROR && mem->start_ - start_offset > anmf_payload_size) {
status = PARSE_ERROR;
}
if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) { if (status != PARSE_ERROR && is_animation && frame->frame_num_ > 0) {
added_frame = AddFrame(dmux, frame); added_frame = AddFrame(dmux, frame);
if (added_frame) { if (added_frame) {
@ -408,9 +401,9 @@ static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame));
if (frame == NULL) return PARSE_ERROR; if (frame == NULL) return PARSE_ERROR;
// For the single image case we allow parsing of a partial frame, so no // For the single image case we allow parsing of a partial frame, but we need
// minimum size is imposed here. // at least CHUNK_HEADER_SIZE for parsing.
status = StoreFrame(1, 0, &dmux->mem_, frame); status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame);
if (status != PARSE_ERROR) { if (status != PARSE_ERROR) {
const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG); const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG);
// Clear any alpha when the alpha flag is missing. // Clear any alpha when the alpha flag is missing.

View File

@ -6,8 +6,8 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,2,0 FILEVERSION 0,3,0,2
PRODUCTVERSION 1,0,2,0 PRODUCTVERSION 0,3,0,2
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -24,12 +24,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Google, Inc." VALUE "CompanyName", "Google, Inc."
VALUE "FileDescription", "libwebpdemux DLL" VALUE "FileDescription", "libwebpdemux DLL"
VALUE "FileVersion", "1.2.0" VALUE "FileVersion", "0.3.2"
VALUE "InternalName", "libwebpdemux.dll" VALUE "InternalName", "libwebpdemux.dll"
VALUE "LegalCopyright", "Copyright (C) 2019" VALUE "LegalCopyright", "Copyright (C) 2017"
VALUE "OriginalFilename", "libwebpdemux.dll" VALUE "OriginalFilename", "libwebpdemux.dll"
VALUE "ProductName", "WebP Image Demuxer" VALUE "ProductName", "WebP Image Demuxer"
VALUE "ProductVersion", "1.2.0" VALUE "ProductVersion", "0.3.2"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

Some files were not shown because too many files have changed in this diff Show More