Compare commits

..

7 Commits
1.2.1 ... 1.0.1

Author SHA1 Message Date
3991eb5fef GetBackwardReferences: fail on alloc error
previously failures in the call to
VP8LBackwardReferencesTraceBackwards() would be ignored which, though it
wouldn't result in a crash, would produce non-deterministic output

Change-Id: Id9890a60883c3270ec75e968506d46eea32b76d4
(cherry picked from commit e3cfafaf71)
(cherry picked from commit 20ef03ee35)
(cherry picked from commit 89e226a3c7)
2022-04-06 21:56:48 -07:00
075bc46697 BackwardReferencesHashChainDistanceOnly: fix segfault on OOM
change CostManager to calloc to avoid frees on undefined pointer
values in CostManagerClear() should the cost_model allocation succeed,
but the cost_manager allocation fail

since:
v0.5.0-93-g3e023c17 Speed-up BackwardReferencesHashChainDistanceOnly.

Tested:
for i in `seq 1 639`; do
  export MALLOC_FAIL_AT=$i
  ./examples/cwebp -m 6 -q 100 -lossless jpeg_file
done

Bug: webp:565
Change-Id: I376d81e6f41eb73529053e9e30c142b4b4f6b45b
(cherry picked from commit a828a59b49)
(cherry picked from commit dd80bb4343)
(cherry picked from commit 4d0964cd0c)
2022-04-06 21:56:48 -07:00
2ba7e11210 VP8LEncodeStream: fix segfault on OOM
initialize bw_side before calling EncoderAnalyze() & EncoderInit() which
may fail; previously this would cause a free of an invalid pointer in
VP8LBitWriterWipeOut().

since at least:
v0.6.0-120-gf8c2ac15 Multi-thread the lossless cruncher.

Tested:
for i in `seq 1 639`; do
  export MALLOC_FAIL_AT=$i
  ./examples/cwebp -m 6 -q 100 -lossless jpeg_file
done

Bug: webp:565
Change-Id: I1c95883834b6e4b13aee890568ce3bad0f4266f0
(cherry picked from commit fe153fae98)
(cherry picked from commit ddd65f0d19)
(cherry picked from commit 5d805f7205)
2022-04-06 21:56:48 -07:00
a8f86c2ef1 alpha_processing_neon.c: fix 0x01... typo
one instance was overlong leading to a int64->uint32 conversion warning

Change-Id: I56d5ab75d89960c79293f62cd489d7ab519bbc34
(cherry picked from commit 03d1219055)
2022-03-08 19:37:43 +00:00
14718202b8 alpha_processing_neon.c: fix Dispatch/ExtractAlpha_NEON
the trailing width % 8 bytes would clear the upper bytes of
alpha_mask as they're done one at a time

since:
49d0280d NEON: implement several alpha-processing functions

Change-Id: Iff76c0af3094597285a6aa6ed032b345f9856aae
(cherry picked from commit 924e7ca654)
2022-03-03 18:07:05 +00:00
85193ec6aa Fix lossless encoding for MIPS.
Bug: webp:558
Change-Id: I3d3ddb64ed26a8d8ff5664664c5f20f6eadfeb4f
(cherry picked from commit e4cbcdd2b5)
2022-03-02 02:56:49 +00:00
067423687d Rescaler: fix rounding error
We saturate the result to [0..255]
It's the easiest and safest, given the wide variety of scaling
range we cover: we're not using floats, so precision is always
an issue at one end or the other of the scaling spectrum.

we also use:
  round(a - floor(b))
instead of:
  floor(a - round(b))
to handle difficult cases (ratio ~= .99, e.g.)

MIPS code is still disabled (and wrong)

Change-Id: I18d3f5ddc4c524879c257b928329b1c648fa7fb5
(cherry picked from commit ab2dc8939f)
2019-04-01 19:37:31 -07:00
174 changed files with 2582 additions and 12320 deletions

1
.gitattributes vendored
View File

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

15
.gitignore vendored
View File

@ -1,7 +1,6 @@
*.l[ao]
*.[ao]
*.pc
.DS_Store
.deps
.libs
/aclocal.m4
@ -21,11 +20,9 @@
Makefile
Makefile.in
examples/anim_diff
examples/anim_dump
examples/[cdv]webp
examples/gif2webp
examples/img2webp
examples/webpinfo
examples/webpmux
src/webp/config.h*
src/webp/stamp-h1
@ -34,21 +31,11 @@ src/webp/stamp-h1
*.idb
*.pdb
/iosbuild
/xcframeworkbuild
/WebP*.*framework
/WebP.framework
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
.gradle
/build
extras/get_disto
extras/vwebp_sdl
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 <johann.koenig@duck.com> <johannkoenig@google.com>
<johann.koenig@duck.com> <johannkoenig@google.com>
Mikołaj Zalewski <mikolajz@google.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>
<vikasa@google.com> <vikasa@gmail.com>
<vikasa@google.com> <vikaas.arora@gmail.com>
@ -11,4 +10,3 @@ Vikas Arora <vikasa@google.com>
Tamar Levy <tamar.levy@intel.com>
<qrczak@google.com> <qrczak>
Hui Su <huisu@google.com>
James Zern <jzern@google.com>

11
AUTHORS
View File

@ -1,19 +1,13 @@
Contributors:
- Aidan O'Loan (aidanol at gmail dot com)
- Alan Browning (browning 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)
- Christopher Degawa (ccom at randomderp dot com)
- Clement Courbet (courbet at google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com)
- Hui Su (huisu at google dot com)
- Ilya Kurdyukov (jpegqs at gmail dot com)
- Ingvar Stepanyan (rreverser at google dot com)
- James Zern (jzern at google dot com)
- Jan Engelhardt (jengelh at medozas dot de)
- 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)
- Jyrki Alakuijala (jyrki at google dot com)
- Konstantin Ivlev (tomskside at gmail dot com)
@ -26,7 +20,6 @@ Contributors:
- Mislav Bradac (mislavm at google dot com)
- Nico Weber (thakis 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)
- Parag Salasakar (img dot mips1 at gmail dot com)
- Pascal Massimino (pascal dot massimino at gmail dot com)
@ -45,7 +38,5 @@ Contributors:
- Vikas Arora (vikasa 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)
- Yannis Guyon (yguyon at google dot com)
- Zhi An Ng (zhin at chromium dot org)

View File

@ -74,7 +74,6 @@ dsp_dec_srcs := \
src/dsp/lossless_msa.c \
src/dsp/lossless_neon.$(NEON) \
src/dsp/lossless_sse2.c \
src/dsp/lossless_sse41.c \
src/dsp/rescaler.c \
src/dsp/rescaler_mips32.c \
src/dsp/rescaler_mips_dsp_r2.c \
@ -98,7 +97,6 @@ dsp_enc_srcs := \
src/dsp/cost.c \
src/dsp/cost_mips32.c \
src/dsp/cost_mips_dsp_r2.c \
src/dsp/cost_neon.$(NEON) \
src/dsp/cost_sse2.c \
src/dsp/enc.c \
src/dsp/enc_mips32.c \

View File

@ -1,27 +1,9 @@
# 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)
if(POLICY CMP0072)
cmake_policy(SET CMP0072 NEW)
endif()
project(WebP C)
# Options for coder / decoder executables.
if(NOT EMSCRIPTEN)
# Disable SIMD on Emscripten by default, as it's a new unstable Wasm feature.
# Users can still explicitly opt-in to make a SIMD-enabled build.
set(WEBP_ENABLE_SIMD_DEFAULT ON)
endif()
option(WEBP_ENABLE_SIMD "Enable any SIMD optimization."
${WEBP_ENABLE_SIMD_DEFAULT})
option(WEBP_ENABLE_SIMD "Enable any SIMD optimization." ON)
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)
@ -29,23 +11,15 @@ 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_LIBWEBPMUX "Build the libwebpmux library." 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_USE_THREAD "Enable threading support" ON)
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_ENABLE_SIMD OFF)
set(WEBP_BUILD_ANIM_UTILS OFF)
set(WEBP_BUILD_CWEBP OFF)
set(WEBP_BUILD_DWEBP OFF)
@ -55,11 +29,6 @@ if(WEBP_BUILD_WEBP_JS)
set(WEBP_BUILD_WEBPINFO OFF)
set(WEBP_BUILD_WEBPMUX OFF)
set(WEBP_BUILD_EXTRAS OFF)
set(WEBP_USE_THREAD OFF)
if(WEBP_ENABLE_SIMD)
message("wasm2js does not support SIMD, disabling webp.js generation.")
endif()
endif()
set(WEBP_DEP_LIBRARIES)
@ -67,7 +36,7 @@ set(WEBP_DEP_INCLUDE_DIRS)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release"
CACHE STRING "Build type: Release, Debug, MinSizeRel or RelWithDebInfo"
CACHE "Build type: Release, Debug, MinSizeRel or RelWithDebInfo" STRING
FORCE)
endif()
@ -81,21 +50,11 @@ if(WEBP_ENABLE_SWAP_16BIT_CSP)
add_definitions(-DWEBP_SWAP_16BIT_CSP=1)
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.
@ -103,7 +62,6 @@ if(ANDROID)
include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
add_library(cpufeatures STATIC
${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
list(APPEND INSTALLED_LIBRARIES cpufeatures)
target_link_libraries(cpufeatures dl)
set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures)
set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS}
@ -188,29 +146,6 @@ add_definitions(-DHAVE_CONFIG_H)
# ##############################################################################
# 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)
@ -237,9 +172,6 @@ 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
@ -279,16 +211,11 @@ add_library(webp
$<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_include_directories(
webp
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include>)
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;\
@ -323,10 +250,10 @@ ${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
configure_pkg_config("src/demux/libwebpdemux.pc")
# Set the version numbers.
macro(set_version FILE TARGET_NAME NAME_IN_MAKEFILE)
function(parse_version FILE NAME VAR)
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/src/${FILE} SOURCE_FILE)
string(REGEX MATCH
"${NAME_IN_MAKEFILE}_la_LDFLAGS[^\n]* -version-info [0-9:]+"
"${NAME}_la_LDFLAGS[^\n]* -version-info [0-9:]+"
TMP
${SOURCE_FILE})
string(REGEX MATCH
@ -335,35 +262,29 @@ macro(set_version FILE TARGET_NAME NAME_IN_MAKEFILE)
${TMP})
string(REGEX
REPLACE ":"
" "
LT_VERSION
"."
VERSION
${TMP})
# See the libtool docs for more information:
# https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
#
# c=<current>, a=<age>, r=<revision>
#
# libtool generates a .so file as .so.[c-a].a.r, while -version-info c:r:a is
# passed to libtool.
#
# We set FULL = [c-a].a.r and MAJOR = [c-a].
separate_arguments(LT_VERSION)
list(GET LT_VERSION 0 LT_CURRENT)
list(GET LT_VERSION 1 LT_REVISION)
list(GET LT_VERSION 2 LT_AGE)
math(EXPR LT_CURRENT_MINUS_AGE "${LT_CURRENT} - ${LT_AGE}")
set_target_properties(
${TARGET_NAME}
PROPERTIES VERSION
${LT_CURRENT_MINUS_AGE}.${LT_AGE}.${LT_REVISION}
SOVERSION
${LT_CURRENT_MINUS_AGE})
endmacro()
set_version(Makefile.am webp webp)
set_version(Makefile.am webpdecoder webpdecoder)
set_version(demux/Makefile.am webpdemux webpdemux)
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\\.]+\\]"
@ -375,7 +296,7 @@ string(REGEX MATCH
${TMP})
# Define the libraries to install.
list(APPEND INSTALLED_LIBRARIES webpdecoder webp webpdemux)
set(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)
@ -391,12 +312,6 @@ foreach(I_FILE RANGE ${WEBP_SIMD_FILES_TO_INCLUDE_RANGE})
${SIMD_COMPILE_FLAG})
endforeach()
if(NOT WEBP_BUILD_LIBWEBPMUX)
set(WEBP_BUILD_GIF2WEBP OFF)
set(WEBP_BUILD_IMG2WEBP OFF)
set(WEBP_BUILD_WEBPMUX OFF)
endif()
if(WEBP_BUILD_GIF2WEBP AND NOT GIF_FOUND)
set(WEBP_BUILD_GIF2WEBP OFF)
endif()
@ -416,21 +331,20 @@ if(WEBP_BUILD_ANIM_UTILS
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "EXAMPLEUTIL_SRCS"
"example_util_[^ ]*")
list(APPEND EXAMPLEUTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h)
add_library(exampleutil STATIC ${EXAMPLEUTIL_SRCS})
target_link_libraries(exampleutil imageioutil)
add_library(exampleutil ${EXAMPLEUTIL_SRCS})
target_include_directories(
exampleutil
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEIOUTILS_SRCS"
"imageio_util_[^ ]*")
add_library(imageioutil STATIC ${IMAGEIOUTILS_SRCS})
add_library(imageioutil ${IMAGEIOUTILS_SRCS})
target_link_libraries(imageioutil webp)
# Image-decoding utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS"
"imagedec_[^ ]*")
add_library(imagedec STATIC ${IMAGEDEC_SRCS})
add_library(imagedec ${IMAGEDEC_SRCS})
target_link_libraries(imagedec
imageioutil
webpdemux
@ -440,8 +354,8 @@ if(WEBP_BUILD_ANIM_UTILS
# Image-encoding utility library.
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEENC_SRCS"
"imageenc_[^ ]*")
add_library(imageenc STATIC ${IMAGEENC_SRCS})
target_link_libraries(imageenc imageioutil webp)
add_library(imageenc ${IMAGEENC_SRCS})
target_link_libraries(imageenc webp)
set_property(TARGET exampleutil
imageioutil
@ -469,14 +383,19 @@ if(WEBP_BUILD_CWEBP)
install(TARGETS cwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(WEBP_BUILD_LIBWEBPMUX)
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})
set_version(mux/Makefile.am libwebpmux webpmux)
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;\
@ -529,12 +448,12 @@ if(WEBP_BUILD_VWEBP)
target_link_libraries(vwebp
${OPENGL_LIBRARIES}
exampleutil
${GLUT_glut_LIBRARY}
GLUT::GLUT
imageioutil
webp
webpdemux)
target_include_directories(vwebp
PRIVATE ${GLUT_INCLUDE_DIR}
PRIVATE GLUT::GLUT
${CMAKE_CURRENT_BINARY_DIR}/src
${OPENGL_INCLUDE_DIR})
install(TARGETS vwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
@ -582,13 +501,13 @@ if(WEBP_BUILD_EXTRAS)
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})
target_include_directories(webp_quality PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS webp_quality RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# vwebp_sdl
find_package(SDL)
@ -603,25 +522,23 @@ if(WEBP_BUILD_EXTRAS)
${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 EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp)
target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
endif()
# 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 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)
# WASM version
add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
@ -629,9 +546,9 @@ if(WEBP_BUILD_WEBP_JS)
target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
set_target_properties(
webp_wasm
PROPERTIES LINK_FLAGS "-s WASM=1 \
PROPERTIES LINK_FLAGS "-s WASM=1 -s 'BINARYEN_METHOD=\"native-wasm\"' \
-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
-s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN)
@ -649,6 +566,7 @@ if(WEBP_BUILD_ANIM_UTILS)
imageenc
imageioutil
webp
libwebpmux
webpdemux
${WEBP_DEP_GIF_LIBRARIES})
target_include_directories(anim_diff PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
@ -664,12 +582,14 @@ if(WEBP_BUILD_ANIM_UTILS)
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.
include(GNUInstallDirs)
install(TARGETS ${INSTALLED_LIBRARIES}
EXPORT ${PROJECT_NAME}Targets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp

View File

@ -1,29 +0,0 @@
# How to Contribute
We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.
## Contributor License Agreement
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution;
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Code reviews
All submissions, including submissions by project members, require review. We
use a [Gerrit](https://www.gerritcodereview.com) instance hosted at
https://chromium-review.googlesource.com for this purpose. See the
[WebM Project page](https://www.webmproject.org/code/contribute/submitting-patches/)
for additional details.
## Community Guidelines
This project follows
[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).

300
ChangeLog
View File

@ -1,301 +1,15 @@
d9191588 fuzzer/*: normalize src/ includes
53b6f762 fix indent
731246ba update ChangeLog (tag: v1.2.1-rc2)
d250f01d dsp/*: use WEBP_HAVE_* to determine Init availability
3a4d3ecd update NEWS
b2bc8093 bump version to 1.2.1
e542fc7a update AUTHORS
e0241154 Merge "libwebp/CMake: Add <BUILD_INTERFACE> to webp incl" into main
edea6444 libwebp/CMake: Add <BUILD_INTERFACE> to webp incl
ece18e55 dsp.h: respect --disable-sse2/sse4.1/neon
a89a3230 wicdec: support alpha from WebP WIC decoder
26f4aa01 Merge "alpha_processing: fix visual studio warnings" into main
8f594663 alpha_processing: fix visual studio warnings
46d844e6 Merge "cpu.cmake: fix compiler flag detection w/3.17.0+" into main
298d26ea Merge changes I593adf92,If20675e7,Ifac68eac into main
a1e5dae0 alpha_processing*: use WEBP_RESTRICT qualifier
327ef24f cpu.cmake: fix compiler flag detection w/3.17.0+
f70819de configure: enable libwebpmux by default
dc7e2b42 configure: add informational notices when disabling binaries
9df23ddd configure: move lib flag checks before binaries
a2e18f10 Merge "WebPConfig.config.in: correct WEBP_INCLUDE_DIRS" into main
e1a8d4f3 Merge "bit_reader_inl_utils: uniformly apply WEBP_RESTRICT" into main
4de35f43 rescaler.c: fix alignment
0f13eec7 bit_reader_inl_utils: uniformly apply WEBP_RESTRICT
277d3074 Fix size_t overflow in WebPRescalerInit
97adbba5 WebPConfig.config.in: correct WEBP_INCLUDE_DIRS
b60d4603 advanced_api_fuzzer: add extreme config value coverage
72fe52f6 anim_encode.c,cosmetics: normalize indent
116d235c anim_encode: Fix encoded_frames_[] overflow
6f445b3e CMake: set CMP0072 to NEW
b1cf887f define WEBP_RESTRICT for MSVC
3e265136 Add WEBP_RESTRICT & use it in VP8BitReader
f6d29247 vp8l_dec::ProcessRows: fix int overflow in multiply
de3b4ba8 CMake: add WEBP_BUILD_LIBWEBPMUX
7f09d3d1 CMakeLists.txt: rm libwebpmux dep from anim_{diff,dump}
4edea4a6 Init{RGB,YUV}Rescaler: fix a few more int overflows
c9e26bdb rescaler_utils: set max valid scaled w/h to INT_MAX/2
28d488e6 utils.h: add SizeOverflow()
695bdaa2 Export/EmitRescaledRowsRGBA: fix pointer offset int overflow
685d073e Init{RGB,YUV}Rescaler: fix int overflows in multiplication
d38bd0dd WebPFlipBuffer: fix integer overflow
109ff0f1 utils: allow MALLOC_LIMIT to indicate a max
a2fce867 WebPRescalerImportRowExpand_C: promote some vals before multiply
776983d4 AllocateBuffer: fix int multiplication overflow check
315abbd6 Merge "Revert "Do not use a palette for one color images.""
eae815d0 Merge changes Ica3bbf75,I82f82954
afbca5a1 Require Emscripten 2.0.18
3320416b CMakeLists,emscripten: use EXPORTED_RUNTIME_METHODS
29145ed6 Update README instructions for using Emscripten
1f579139 cosmetics: remove use of 'sanity' / 'master'
29b6129c WebPAnimEncoderNewInternal: remove some unnecessary inits
b60869a1 Revert "Do not use a palette for one color images."
6fb4cddc demux: move padded size calc post unpadded validation
05b72d42 vp8l_enc.c: normalize index types
b6513fba Do not use a palette for one color images.
98bbe35b Fix multi-threading with palettes.
b1674240 Add modified Zeng's method to palette sorting.
88c90c45 add CONTRIBUTING.md
6a9916d7 WebPRescalerInit: add missing int64_t promotion
b6cf52d5 WebPIoInitFromOptions: treat use_scaling as a bool
3b12b7f4 WebPIoInitFromOptions: treat use_cropping as a bool
595fa13f add WebPCheckCropDimensions()
8fdaecb0 Disable cross-color when palette is used.
8933bac2 WebPIoInitFromOptions: respect incoming bypass_filtering val
7d416ff0 webpdec,cosmetics: match error text to function call
ec6cfeb5 Fix typo on WebPPictureAlloc() in README
7e58a1a2 *.cmake: add license header
5651a6b2 cmake: fix .so versioning
25ae67b3 xcframeworkbuild.sh: add arm64 simulator target
5d4ee4c3 cosmetics: remove use of the term 'dummy'
01b38ee1 faster CollectColorXXXTransforms_SSE41
652aa344 Merge "Use BitCtz for FastSLog2Slow_C"
0320e1e3 add the missing default BitsCtz() code
8886f620 Use BitCtz for FastSLog2Slow_C
fae41617 faster CombinedShannonEntropy_SSE2
5bd2704e Introduce the BitCtz() function.
fee64287 Merge "wicdec,icc: treat unsupported op as non-fatal"
33ddb894 lossless_sse{2,41}: remove some unneeded includes
b27ea852 wicdec,icc: treat unsupported op as non-fatal
b78494a9 Merge "Fix undefined signed shift."
e79974cd Fix undefined signed shift.
a8853394 SSE4.1 versions of BGRA to RGB/BGR color-space conversions
a09a6472 SSE4.1 version of TransformColorInverse
401da22b Merge "pngdec: check version before using png_get_chunk_malloc_max"
26907822 pngdec: check version before using png_get_chunk_malloc_max
06c1e72e Code cleanup
8f0d41aa Merge changes Id135bbf4,I99e59797
373eb170 gif2webp: don't store loop-count if there's only 1 frame
759b9d5a cmake: add WEBP_USE_THREAD option
926ce921 cmake: don't install binaries from extras/
9c367bc6 WebPAnimDecoderNewInternal: validate bitstream before alloc
47f64f6e filters_sse2: import Chromium change
cc3577e9 fuzzer/*: use src/ based include paths
004d77ff Merge tag 'v1.2.0'
fedac6cc update ChangeLog (tag: v1.2.0-rc3, tag: v1.2.0)
170a8712 Fix check_c_source_compiles with pthread.
ceddb5fc Fix check_c_source_compiles with pthread.
85995719 disable CombinedShannonEntropy_SSE2 on x86
289757fe TiffDec: enforce stricter mem/dimension limit on tiles
8af7436f Merge "{ios,xcframework}build.sh: make min version(s) more visible" into 1.2.0
e56c3c5b pngdec: raise memory limit if needed
8696147d 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
8df77fb1 animdecoder_fuzzer: fix memory leak
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
@ -741,7 +455,7 @@ 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)
50d1a848 update ChangeLog (tag: v0.6.0, origin/0.6.0, 0.6.0)
20a7fea0 extras/Makefile.am: fix libwebpextras.la reference
415f3ffe update ChangeLog (tag: v0.6.0-rc3)
3c6d1224 update NEWS
@ -818,7 +532,7 @@ b016cb91 NEON: faster fancy upsampling
f04eb376 Merge tag 'v0.5.2'
341d711c NEON: 5% faster conversion to RGB565 and RGBA4444
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
d9120271 jpegdec: correct ContextFill signature
24eb3940 Remove some errors when compiling the code as C++.
@ -1105,7 +819,7 @@ bbb6ecd9 Merge "Add MSA optimized distortion functions"
c0991a14 io,EmitRescaledAlphaYUV: factor out a common expr
48bf5ed1 build.gradle: remove tab
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()
435308e0 Add MSA optimized encoder transform functions
dce64bfa Add MSA optimized alpha filter functions
@ -1299,7 +1013,7 @@ b74657fb configure: fix builtin detection w/-Werror
6c1d7631 avoid Yoda style for comparison
8ce975ac SSE optimization for vector mismatch.
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
4c7f565f update NEWS
1f62b6b2 update AUTHORS
@ -2083,7 +1797,7 @@ b5a36cc9 add -near_lossless [0..100] experimental option
0524d9e5 dsp: detect mips64 & disable mips32 code
d3485d96 cwebp.1: fix quality description placement
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.
f59c0b4b iosbuild.sh: specify optimization flags
8d34ea3e update ChangeLog (tag: v0.4.1-rc1)
@ -2468,7 +2182,7 @@ ea59a8e9 Merge "Merge tag 'v0.4.0'"
effcb0fd Merge tag 'v0.4.0'
7c76255d autoconf: update ax_pthread.m4
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
29625340 Merge "gif2webp: don't use C99 %zu" into 0.4.0
3b9f9dd0 gif2webp: don't use C99 %zu
@ -3244,7 +2958,7 @@ a61a824b Merge "Add NULL check in chunk APIs"
a0770727 mux struct naming
6c66dde8 Merge "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:
3bb4bbeb Merge "Mux API change:"
d0c79f05 Mux API change:

View File

@ -28,7 +28,7 @@ PLATFORM_LDFLAGS = /SAFESEH
NOLOGO = /nologo
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 = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
@ -129,16 +129,12 @@ LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
CFGSET = TRUE
!ENDIF
!IF "$(UNICODE)" == "1"
CFLAGS = $(CFLAGS) /D_UNICODE /DUNICODE
!ENDIF
#######################
# Usage
#
!IF "$(CFGSET)" == "FALSE"
!MESSAGE Usage: nmake /f Makefile.vc [CFG=<config>]
!MESSAGE . [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [UNICODE=1] [<target>]
!MESSAGE . [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [<target>]
!MESSAGE
!MESSAGE where <config> is one of:
!MESSAGE - release-static - release static library
@ -215,7 +211,6 @@ DSP_DEC_OBJS = \
$(DIROBJ)\dsp\lossless_msa.obj \
$(DIROBJ)\dsp\lossless_neon.obj \
$(DIROBJ)\dsp\lossless_sse2.obj \
$(DIROBJ)\dsp\lossless_sse41.obj \
$(DIROBJ)\dsp\rescaler.obj \
$(DIROBJ)\dsp\rescaler_mips32.obj \
$(DIROBJ)\dsp\rescaler_mips_dsp_r2.obj \
@ -239,7 +234,6 @@ DSP_ENC_OBJS = \
$(DIROBJ)\dsp\cost.obj \
$(DIROBJ)\dsp\cost_mips32.obj \
$(DIROBJ)\dsp\cost_mips_dsp_r2.obj \
$(DIROBJ)\dsp\cost_neon.obj \
$(DIROBJ)\dsp\cost_sse2.obj \
$(DIROBJ)\dsp\enc.obj \
$(DIROBJ)\dsp\enc_mips32.obj \
@ -392,13 +386,7 @@ $(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\get_disto.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
$(DIRBIN)\webp_quality.exe: $(DIROBJ)\extras\webp_quality.obj
$(DIRBIN)\webp_quality.exe: $(IMAGEIO_UTIL_OBJS)
$(DIRBIN)\webp_quality.exe: $(EXTRAS_OBJS)
# 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)\webp_quality.exe: $(EXTRAS_OBJS) $(LIBWEBP)
$(DIRBIN)\webpinfo.exe: $(DIROBJ)\examples\webpinfo.obj
$(DIRBIN)\webpinfo.exe: $(IMAGEIO_DEC_OBJS)
$(DIRBIN)\webpinfo.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
@ -495,18 +483,15 @@ $(DIROBJ)\examples\gifdec.obj: examples\gifdec.c
{src\utils}.c{$(DIROBJ)\utils}.obj::
$(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:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** \
ole32.lib windowscodecs.lib shlwapi.lib
$(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest
{$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe:
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** \
ole32.lib windowscodecs.lib shlwapi.lib
$(MT) -manifest $@.manifest -outputresource:$@;1
del $@.manifest

55
NEWS
View File

@ -1,58 +1,3 @@
- 7/20/2021: version 1.2.1
This is a binary compatible release.
* minor lossless encoder improvements and x86 color conversion speed up
* add ARM64 simulator support to xcframeworkbuild.sh (#510)
* further security related hardening in libwebp & examples
(issues: #497, #508, #518)
(chromium: #1196480, #1196773, #1196775, #1196777, #1196778, #1196850)
(oss-fuzz: #28658, #28978)
* toolchain updates and bug fixes (#498, #501, #502, #504, #505, #506, #509,
#533)
* use more inclusive language within the source (#507)
- 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

20
README
View File

@ -4,7 +4,7 @@
\__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__
\____/____/\_____/_____/____/v1.2.1
\____/____/\_____/_____/____/v1.0.1
Description:
============
@ -113,7 +113,7 @@ make install
CMake:
------
With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo
With CMake, you can compile libwebp, cwebp, dwebp, gif2web, img2webp, webpinfo
and the JS bindings.
Prerequisites:
@ -136,8 +136,6 @@ cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../
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)
@ -225,7 +223,6 @@ Usage:
If input size (-s) for an image is not specified, it is
assumed to be a PNG, JPEG, TIFF or WebP file.
Note: Animated PNG and WebP files are not supported.
Options:
-h / -help ............. short help
@ -255,8 +252,6 @@ Options:
-partition_limit <int> . limit quality to fit the 512k limit on
the first partition (0=no degradation ... 100=full)
-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
-resize <w> <h> ........ resize picture (after any cropping)
-mt .................... use multi-threading if available
@ -297,7 +292,6 @@ Experimental Options:
-af .................... auto-adjust filter strength
-pre <int> ............. pre-processing filter
The main options you might want to try in order to further tune the
visual quality are:
-preset
@ -345,9 +339,7 @@ The full list of options is available using -h:
> dwebp -h
Usage: dwebp in_file [options] [-o out_file]
Decodes the WebP image file to PNG format [Default].
Note: Animated WebP files are not supported.
Decodes the WebP image file to PNG format [Default]
Use following options to convert into alternate image formats:
-pam ......... save the raw RGBA samples as a color PAM
-ppm ......... save the raw RGB samples as a color PPM
@ -429,7 +421,7 @@ Prerequisites:
1) OpenGL & OpenGL Utility Toolkit (GLUT)
Linux:
$ sudo apt-get install freeglut3-dev mesa-common-dev
Mac + Xcode:
Mac + XCode:
- These libraries should be available in the OpenGL / GLUT frameworks.
Windows:
http://freeglut.sourceforge.net/index.php#download
@ -603,7 +595,7 @@ The encoding flow looks like:
// Setup a config, starting form a preset and tuning some additional
// parameters
WebPConfig config;
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) {
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor))
return 0; // version error
}
// ... additional tuning
@ -619,7 +611,7 @@ The encoding flow looks like:
pic.width = width;
pic.height = height;
// allocated picture of dimension width x height
if (!WebPPictureAlloc(&pic)) {
if (!WebPPictureAllocate(&pic)) {
return 0; // memory error
}
// at this point, 'pic' has been initialized as a container,

View File

@ -1,7 +1,7 @@
 __ __ ____ ____ ____ __ __ _ __ __
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
\ / __/ _ \ __/ / / (_/ /__
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.2.1
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.0.1
Description:
@ -44,7 +44,6 @@ GET_OPTIONS:
SET_OPTIONS:
Set color profile/metadata:
loop LOOP_COUNT set the loop count
icc file.icc set ICC profile
exif file.exif set EXIF metadata
xmp file.xmp set XMP metadata

View File

@ -10,21 +10,26 @@ 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://emscripten.org/docs/getting_started/downloads.html#installation-instructions-using-the-emsdk-recommended
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, $EMSDK should point 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.
- configure the project 'WEBP_JS' with CMake using:
cd webp_js && \
emcmake cmake -DWEBP_BUILD_WEBP_JS=ON \
cmake -DWEBP_BUILD_WEBP_JS=ON \
-DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=1 \
-DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake \
../
- compile webp.js using 'emmake make'.
- compile webp.js using 'make'.
- that's it! Upon completion, you should have the webp.js and
webp.wasm files generated.
webp.js.mem 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
@ -50,9 +55,8 @@ Web-Assembly (WASM) version:
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 2.0.18,
latest-upstream is recommended) and of your WASM-enabled browser to run this
version.
You will need a fairly recent version of Emscripten (at least 1.37.8) and of
your WASM-enabled browser to run this version. Consider it very experimental!
Caveat:
=======
@ -70,6 +74,3 @@ Caveat:
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

@ -141,7 +141,6 @@ model {
include "lossless_msa.c"
include "lossless_neon.$NEON"
include "lossless_sse2.c"
include "lossless_sse41.c"
include "rescaler.c"
include "rescaler_mips32.c"
include "rescaler_mips_dsp_r2.c"
@ -174,7 +173,6 @@ model {
include "cost.c"
include "cost_mips32.c"
include "cost_mips_dsp_r2.c"
include "cost_neon.$NEON"
include "cost_sse2.c"
include "enc.c"
include "enc_mips32.c"
@ -433,3 +431,8 @@ model {
}
}
}
// Task to generate the wrapper.
task wrapper(type: Wrapper) {
gradleVersion = '2.13'
}

View File

@ -5,7 +5,7 @@ set(WEBP_VERSION ${WebP_VERSION})
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
set(WebP_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
set(WebP_INCLUDE_DIRS "webp")
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIRS})
set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@")
set(WEBP_LIBRARIES "${WebP_LIBRARIES}")

View File

@ -93,6 +93,10 @@
/* Define to the version of this package. */
#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. */
#cmakedefine STDC_HEADERS 1

View File

@ -1,11 +1,3 @@
# Copyright (c) 2021 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.
# Check for SIMD extensions.
include(CMakePushCheckState)
@ -39,17 +31,9 @@ endfunction()
set(WEBP_SIMD_FLAGS "SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA")
set(WEBP_SIMD_FILE_EXTENSIONS
"_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
# With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2
# or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4
# 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()
if(MSVC)
# MSVC does not have a SSE4 flag but AVX support implies SSE4 support.
set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;")
set(SIMD_DISABLE_FLAGS)
else()
set(SIMD_ENABLE_FLAGS
@ -73,14 +57,9 @@ endif()
list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH)
math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1")
unset(HIGHEST_SSE_FLAG)
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)
# First try with no extra flag added as the compiler might have default flags
@ -91,15 +70,10 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
if(NOT WEBP_HAVE_${WEBP_SIMD_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})
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
else()
if(MSVC AND SIMD_ENABLE_FLAGS)
# 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.
if(MSVC)
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
else()
set(SIMD_COMPILE_FLAG " ")
@ -110,10 +84,17 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../"
"src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
if(WEBP_HAVE_${WEBP_SIMD_FLAG})
if(${I_SIMD} LESS 2 AND NOT HIGHEST_SSE_FLAG)
set(HIGHEST_SSE_FLAG ${SIMD_COMPILE_FLAG})
endif()
# Memorize the file and flags.
foreach(FILE ${SIMD_FILES})
list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE})
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG})
if(${I_SIMD} LESS 2)
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${HIGHEST_SSE_FLAG})
else()
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG})
endif()
endforeach()
else()
# Remove the file from the list.
@ -125,12 +106,6 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
include(CheckCCompilerFlag)
if(SIMD_COMPILE_FLAG)
# Between 3.17.0 and 3.18.2 check_cxx_compiler_flag() sets a normal
# variable at parent scope while check_cxx_source_compiles() continues
# to set an internal cache variable, so we unset both to avoid the
# failure / success state persisting between checks. See
# https://gitlab.kitware.com/cmake/cmake/-/issues/21207.
unset(HAS_COMPILE_FLAG)
unset(HAS_COMPILE_FLAG CACHE)
check_c_compiler_flag(${SIMD_COMPILE_FLAG} HAS_COMPILE_FLAG)
if(HAS_COMPILE_FLAG)
@ -148,7 +123,6 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
"warning: argument unused during compilation:"
${COMMON_PATTERNS})
if(NOT FLAG_${SIMD_COMPILE_FLAG})
unset(HAS_COMPILE_FLAG)
unset(HAS_COMPILE_FLAG CACHE)
endif()
endif()

View File

@ -1,11 +1,3 @@
# Copyright (c) 2021 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.
# Generate the config.h to compile with specific intrinsics / libs.
# Check for compiler options.
@ -30,25 +22,23 @@ check_c_source_compiles("
" HAVE_BUILTIN_BSWAP64)
# Check for libraries.
if(WEBP_USE_THREAD)
find_package(Threads)
if(Threads_FOUND)
# work around cmake bug on QNX (https://cmake.org/Bug/view.php?id=11333)
if(CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
endif()
find_package(Threads)
if(Threads_FOUND)
if(CMAKE_USE_PTHREADS_INIT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
endif()
foreach(PTHREAD_TEST HAVE_PTHREAD_PRIO_INHERIT PTHREAD_CREATE_UNDETACHED)
check_c_source_compiles("
#include <pthread.h>
int main (void) {
int attr = PTHREAD_PRIO_INHERIT;
int attr = ${PTHREAD_TEST};
return attr;
}
" FLAG_HAVE_PTHREAD_PRIO_INHERIT)
set(HAVE_PTHREAD_PRIO_INHERIT ${FLAG_HAVE_PTHREAD_PRIO_INHERIT})
list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif()
set(WEBP_USE_THREAD ${Threads_FOUND})
" ${PTHREAD_TEST})
endforeach()
list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif()
set(WEBP_USE_THREAD ${Threads_FOUND})
# TODO: this seems unused, check with autotools.
set(LT_OBJDIR ".libs/")

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.1],
AC_INIT([libwebp], [1.0.1],
[https://bugs.chromium.org/p/webp],,
[http://developers.google.com/speed/webp])
AC_CANONICAL_HOST
@ -32,40 +32,6 @@ AC_ARG_ENABLE([everything],
SET_IF_UNSET([enable_libwebpextras], [$enableval])
SET_IF_UNSET([enable_libwebpmux], [$enableval])])
dnl === Check whether libwebpmux should be built
AC_MSG_CHECKING(whether libwebpmux is to be built)
AC_ARG_ENABLE([libwebpmux],
AS_HELP_STRING([--disable-libwebpmux],
[Disable libwebpmux @<:@default=no@:>@]),
[], [enable_libwebpmux=yes])
AC_MSG_RESULT(${enable_libwebpmux-no})
AM_CONDITIONAL([BUILD_MUX], [test "$enable_libwebpmux" = "yes"])
dnl === Check whether libwebpdemux should be built
AC_MSG_CHECKING(whether libwebpdemux is to be built)
AC_ARG_ENABLE([libwebpdemux],
AS_HELP_STRING([--disable-libwebpdemux],
[Disable libwebpdemux @<:@default=no@:>@]),
[], [enable_libwebpdemux=yes])
AC_MSG_RESULT(${enable_libwebpdemux-no})
AM_CONDITIONAL([BUILD_DEMUX], [test "$enable_libwebpdemux" = "yes"])
dnl === Check whether decoder library should be built.
AC_MSG_CHECKING(whether decoder library is to be built)
AC_ARG_ENABLE([libwebpdecoder],
AS_HELP_STRING([--enable-libwebpdecoder],
[Build libwebpdecoder @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpdecoder-no})
AM_CONDITIONAL([BUILD_LIBWEBPDECODER], [test "$enable_libwebpdecoder" = "yes"])
dnl === Check whether libwebpextras should be built
AC_MSG_CHECKING(whether libwebpextras is to be built)
AC_ARG_ENABLE([libwebpextras],
AS_HELP_STRING([--enable-libwebpextras],
[Build libwebpextras @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpextras-no})
AM_CONDITIONAL([BUILD_EXTRAS], [test "$enable_libwebpextras" = "yes"])
dnl === If --enable-asserts is not defined, define NDEBUG
AC_MSG_CHECKING(whether asserts are enabled)
@ -114,7 +80,6 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow])
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], [-Wunused-but-set-variable])
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused])
@ -259,9 +224,6 @@ AS_IF([test "x$enable_neon" != "xno"], [
*android*) AC_CHECK_HEADERS([cpu-features.h]) ;;
esac
;;
aarch64*|arm64*)
AC_DEFINE(WEBP_HAVE_NEON, [1], [Set to 1 if NEON is supported])
;;
esac
AC_SUBST([NEON_FLAGS])])
@ -446,10 +408,6 @@ AS_IF([test "x$enable_gl" != "xno"], [
if test "$glut_support" = "yes" -a "$enable_libwebpdemux" = "yes"; then
build_vwebp=yes
else
AC_MSG_NOTICE(
m4_normalize([Not building vwebp.
OpenGL libraries and --enable-libwebpdemux are required.]))
fi
])
AM_CONDITIONAL([BUILD_VWEBP], [test "$build_vwebp" = "yes"])
@ -509,7 +467,7 @@ AS_IF([test "x$enable_sdl" != "xno"], [
if test x"$sdl_support" = "xyes"; then
build_vwebp_sdl=yes
else
AC_MSG_NOTICE([Not building vwebp-sdl. SDL library is required.])
AC_MSG_WARN(Optional SDL library not found)
fi
])
@ -633,17 +591,11 @@ AS_IF([test "x$enable_gif" != "xno"], [
if test "$gif_support" = "yes" -a \
"$enable_libwebpdemux" = "yes"; then
build_anim_diff=yes
else
AC_MSG_NOTICE(
[Not building anim_diff. libgif and --enable-libwebpdemux are required.])
fi
if test "$gif_support" = "yes" -a \
"$enable_libwebpmux" = "yes"; then
build_gif2webp=yes
else
AC_MSG_NOTICE(
[Not building gif2webp. libgif and --enable-libwebpmux are required.])
fi
])
AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_anim_diff}" = "yes"])
@ -651,17 +603,11 @@ AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"])
if test "$enable_libwebpdemux" = "yes" -a "$enable_libwebpmux" = "yes"; then
build_img2webp=yes
else
AC_MSG_NOTICE(
m4_normalize([Not building img2webp.
--enable-libwebpdemux & --enable-libwebpmux are required.]))
fi
AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"])
if test "$enable_libwebpmux" = "yes"; then
build_webpinfo=yes
else
AC_MSG_NOTICE([Not building webpinfo. --enable-libwebpdemux is required.])
fi
AM_CONDITIONAL([BUILD_WEBPINFO], [test "${build_webpinfo}" = "yes"])
@ -745,6 +691,39 @@ else
AC_MSG_RESULT([no])
fi
dnl === Check whether libwebpmux should be built
AC_MSG_CHECKING(whether libwebpmux is to be built)
AC_ARG_ENABLE([libwebpmux],
AS_HELP_STRING([--enable-libwebpmux],
[Build libwebpmux @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpmux-no})
AM_CONDITIONAL([BUILD_MUX], [test "$enable_libwebpmux" = "yes"])
dnl === Check whether libwebpdemux should be built
AC_MSG_CHECKING(whether libwebpdemux is to be built)
AC_ARG_ENABLE([libwebpdemux],
AS_HELP_STRING([--disable-libwebpdemux],
[Disable libwebpdemux @<:@default=no@:>@]),
[], [enable_libwebpdemux=yes])
AC_MSG_RESULT(${enable_libwebpdemux-no})
AM_CONDITIONAL([BUILD_DEMUX], [test "$enable_libwebpdemux" = "yes"])
dnl === Check whether decoder library should be built.
AC_MSG_CHECKING(whether decoder library is to be built)
AC_ARG_ENABLE([libwebpdecoder],
AS_HELP_STRING([--enable-libwebpdecoder],
[Build libwebpdecoder @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpdecoder-no})
AM_CONDITIONAL([BUILD_LIBWEBPDECODER], [test "$enable_libwebpdecoder" = "yes"])
dnl === Check whether libwebpextras should be built
AC_MSG_CHECKING(whether libwebpextras is to be built)
AC_ARG_ENABLE([libwebpextras],
AS_HELP_STRING([--enable-libwebpextras],
[Build libwebpextras @<:@default=no@:>@]))
AC_MSG_RESULT(${enable_libwebpextras-no})
AM_CONDITIONAL([BUILD_EXTRAS], [test "$enable_libwebpextras" = "yes"])
dnl =========================
AC_CONFIG_MACRO_DIR([m4])

View File

@ -816,7 +816,7 @@ RIFF/WEBP
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[vp8spec]: http://tools.ietf.org/html/rfc6386
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
[iccspec]: http://www.color.org/icc_specs2.xalter
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
[rfc 1166]: http://tools.ietf.org/html/rfc1166

View File

@ -21,7 +21,6 @@
#include "./anim_util.h"
#include "./example_util.h"
#include "./unicode.h"
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
@ -219,14 +218,12 @@ int main(int argc, const char* argv[]) {
const char* files[2] = { NULL, NULL };
AnimatedImage images[2];
INIT_WARGV(argc, argv);
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-dump_frames")) {
if (c < argc - 1) {
dump_frames = 1;
dump_folder = (const char*)GET_WARGV(argv, ++c);
dump_folder = argv[++c];
} else {
parse_error = 1;
}
@ -246,7 +243,7 @@ int main(int argc, const char* argv[]) {
}
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
return 0;
} else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version);
@ -255,13 +252,13 @@ int main(int argc, const char* argv[]) {
(dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff);
FREE_WARGV_AND_RETURN(0);
return 0;
} else {
if (!got_input1) {
files[0] = (const char*)GET_WARGV(argv, c);
files[0] = argv[c];
got_input1 = 1;
} else if (!got_input2) {
files[1] = (const char*)GET_WARGV(argv, c);
files[1] = argv[c];
got_input2 = 1;
} else {
parse_error = 1;
@ -269,30 +266,29 @@ int main(int argc, const char* argv[]) {
}
if (parse_error) {
Help();
FREE_WARGV_AND_RETURN(-1);
return -1;
}
}
if (argc < 3) {
Help();
FREE_WARGV_AND_RETURN(-1);
return -1;
}
if (!got_input2) {
Help();
FREE_WARGV_AND_RETURN(-1);
return -1;
}
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));
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)) {
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n",
(const W_CHAR*)files[i]);
fprintf(stderr, "Error decoding file: %s\n Aborting.\n", files[i]);
return_code = -2;
goto End;
} else {
@ -302,16 +298,14 @@ int main(int argc, const char* argv[]) {
if (!CompareAnimatedImagePair(&images[0], &images[1],
premultiply, min_psnr)) {
WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0],
(const W_CHAR*)files[1]);
fprintf(stderr, "\nFiles %s and %s differ.\n", files[0], files[1]);
return_code = -3;
} else {
WPRINTF("\nFiles %s and %s are identical.\n", (const W_CHAR*)files[0],
(const W_CHAR*)files[1]);
printf("\nFiles %s and %s are identical.\n", files[0], files[1]);
return_code = 0;
}
End:
ClearAnimatedImage(&images[0]);
ClearAnimatedImage(&images[1]);
FREE_WARGV_AND_RETURN(return_code);
return return_code;
}

View File

@ -17,7 +17,6 @@
#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
@ -37,17 +36,15 @@ static void Help(void) {
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");
const char* dump_folder = ".";
const char* prefix = "dump_";
const char* suffix = "png";
WebPOutputFileFormat format = PNG;
int c;
INIT_WARGV(argc, argv);
if (argc < 2) {
Help();
FREE_WARGV_AND_RETURN(-1);
return -1;
}
for (c = 1; !error && c < argc; ++c) {
@ -57,23 +54,23 @@ int main(int argc, const char* argv[]) {
error = 1;
break;
}
dump_folder = GET_WARGV(argv, ++c);
dump_folder = 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);
prefix = argv[++c];
} else if (!strcmp(argv[c], "-tiff")) {
format = TIFF;
suffix = TO_W_CHAR("tiff");
suffix = "tiff";
} else if (!strcmp(argv[c], "-pam")) {
format = PAM;
suffix = TO_W_CHAR("pam");
suffix = "pam";
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
return 0;
} else if (!strcmp(argv[c], "-version")) {
int dec_version, demux_version;
GetAnimatedImageVersions(&dec_version, &demux_version);
@ -82,21 +79,21 @@ int main(int argc, const char* argv[]) {
(dec_version >> 0) & 0xff,
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
(demux_version >> 0) & 0xff);
FREE_WARGV_AND_RETURN(0);
return 0;
} else {
uint32_t i;
AnimatedImage image;
const W_CHAR* const file = GET_WARGV(argv, c);
const char* const file = 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);
printf("Decoding file: %s as %s/%sxxxx.%s\n",
file, dump_folder, prefix, suffix);
if (!ReadAnimatedImage(file, &image, 0, NULL)) {
fprintf(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];
char out_file[1024];
WebPDecBuffer buffer;
WebPInitDecBuffer(&buffer);
buffer.colorspace = MODE_RGBA;
@ -106,10 +103,10 @@ int main(int argc, const char* argv[]) {
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);
snprintf(out_file, sizeof(out_file), "%s/%s%.4d.%s",
dump_folder, prefix, i, suffix);
if (!WebPSaveImage(&buffer, format, out_file)) {
fprintf(stderr, "Error while saving image '%s'\n", out_file);
error = 1;
}
WebPFreeDecBuffer(&buffer);
@ -117,5 +114,5 @@ int main(int argc, const char* argv[]) {
ClearAnimatedImage(&image);
}
}
FREE_WARGV_AND_RETURN(error ? 1 : 0);
return error ? 1 : 0;
}

View File

@ -24,8 +24,6 @@
#include "webp/demux.h"
#include "../imageio/imageio_util.h"
#include "./gifdec.h"
#include "./unicode.h"
#include "./unicode_gif.h"
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
@ -60,15 +58,15 @@ static int AllocateFrames(AnimatedImage* const image, uint32_t num_frames) {
!CheckSizeForOverflow(total_frame_size)) {
return 0;
}
mem = (uint8_t*)WebPMalloc((size_t)total_size);
frames = (DecodedFrame*)WebPMalloc((size_t)total_frame_size);
mem = (uint8_t*)malloc((size_t)total_size);
frames = (DecodedFrame*)malloc((size_t)total_frame_size);
if (mem == NULL || frames == NULL) {
WebPFree(mem);
WebPFree(frames);
free(mem);
free(frames);
return 0;
}
WebPFree(image->raw_mem);
free(image->raw_mem);
image->num_frames = num_frames;
image->frames = frames;
for (i = 0; i < num_frames; ++i) {
@ -82,8 +80,8 @@ static int AllocateFrames(AnimatedImage* const image, uint32_t num_frames) {
void ClearAnimatedImage(AnimatedImage* const image) {
if (image != NULL) {
WebPFree(image->raw_mem);
WebPFree(image->frames);
free(image->raw_mem);
free(image->frames);
image->num_frames = 0;
image->frames = NULL;
image->raw_mem = NULL;
@ -154,42 +152,42 @@ static int DumpFrame(const char filename[], const char dump_folder[],
int ok = 0;
size_t max_len;
int y;
const W_CHAR* base_name = NULL;
W_CHAR* file_name = NULL;
const char* base_name = NULL;
char* file_name = NULL;
FILE* f = NULL;
const char* row;
if (dump_folder == NULL) dump_folder = (const char*)TO_W_CHAR(".");
if (dump_folder == NULL) dump_folder = ".";
base_name = WSTRRCHR(filename, '/');
base_name = (base_name == NULL) ? (const W_CHAR*)filename : base_name + 1;
max_len = WSTRLEN(dump_folder) + 1 + WSTRLEN(base_name)
base_name = strrchr(filename, '/');
base_name = (base_name == NULL) ? filename : base_name + 1;
max_len = strlen(dump_folder) + 1 + strlen(base_name)
+ 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 (WSNPRINTF(file_name, max_len, "%s/%s_frame_%d.pam",
(const W_CHAR*)dump_folder, base_name, frame_num) < 0) {
if (snprintf(file_name, max_len, "%s/%s_frame_%d.pam",
dump_folder, base_name, frame_num) < 0) {
fprintf(stderr, "Error while generating file name\n");
goto End;
}
f = WFOPEN(file_name, "wb");
f = fopen(file_name, "wb");
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;
goto End;
}
if (fprintf(f, "P7\nWIDTH %d\nHEIGHT %d\n"
"DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
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;
}
row = (const char*)rgba;
for (y = 0; y < canvas_height; ++y) {
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;
}
row += canvas_width * kNumChannels;
@ -197,7 +195,7 @@ static int DumpFrame(const char filename[], const char dump_folder[],
ok = 1;
End:
if (f != NULL) fclose(f);
WebPFree(file_name);
free(file_name);
return ok;
}
@ -225,7 +223,7 @@ static int ReadAnimatedWebP(const char filename[],
dec = WebPAnimDecoderNew(webp_data, 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;
}
@ -405,7 +403,7 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) {
return 0xffffffff; // Invalid: assume white.
} else {
const GifColorType color = color_map->Colors[gif->SBackGroundColor];
return (0xffu << 24) |
return (0xff << 24) |
(color.Red << 16) |
(color.Green << 8) |
(color.Blue << 0);
@ -513,15 +511,15 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
int gif_error;
GifFileType* gif;
gif = DGifOpenFileUnicode((const W_CHAR*)filename, NULL);
gif = DGifOpenFileName(filename, 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;
}
gif_error = DGifSlurp(gif);
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);
DGifCloseFile(gif, NULL);
return 0;
@ -707,7 +705,7 @@ int ReadAnimatedImage(const char filename[], AnimatedImage* const image,
memset(image, 0, sizeof(*image));
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;
}
@ -717,9 +715,9 @@ int ReadAnimatedImage(const char filename[], AnimatedImage* const image,
} else if (IsGIF(&webp_data)) {
ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder);
} else {
WFPRINTF(stderr,
"Unknown file type: %s. Supported file types are WebP and GIF\n",
(const W_CHAR*)filename);
fprintf(stderr,
"Unknown file type: %s. Supported file types are WebP and GIF\n",
filename);
ok = 0;
}
if (!ok) ClearAnimatedImage(image);

View File

@ -12,7 +12,6 @@
//
// Author: Skal (pascal.massimino@gmail.com)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -24,9 +23,7 @@
#include "../examples/example_util.h"
#include "../imageio/image_dec.h"
#include "../imageio/imageio_util.h"
#include "../imageio/webpdec.h"
#include "./stopwatch.h"
#include "./unicode.h"
#include "webp/encode.h"
#ifndef WEBP_DLL
@ -91,10 +88,9 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
}
}
if (!ok) {
WFPRINTF(stderr, "Error! Could not process file %s\n",
(const W_CHAR*)filename);
fprintf(stderr, "Error! Could not process file %s\n", filename);
}
WebPFree((void*)data);
free((void*)data);
return ok;
}
@ -118,10 +114,9 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
}
End:
if (!ok) {
WFPRINTF(stderr, "Error! Could not process file %s\n",
(const W_CHAR*)filename);
fprintf(stderr, "Error! Could not process file %s\n", filename);
}
WebPFree((void*)data);
free((void*)data);
return ok;
}
@ -130,8 +125,7 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
static void AllocExtraInfo(WebPPicture* const pic) {
const int mb_w = (pic->width + 15) / 16;
const int mb_h = (pic->height + 15) / 16;
pic->extra_info =
(uint8_t*)WebPMalloc(mb_w * mb_h * sizeof(*pic->extra_info));
pic->extra_info = (uint8_t*)malloc(mb_w * mb_h * sizeof(*pic->extra_info));
}
static void PrintByteCount(const int bytes[4], int total_size,
@ -150,7 +144,7 @@ static void PrintPercents(const int counts[4]) {
int s;
const int total = counts[0] + counts[1] + counts[2] + counts[3];
for (s = 0; s < 4; ++s) {
fprintf(stderr, "| %3d%%", (int)(100. * counts[s] / total + .5));
fprintf(stderr, "| %2d%%", (int)(100. * counts[s] / total + .5));
}
fprintf(stderr, "| %7d\n", total);
}
@ -191,7 +185,7 @@ static void PrintExtraInfoLossless(const WebPPicture* const pic,
if (short_output) {
fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]);
} 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, "Output: %d bytes (%.2f bpp)\n", stats->coded_size,
8.f * stats->coded_size / pic->width / pic->height);
@ -210,7 +204,7 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
const int num_i16 = stats->block_count[1];
const int num_skip = stats->block_count[2];
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",
pic->width, pic->height,
stats->alpha_data_size ? " (with alpha)" : "");
@ -315,7 +309,7 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
const int alpha_height =
WebPPictureHasTransparency(picture) ? picture->height : 0;
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;
fprintf(f, "P5\n%d %d\n255\n", stride, height);
for (y = 0; y < picture->height; ++y) {
@ -527,7 +521,6 @@ static void HelpLong(void) {
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"
"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
printf("Windows builds can take as input any of the files handled by WIC.\n");
#endif
@ -568,8 +561,6 @@ static void HelpLong(void) {
printf(" "
"the first partition (0=no degradation ... 100=full)\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(" -resize <w> <h> ........ resize picture (after any cropping)\n");
printf(" -mt .................... use multi-threading if available\n");
@ -646,10 +637,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;
const char* in_file = NULL, *out_file = NULL, *dump_file = NULL;
FILE* out = NULL;
const char *in_file = NULL, *out_file = NULL, *dump_file = NULL;
FILE *out = NULL;
int c;
int short_output = 0;
int quiet = 0;
@ -669,38 +660,35 @@ int main(int argc, const char* argv[]) {
WebPConfig config;
WebPAuxStats stats;
WebPMemoryWriter memory_writer;
int use_memory_writer;
Metadata metadata;
Stopwatch stop_watch;
INIT_WARGV(argc, argv);
MetadataInit(&metadata);
WebPMemoryWriterInit(&memory_writer);
if (!WebPPictureInit(&picture) ||
!WebPPictureInit(&original_picture) ||
!WebPConfigInit(&config)) {
fprintf(stderr, "Error! Version mismatch!\n");
FREE_WARGV_AND_RETURN(-1);
return -1;
}
if (argc == 1) {
HelpShort();
FREE_WARGV_AND_RETURN(0);
return 0;
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
HelpShort();
FREE_WARGV_AND_RETURN(0);
return 0;
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
HelpLong();
FREE_WARGV_AND_RETURN(0);
} else if (!strcmp(argv[c], "-o") && c + 1 < argc) {
out_file = (const char*)GET_WARGV(argv, ++c);
} else if (!strcmp(argv[c], "-d") && c + 1 < argc) {
dump_file = (const char*)GET_WARGV(argv, ++c);
return 0;
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
out_file = argv[++c];
} else if (!strcmp(argv[c], "-d") && c < argc - 1) {
dump_file = argv[++c];
config.show_compressed = 1;
} else if (!strcmp(argv[c], "-print_psnr")) {
config.show_compressed = 1;
@ -713,7 +701,7 @@ int main(int argc, const char* argv[]) {
print_distortion = 2;
} else if (!strcmp(argv[c], "-short")) {
++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.height = ExUtilGetInt(argv[++c], 0, &parse_error);
if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 ||
@ -723,30 +711,30 @@ int main(int argc, const char* argv[]) {
picture.width, picture.height);
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);
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);
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);
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);
} 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);
} else if (!strcmp(argv[c], "-alpha_cleanup")) {
// This flag is obsolete, does opposite of -exact.
config.exact = 0;
} else if (!strcmp(argv[c], "-exact")) {
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;
// background color is given in hex with an optional '0x' prefix
background_color = ExUtilGetInt(argv[++c], 16, &parse_error);
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;
if (!strcmp(argv[c], "none")) {
config.alpha_filtering = 0;
@ -762,10 +750,10 @@ int main(int argc, const char* argv[]) {
keep_alpha = 0;
} else if (!strcmp(argv[c], "-lossless")) {
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.lossless = 1; // use near-lossless only with lossless
} else if (!strcmp(argv[c], "-hint") && c + 1 < argc) {
} else if (!strcmp(argv[c], "-hint") && c < argc - 1) {
++c;
if (!strcmp(argv[c], "photo")) {
config.image_hint = WEBP_HINT_PHOTO;
@ -777,13 +765,13 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]);
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);
} 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);
} 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);
} 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);
} else if (!strcmp(argv[c], "-af")) {
config.autofilter = 1;
@ -797,32 +785,27 @@ int main(int argc, const char* argv[]) {
config.filter_type = 1;
} else if (!strcmp(argv[c], "-nostrong")) {
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);
} else if (!strcmp(argv[c], "-sharp_yuv")) {
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);
} else if (!strcmp(argv[c], "-qrange") && c + 2 < argc) {
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) {
} else if (!strcmp(argv[c], "-pre") && c < argc - 1) {
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);
} 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);
} 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);
} else if (!strcmp(argv[c], "-crop") && c + 4 < argc) {
} else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
crop = 1;
crop_x = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_y = ExUtilGetInt(argv[++c], 0, &parse_error);
crop_w = 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_h = ExUtilGetInt(argv[++c], 0, &parse_error);
#ifndef WEBP_DLL
@ -833,12 +816,12 @@ int main(int argc, const char* argv[]) {
const int version = WebPGetEncoderVersion();
printf("%d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
FREE_WARGV_AND_RETURN(0);
return 0;
} else if (!strcmp(argv[c], "-progress")) {
show_progress = 1;
} else if (!strcmp(argv[c], "-quiet")) {
quiet = 1;
} else if (!strcmp(argv[c], "-preset") && c + 1 < argc) {
} else if (!strcmp(argv[c], "-preset") && c < argc - 1) {
WebPPreset preset;
++c;
if (!strcmp(argv[c], "default")) {
@ -861,7 +844,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Could initialize configuration with preset.\n");
goto Error;
}
} else if (!strcmp(argv[c], "-metadata") && c + 1 < argc) {
} else if (!strcmp(argv[c], "-metadata") && c < argc - 1) {
static const struct {
const char* option;
int flag;
@ -895,7 +878,8 @@ int main(int argc, const char* argv[]) {
if (i == kNumTokens) {
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
(int)(token - start), start);
FREE_WARGV_AND_RETURN(-1);
HelpLong();
return -1;
}
start = token + 1;
}
@ -909,19 +893,19 @@ int main(int argc, const char* argv[]) {
} else if (!strcmp(argv[c], "-v")) {
verbose = 1;
} 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;
} else if (argv[c][0] == '-') {
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
HelpLong();
FREE_WARGV_AND_RETURN(-1);
return -1;
} else {
in_file = (const char*)GET_WARGV(argv, c);
in_file = argv[c];
}
if (parse_error) {
HelpLong();
FREE_WARGV_AND_RETURN(-1);
return -1;
}
}
if (in_file == NULL) {
@ -971,8 +955,7 @@ int main(int argc, const char* argv[]) {
}
if (!ReadPicture(in_file, &picture, keep_alpha,
(keep_metadata == 0) ? NULL : &metadata)) {
WFPRINTF(stderr, "Error! Cannot read input picture file '%s'\n",
(const W_CHAR*)in_file);
fprintf(stderr, "Error! Cannot read input picture file '%s'\n", in_file);
goto Error;
}
picture.progress_hook = (show_progress && !quiet) ? ProgressReport : NULL;
@ -985,41 +968,28 @@ int main(int argc, const char* argv[]) {
const double read_time = StopwatchReadAndReset(&stop_watch);
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
if (out_file != NULL) {
const int use_stdout = !WSTRCMP(out_file, "-");
out = use_stdout ? ImgIoUtilSetBinaryMode(stdout) : WFOPEN(out_file, "wb");
const int use_stdout = !strcmp(out_file, "-");
out = use_stdout ? ImgIoUtilSetBinaryMode(stdout) : fopen(out_file, "wb");
if (out == NULL) {
WFPRINTF(stderr, "Error! Cannot open output file '%s'\n",
(const W_CHAR*)out_file);
fprintf(stderr, "Error! Cannot open output file '%s'\n", out_file);
goto Error;
} else {
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) {
picture.writer = WebPMemoryWrite;
picture.custom_ptr = (void*)&memory_writer;
} else {
if (keep_metadata == 0) {
picture.writer = MyWriter;
picture.custom_ptr = (void*)out;
} else {
picture.writer = WebPMemoryWrite;
picture.custom_ptr = (void*)&memory_writer;
}
} else {
out = NULL;
if (use_memory_writer) {
picture.writer = WebPMemoryWrite;
picture.custom_ptr = (void*)&memory_writer;
}
if (!quiet && !short_output) {
fprintf(stderr, "No output file specified (no -o flag). Encoding will\n");
fprintf(stderr, "be performed, but its results discarded.\n\n");
@ -1098,12 +1068,8 @@ int main(int argc, const char* argv[]) {
if (picture.extra_info_type > 0) {
AllocExtraInfo(&picture);
}
// Save original picture for later comparison. Only for lossy as lossless does
// not modify 'picture' (even near-lossless).
if (print_distortion >= 0 && !config.lossless &&
!WebPPictureCopy(&picture, &original_picture)) {
fprintf(stderr, "Error! Cannot copy temporary picture\n");
goto Error;
if (print_distortion >= 0) { // Save original picture for later comparison
WebPPictureCopy(&picture, &original_picture);
}
// Compress.
@ -1121,71 +1087,41 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Time to encode picture: %.3fs\n", encode_time);
}
// Get the decompressed image for the lossless pipeline.
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.
// Write info
if (dump_file) {
if (picture.use_argb) {
fprintf(stderr, "Warning: can't dump file (-d option) "
"in lossless mode.\n");
} else if (!DumpPicture(&picture, dump_file)) {
WFPRINTF(stderr, "Warning, couldn't dump picture %s\n",
(const W_CHAR*)dump_file);
fprintf(stderr, "Warning, couldn't dump picture %s\n", dump_file);
}
}
if (use_memory_writer && out != NULL &&
!WriteWebPWithMetadata(out, &picture, &memory_writer, &metadata,
keep_metadata, &metadata_written)) {
fprintf(stderr, "Error writing WebP file!\n");
goto Error;
}
if (keep_metadata != 0) {
if (out != NULL) {
if (!WriteWebPWithMetadata(out, &picture, &memory_writer,
&metadata, keep_metadata, &metadata_written)) {
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) {
// 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;
for (iter = info; iter->payload != NULL; ++iter) {
if (UpdateFlagsAndSize(iter->payload, !!(keep_metadata & iter->flag),
/*flag=*/0, &unused1, &unused2)) {
metadata_written |= iter->flag;
for (iter = info; iter->payload != NULL; ++iter) {
if (UpdateFlagsAndSize(iter->payload, !!(keep_metadata & iter->flag),
0, &unused1, &unused2)) {
metadata_written |= iter->flag;
}
}
}
}
@ -1225,7 +1161,7 @@ int main(int argc, const char* argv[]) {
Error:
WebPMemoryWriterClear(&memory_writer);
WebPFree(picture.extra_info);
free(picture.extra_info);
MetadataFree(&metadata);
WebPPictureFree(&picture);
WebPPictureFree(&original_picture);
@ -1233,7 +1169,7 @@ int main(int argc, const char* argv[]) {
fclose(out);
}
FREE_WARGV_AND_RETURN(return_value);
return return_value;
}
//------------------------------------------------------------------------------

View File

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

View File

@ -75,7 +75,7 @@ static void ResetCommandLineArguments(int argc, const char* argv[],
void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args) {
if (args != NULL) {
if (args->own_argv_) {
WebPFree((void*)args->argv_);
free((void*)args->argv_);
WebPDataClear(&args->argv_data_);
}
ResetCommandLineArguments(0, NULL, args);
@ -90,19 +90,11 @@ int ExUtilInitCommandLineArguments(int argc, const char* argv[],
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_));
args->argv_ = (const char**)malloc(MAX_ARGC * sizeof(*args->argv_));
if (args->argv_ == NULL) return 0;
argc = 0;

View File

@ -33,8 +33,6 @@
#include "../examples/example_util.h"
#include "../imageio/imageio_util.h"
#include "./gifdec.h"
#include "./unicode.h"
#include "./unicode_gif.h"
#if !defined(STDIN_FILENO)
#define STDIN_FILENO 0
@ -96,12 +94,12 @@ static void Help(void) {
//------------------------------------------------------------------------------
int main(int argc, const char* argv[]) {
int main(int argc, const char *argv[]) {
int verbose = 0;
int gif_error = GIF_ERROR;
WebPMuxError err = WEBP_MUX_OK;
int ok = 0;
const W_CHAR* in_file = NULL, *out_file = NULL;
const char *in_file = NULL, *out_file = NULL;
GifFileType* gif = NULL;
int frame_duration = 0;
int frame_timestamp = 0;
@ -134,13 +132,11 @@ int main(int argc, const char* argv[]) {
int default_kmin = 1; // Whether to use default kmin value.
int default_kmax = 1;
INIT_WARGV(argc, argv);
if (!WebPConfigInit(&config) || !WebPAnimEncoderOptionsInit(&enc_options) ||
!WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) ||
!WebPPictureInit(&prev_canvas)) {
fprintf(stderr, "Error! Version mismatch!\n");
FREE_WARGV_AND_RETURN(-1);
return -1;
}
config.lossless = 1; // Use lossless compression by default.
@ -150,16 +146,16 @@ int main(int argc, const char* argv[]) {
if (argc == 1) {
Help();
FREE_WARGV_AND_RETURN(0);
return 0;
}
for (c = 1; c < argc; ++c) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
return 0;
} 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")) {
config.lossless = 0;
} else if (!strcmp(argv[c], "-mixed")) {
@ -216,7 +212,7 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
(int)(token - start), start);
Help();
FREE_WARGV_AND_RETURN(-1);
return -1;
}
start = token + 1;
}
@ -229,7 +225,7 @@ int main(int argc, const char* argv[]) {
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
enc_version & 0xff, (mux_version >> 16) & 0xff,
(mux_version >> 8) & 0xff, mux_version & 0xff);
FREE_WARGV_AND_RETURN(0);
return 0;
} else if (!strcmp(argv[c], "-quiet")) {
quiet = 1;
enc_options.verbose = 0;
@ -237,19 +233,19 @@ int main(int argc, const char* argv[]) {
verbose = 1;
enc_options.verbose = 1;
} else if (!strcmp(argv[c], "--")) {
if (c < argc - 1) in_file = GET_WARGV(argv, ++c);
if (c < argc - 1) in_file = argv[++c];
break;
} else if (argv[c][0] == '-') {
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
Help();
FREE_WARGV_AND_RETURN(-1);
return -1;
} else {
in_file = GET_WARGV(argv, c);
in_file = argv[c];
}
if (parse_error) {
Help();
FREE_WARGV_AND_RETURN(-1);
return -1;
}
}
@ -273,7 +269,13 @@ int main(int argc, const char* argv[]) {
}
// Start the decoder object
gif = DGifOpenFileUnicode(in_file, &gif_error);
#if LOCAL_GIF_PREREQ(5,0)
gif = !strcmp(in_file, "-") ? DGifOpenFileHandle(STDIN_FILENO, &gif_error)
: DGifOpenFileName(in_file, &gif_error);
#else
gif = !strcmp(in_file, "-") ? DGifOpenFileHandle(STDIN_FILENO)
: DGifOpenFileName(in_file);
#endif
if (gif == NULL) goto End;
// Loop over GIF images
@ -379,7 +381,7 @@ int main(int argc, const char* argv[]) {
}
case EXTENSION_RECORD_TYPE: {
int extension;
GifByteType* data = NULL;
GifByteType *data = NULL;
if (DGifGetExtension(gif, &extension, &data) == GIF_ERROR) {
goto End;
}
@ -465,10 +467,8 @@ int main(int argc, const char* argv[]) {
fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc));
goto End;
}
// If there's only one frame, we don't need to handle loop count.
if (frame_number == 1) {
loop_count = 0;
} else if (!loop_compatibility) {
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
@ -544,18 +544,17 @@ int main(int argc, const char* argv[]) {
}
if (out_file != NULL) {
if (!ImgIoUtilWriteFile((const char*)out_file, webp_data.bytes,
webp_data.size)) {
WFPRINTF(stderr, "Error writing output file: %s\n", out_file);
if (!ImgIoUtilWriteFile(out_file, webp_data.bytes, webp_data.size)) {
fprintf(stderr, "Error writing output file: %s\n", out_file);
goto End;
}
if (!quiet) {
if (!WSTRCMP(out_file, "-")) {
if (!strcmp(out_file, "-")) {
fprintf(stderr, "Saved %d bytes to STDIO\n",
(int)webp_data.size);
} else {
WFPRINTF(stderr, "Saved output file (%d bytes): %s\n",
(int)webp_data.size, out_file);
fprintf(stderr, "Saved output file (%d bytes): %s\n",
(int)webp_data.size, out_file);
}
}
} else {
@ -590,12 +589,12 @@ int main(int argc, const char* argv[]) {
#endif
}
FREE_WARGV_AND_RETURN(!ok);
return !ok;
}
#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]);
(void)argc;
return 0;

View File

@ -137,7 +137,7 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
}
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 (image_desc->Interlace) { // Interlaced image.
@ -168,7 +168,7 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
End:
if (!ok) picture->error_code = sub_image.error_code;
WebPPictureFree(&sub_image);
WebPFree(tmp);
free(tmp);
return ok;
}

View File

@ -27,7 +27,6 @@
#include "../imageio/image_dec.h"
#include "../imageio/imageio_util.h"
#include "./stopwatch.h"
#include "./unicode.h"
#include "webp/encode.h"
#include "webp/mux.h"
@ -84,7 +83,7 @@ static int ReadImage(const char filename[], WebPPicture* const pic) {
if (!ImgIoUtilReadFile(filename, &data, &data_size)) return 0;
reader = WebPGuessImageReader(data, data_size);
ok = reader(data, data_size, pic, 1, NULL);
WebPFree((void*)data);
free((void*)data);
return ok;
}
@ -139,13 +138,8 @@ int main(int argc, const char* argv[]) {
int c;
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);
int ok = ExUtilInitCommandLineArguments(argc - 1, argv + 1, &cmd_args);
if (!ok) return 1;
argc = cmd_args.argc_;
argv = cmd_args.argv_;
@ -164,7 +158,7 @@ int main(int argc, const char* argv[]) {
int parse_error = 0;
if (!strcmp(argv[c], "-o") && c + 1 < argc) {
argv[c] = NULL;
output = (const char*)GET_WARGV_SHIFTED(argv, ++c);
output = argv[++c];
} else if (!strcmp(argv[c], "-kmin") && c + 1 < argc) {
argv[c] = NULL;
anim_config.kmin = ExUtilGetInt(argv[++c], 0, &parse_error);
@ -251,7 +245,7 @@ int main(int argc, const char* argv[]) {
// read next input image
pic.use_argb = 1;
ok = ReadImage((const char*)GET_WARGV_SHIFTED(argv, c), &pic);
ok = ReadImage(argv[c], &pic);
if (!ok) goto End;
if (enc == NULL) {
@ -283,8 +277,8 @@ int main(int argc, const char* argv[]) {
if (!ok) goto End;
if (verbose) {
WFPRINTF(stderr, "Added frame #%3d at time %4d (file: %s)\n",
pic_num, timestamp_ms, GET_WARGV_SHIFTED(argv, c));
fprintf(stderr, "Added frame #%3d at time %4d (file: %s)\n",
pic_num, timestamp_ms, argv[c]);
}
timestamp_ms += duration;
++pic_num;
@ -308,7 +302,7 @@ int main(int argc, const char* argv[]) {
if (ok) {
if (output != NULL) {
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 {
fprintf(stderr, "[no output file specified] ");
}
@ -320,5 +314,5 @@ int main(int argc, const char* argv[]) {
}
WebPDataClear(&webp_data);
ExUtilDeleteCommandLineArguments(&cmd_args);
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
return ok ? 0 : 1;
}

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 "../imageio/imageio_util.h"
#include "./unicode.h"
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
@ -418,9 +417,8 @@ static void HandleDisplay(void) {
}
static void StartDisplay(void) {
int width = kParams.canvas_width;
int height = kParams.canvas_height;
int screen_width, screen_height;
const int width = kParams.canvas_width;
const int height = kParams.canvas_height;
// TODO(webp:365) GLUT_DOUBLE results in flickering / old frames to be
// partially displayed with animated webp + alpha.
#if defined(__APPLE__) || defined(_WIN32)
@ -428,18 +426,6 @@ static void StartDisplay(void) {
#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);
glutCreateWindow("WebP viewer");
glutDisplayFunc(HandleDisplay);
@ -479,16 +465,14 @@ static void Help(void) {
" 'q' / 'Q' / ESC .... quit\n");
}
int main(int argc, char* argv[]) {
int main(int argc, char *argv[]) {
int c;
WebPDecoderConfig* const config = &kParams.config;
WebPIterator* const curr = &kParams.curr_frame;
INIT_WARGV(argc, argv);
if (!WebPInitDecoderConfig(config)) {
fprintf(stderr, "Library version mismatch!\n");
FREE_WARGV_AND_RETURN(-1);
return -1;
}
config->options.dithering_strength = 50;
config->options.alpha_dithering_strength = 100;
@ -500,7 +484,7 @@ int main(int argc, char* argv[]) {
int parse_error = 0;
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
Help();
FREE_WARGV_AND_RETURN(0);
return 0;
} else if (!strcmp(argv[c], "-noicc")) {
kParams.use_color_profile = 0;
} else if (!strcmp(argv[c], "-nofancy")) {
@ -523,30 +507,30 @@ int main(int argc, char* argv[]) {
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
dec_version & 0xff, (dmux_version >> 16) & 0xff,
(dmux_version >> 8) & 0xff, dmux_version & 0xff);
FREE_WARGV_AND_RETURN(0);
return 0;
} else if (!strcmp(argv[c], "-mt")) {
config->options.use_threads = 1;
} 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;
} else if (argv[c][0] == '-') {
printf("Unknown option '%s'\n", argv[c]);
Help();
FREE_WARGV_AND_RETURN(-1);
return -1;
} else {
kParams.file_name = (const char*)GET_WARGV(argv, c);
kParams.file_name = argv[c];
}
if (parse_error) {
Help();
FREE_WARGV_AND_RETURN(-1);
return -1;
}
}
if (kParams.file_name == NULL) {
printf("missing input file!!\n");
Help();
FREE_WARGV_AND_RETURN(0);
return 0;
}
if (!ImgIoUtilReadFile(kParams.file_name,
@ -621,16 +605,16 @@ int main(int argc, char* argv[]) {
// Should only be reached when using FREEGLUT:
ClearParams();
FREE_WARGV_AND_RETURN(0);
return 0;
Error:
ClearParams();
FREE_WARGV_AND_RETURN(-1);
return -1;
}
#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]);
(void)argc;
return 0;

View File

@ -20,7 +20,6 @@
#endif
#include "../imageio/imageio_util.h"
#include "./unicode.h"
#include "webp/decode.h"
#include "webp/format_constants.h"
#include "webp/mux_types.h"
@ -1120,21 +1119,19 @@ int main(int argc, const char* argv[]) {
WebPInfoStatus webp_info_status = WEBP_INFO_OK;
WebPInfo webp_info;
INIT_WARGV(argc, argv);
if (argc == 1) {
HelpShort();
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
return WEBP_INFO_OK;
}
// Parse command-line input.
for (c = 1; c < argc; ++c) {
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
HelpShort();
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
return WEBP_INFO_OK;
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
HelpLong();
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
return WEBP_INFO_OK;
} else if (!strcmp(argv[c], "-quiet")) {
quiet = 1;
} else if (!strcmp(argv[c], "-diag")) {
@ -1147,7 +1144,7 @@ int main(int argc, const char* argv[]) {
const int version = WebPGetDecoderVersion();
printf("WebP Decoder version: %d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
FREE_WARGV_AND_RETURN(0);
return 0;
} else { // Assume the remaining are all input files.
break;
}
@ -1155,28 +1152,27 @@ int main(int argc, const char* argv[]) {
if (c == argc) {
HelpShort();
FREE_WARGV_AND_RETURN(WEBP_INFO_INVALID_COMMAND);
return WEBP_INFO_INVALID_COMMAND;
}
// Process input files one by one.
for (; c < argc; ++c) {
WebPData webp_data;
const W_CHAR* in_file = NULL;
const char* in_file = NULL;
WebPInfoInit(&webp_info);
webp_info.quiet_ = quiet;
webp_info.show_diagnosis_ = show_diag;
webp_info.show_summary_ = show_summary;
webp_info.parse_bitstream_ = parse_bitstream;
in_file = GET_WARGV(argv, c);
if (in_file == NULL ||
!ReadFileToWebPData((const char*)in_file, &webp_data)) {
in_file = argv[c];
if (in_file == NULL || !ReadFileToWebPData(in_file, &webp_data)) {
webp_info_status = WEBP_INFO_INVALID_COMMAND;
WFPRINTF(stderr, "Failed to open input file %s.\n", in_file);
fprintf(stderr, "Failed to open input file %s.\n", in_file);
continue;
}
if (!webp_info.quiet_) WPRINTF("File: %s\n", in_file);
if (!webp_info.quiet_) printf("File: %s\n", in_file);
webp_info_status = AnalyzeWebP(&webp_info, &webp_data);
WebPDataClear(&webp_data);
}
FREE_WARGV_AND_RETURN(webp_info_status);
return webp_info_status;
}

View File

@ -26,7 +26,6 @@
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 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:
webpmux -get frame n in.webp -o out_frame.webp
@ -63,7 +62,6 @@
#include "webp/mux.h"
#include "../examples/example_util.h"
#include "../imageio/imageio_util.h"
#include "./unicode.h"
//------------------------------------------------------------------------------
// Config object to parse command-line arguments.
@ -98,7 +96,6 @@ typedef enum {
FEATURE_ICCP,
FEATURE_ANMF,
FEATURE_DURATION,
FEATURE_LOOP,
LAST_FEATURE
} FeatureType;
@ -316,7 +313,6 @@ static void PrintHelp(void) {
printf("\n");
printf("SET_OPTIONS:\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(" exif file.exif set EXIF metadata\n");
printf(" xmp file.xmp set XMP metadata\n");
@ -394,25 +390,23 @@ static int CreateMux(const char* const filename, WebPMux** mux) {
*mux = WebPMuxCreate(&bitstream, 1);
WebPDataClear(&bitstream);
if (*mux != NULL) return 1;
WFPRINTF(stderr, "Failed to create mux object from file %s.\n",
(const W_CHAR*)filename);
fprintf(stderr, "Failed to create mux object from file %s.\n", filename);
return 0;
}
static int WriteData(const char* filename, const WebPData* const webpdata) {
int ok = 0;
FILE* fout = WSTRCMP(filename, "-") ? WFOPEN(filename, "wb")
: ImgIoUtilSetBinaryMode(stdout);
FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb")
: ImgIoUtilSetBinaryMode(stdout);
if (fout == NULL) {
WFPRINTF(stderr, "Error opening output WebP file %s!\n",
(const W_CHAR*)filename);
fprintf(stderr, "Error opening output WebP file %s!\n", filename);
return 0;
}
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 {
WFPRINTF(stderr, "Saved file %s (%d bytes)\n",
(const W_CHAR*)filename, (int)webpdata->size);
fprintf(stderr, "Saved file %s (%d bytes)\n",
filename, (int)webpdata->size);
ok = 1;
}
if (fout != stdout) fclose(fout);
@ -472,11 +466,11 @@ static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) {
}
static int ParseFrameArgs(const char* args, WebPMuxFrameInfo* const info) {
int dispose_method, unused;
int dispose_method, dummy;
char plus_minus, blend_method;
const int num_args = sscanf(args, "+%d+%d+%d+%d%c%c+%d", &info->duration,
&info->x_offset, &info->y_offset, &dispose_method,
&plus_minus, &blend_method, &unused);
&plus_minus, &blend_method, &dummy);
switch (num_args) {
case 1:
info->x_offset = info->y_offset = 0; // fall through
@ -495,7 +489,7 @@ static int ParseFrameArgs(const char* args, WebPMuxFrameInfo* const info) {
WarnAboutOddOffset(info);
// Note: The validity of the following conversion is checked by
// Note: The sanity of the following conversion is checked by
// WebPMuxPushFrame().
info->dispose_method = (WebPMuxAnimDispose)dispose_method;
@ -618,16 +612,13 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
CHECK_NUM_ARGS_AT_MOST(NUM, LABEL);
// Parses command-line arguments to fill up config object. Also performs some
// semantic checks. unicode_argv contains wchar_t arguments or is null.
static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
// semantic checks.
static int ParseCommandLine(Config* config) {
int i = 0;
int feature_arg_index = 0;
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) {
FeatureArg* const arg = &config->args_[feature_arg_index];
@ -705,7 +696,7 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
i += 2;
} else if (!strcmp(argv[i], "-o")) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
config->output_ = wargv[i + 1];
config->output_ = argv[i + 1];
i += 2;
} else if (!strcmp(argv[i], "-info")) {
CHECK_NUM_ARGS_EXACTLY(2, ErrParse);
@ -714,26 +705,24 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
} else {
config->action_type_ = ACTION_INFO;
config->arg_count_ = 0;
config->input_ = wargv[i + 1];
config->input_ = argv[i + 1];
}
i += 2;
} else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help")) {
PrintHelp();
DeleteConfig(config);
LOCAL_FREE((W_CHAR** const)unicode_argv);
exit(0);
} else if (!strcmp(argv[i], "-version")) {
const int version = WebPGetMuxVersion();
printf("%d.%d.%d\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
DeleteConfig(config);
LOCAL_FREE((W_CHAR** const)unicode_argv);
exit(0);
} else if (!strcmp(argv[i], "--")) {
if (i < argc - 1) {
++i;
if (config->input_ == NULL) {
config->input_ = wargv[i];
config->input_ = argv[i];
} else {
ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n",
argv[i], ErrParse);
@ -758,7 +747,7 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
}
if (config->action_type_ == ACTION_SET) {
CHECK_NUM_ARGS_AT_LEAST(2, ErrParse);
arg->filename_ = wargv[i + 1];
arg->filename_ = argv[i + 1];
++feature_arg_index;
i += 2;
} else {
@ -771,16 +760,9 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
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];
++feature_arg_index;
i += 2;
} else { // Assume input file.
if (config->input_ == NULL) {
config->input_ = wargv[i];
config->input_ = argv[i];
} else {
ERROR_GOTO2("ERROR at '%s': Multiple input files specified.\n",
argv[i], ErrParse);
@ -826,8 +808,8 @@ static int ValidateConfig(Config* const config) {
}
// Create config object from command-line arguments.
static int InitializeConfig(int argc, const char* argv[], Config* const config,
const W_CHAR** const unicode_argv) {
static int InitializeConfig(int argc, const char* argv[],
Config* const config) {
int num_feature_args = 0;
int ok;
@ -848,7 +830,7 @@ static int InitializeConfig(int argc, const char* argv[], Config* const config,
}
// Parse command-line.
if (!ParseCommandLine(config, unicode_argv) || !ValidateConfig(config)) {
if (!ParseCommandLine(config) || !ValidateConfig(config)) {
ERROR_GOTO1("Exiting due to command-line parsing error.\n", Err1);
}
@ -1021,38 +1003,13 @@ static int Process(const Config* config) {
ok = ExUtilReadFileToWebPData(config->args_[0].filename_, &chunk);
if (!ok) goto Err2;
err = WebPMuxSetChunk(mux, kFourccList[config->type_], &chunk, 1);
WebPDataClear(&chunk);
free((void*)chunk.bytes);
if (err != WEBP_MUX_OK) {
ERROR_GOTO3("ERROR (%s): Could not set the %s.\n",
ErrorString(err), kDescriptions[config->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;
}
default: {
ERROR_GOTO1("ERROR: Invalid feature for action 'set'.\n", Err2);
break;
@ -1080,7 +1037,7 @@ static int Process(const Config* config) {
int* durations = NULL;
WebPMux* new_mux = DuplicateMuxHeader(mux);
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;
for (i = 0; i < num_frames; ++i) durations[i] = -1;
@ -1138,7 +1095,7 @@ static int Process(const Config* config) {
new_mux = NULL;
Err3:
WebPFree(durations);
free(durations);
WebPMuxDelete(new_mux);
if (!ok) goto Err2;
}
@ -1183,18 +1140,14 @@ static int Process(const Config* config) {
int main(int argc, const char* argv[]) {
Config config;
int ok;
INIT_WARGV(argc, argv);
ok = InitializeConfig(argc - 1, argv + 1, &config, GET_WARGV_OR_NULL());
int ok = InitializeConfig(argc - 1, argv + 1, &config);
if (ok) {
ok = Process(&config);
} else {
PrintHelp();
}
DeleteConfig(&config);
FREE_WARGV_AND_RETURN(!ok);
return !ok;
}
//------------------------------------------------------------------------------

View File

@ -12,13 +12,12 @@
#include "extras/extras.h"
#include "webp/format_constants.h"
#include "src/dsp/dsp.h"
#include <assert.h>
#include <string.h>
#define XTRA_MAJ_VERSION 1
#define XTRA_MIN_VERSION 2
#define XTRA_MIN_VERSION 0
#define XTRA_REV_VERSION 1
//------------------------------------------------------------------------------
@ -58,7 +57,7 @@ int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) {
for (y = 0; y < pic->height; ++y) {
const int width = pic->width;
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 gb = rgb565[2 * x + 0];
#else
@ -91,7 +90,7 @@ int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) {
for (y = 0; y < pic->height; ++y) {
const int width = pic->width;
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 ba = rgb4444[2 * x + 0];
#else
@ -145,18 +144,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,7 +19,7 @@ extern "C" {
#include "webp/encode.h"
#define WEBP_EXTRAS_ABI_VERSION 0x0002 // MAJOR(8b) + MINOR(8b)
#define WEBP_EXTRAS_ABI_VERSION 0x0001 // MAJOR(8b) + MINOR(8b)
//------------------------------------------------------------------------------
@ -51,13 +51,6 @@ WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride,
const uint32_t palette[], int palette_size,
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

View File

@ -26,7 +26,6 @@
#include "webp/encode.h"
#include "imageio/image_dec.h"
#include "imageio/imageio_util.h"
#include "../examples/unicode.h"
static size_t ReadPicture(const char* const filename, WebPPicture* const pic,
int keep_alpha) {
@ -49,8 +48,7 @@ static size_t ReadPicture(const char* const filename, WebPPicture* const pic,
End:
if (!ok) {
WFPRINTF(stderr, "Error! Could not process file %s\n",
(const W_CHAR*)filename);
fprintf(stderr, "Error! Could not process file %s\n", filename);
}
free((void*)data);
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");
}
int main(int argc, const char* argv[]) {
int main(int argc, const char *argv[]) {
WebPPicture pic1, pic2;
size_t size1 = 0, size2 = 0;
int ret = 1;
@ -241,11 +239,9 @@ int main(int argc, const char* argv[]) {
const char* name2 = NULL;
const char* output = NULL;
INIT_WARGV(argc, argv);
if (!WebPPictureInit(&pic1) || !WebPPictureInit(&pic2)) {
fprintf(stderr, "Can't init pictures\n");
FREE_WARGV_AND_RETURN(1);
return 1;
}
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]);
goto End;
}
output = (const char*)GET_WARGV(argv, c);
output = argv[c];
} else if (name1 == NULL) {
name1 = (const char*)GET_WARGV(argv, c);
name1 = argv[c];
} else {
name2 = (const char*)GET_WARGV(argv, c);
name2 = argv[c];
}
}
if (help || name1 == NULL || name2 == NULL) {
@ -351,5 +347,5 @@ int main(int argc, const char* argv[]) {
End:
WebPPictureFree(&pic1);
WebPPictureFree(&pic2);
FREE_WARGV_AND_RETURN(ret);
return ret;
}

View File

@ -25,7 +25,6 @@
#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>
@ -52,33 +51,29 @@ static void ProcessEvents(void) {
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);
return 0;
} else {
file = (const char*)GET_WARGV(argv, c);
file = argv[c];
}
if (file == NULL) continue;
if (!ImgIoUtilReadFile(file, &webp, &webp_size)) {
WFPRINTF(stderr, "Error opening file: %s\n", (const W_CHAR*)file);
fprintf(stderr, "Error opening file: %s\n", 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);
fprintf(stderr, "Error decoding file %s\n", file);
goto Error;
}
ProcessEvents();
@ -87,12 +82,12 @@ int main(int argc, char* argv[]) {
Error:
SDL_Quit();
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
return ok ? 0 : 1;
}
#else // !WEBP_HAVE_SDL
int main(int argc, const char* argv[]) {
int main(int argc, const char *argv[]) {
fprintf(stderr, "SDL support not enabled in %s.\n", argv[0]);
(void)argc;
return 0;

View File

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

Binary file not shown.

View File

@ -1,5 +1,6 @@
#Thu May 12 17:06:25 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
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
#
# 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.
#
#!/usr/bin/env bash
##############################################################################
##
@ -44,16 +28,16 @@ APP_NAME="Gradle"
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.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
warn ( ) {
echo "$*"
}
die () {
die ( ) {
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\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
@ -154,30 +138,27 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
i=$((i+1))
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
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
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" "$@"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

190
gradlew.bat vendored
View File

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

@ -29,13 +29,11 @@
// code with COBJMACROS.
#include <ole2.h> // CreateStreamOnHGlobal()
#include <shlwapi.h>
#include <tchar.h>
#include <windows.h>
#include <wincodec.h>
#endif
#include "./imageio_util.h"
#include "../examples/unicode.h"
//------------------------------------------------------------------------------
// 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.
IFS(CreateStreamOnHGlobal(NULL, TRUE, stream));
} else {
IFS(SHCreateStreamOnFile((const LPTSTR)out_file_name,
STGM_WRITE | STGM_CREATE, stream));
IFS(SHCreateStreamOnFileA(out_file_name, STGM_WRITE | STGM_CREATE, stream));
}
if (FAILED(hr)) {
_ftprintf(stderr, _T("Error opening output file %s (%08lx)\n"),
(const LPTSTR)out_file_name, hr);
fprintf(stderr, "Error opening output file %s (%08lx)\n",
out_file_name, hr);
}
return hr;
}
@ -155,8 +152,8 @@ int WebPWritePNG(const char* out_file_name, int use_stdout,
}
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp unused) {
(void)unused; // remove variable-unused warning
static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp dummy) {
(void)dummy; // remove variable-unused warning
longjmp(png_jmpbuf(png), 1);
}
@ -320,7 +317,7 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
PutLE16(bmp_header + 26, 1); // number of planes
PutLE16(bmp_header + 28, bytes_per_px * 8); // bits per pixel
PutLE32(bmp_header + 30, 0); // no compression (BI_RGB)
PutLE32(bmp_header + 34, 0); // image size (placeholder)
PutLE32(bmp_header + 34, 0); // image size (dummy)
PutLE32(bmp_header + 38, 2400); // x pixels/meter
PutLE32(bmp_header + 42, 2400); // y pixels/meter
PutLE32(bmp_header + 46, 0); // number of palette colors
@ -552,8 +549,7 @@ int WebPSaveImage(const WebPDecBuffer* const buffer,
const char* const out_file_name) {
FILE* fout = NULL;
int needs_open_file = 1;
const int use_stdout =
(out_file_name != NULL) && !WSTRCMP(out_file_name, "-");
const int use_stdout = (out_file_name != NULL) && !strcmp(out_file_name, "-");
int ok = 1;
if (buffer == NULL || out_file_name == NULL) return 0;
@ -564,10 +560,9 @@ int WebPSaveImage(const WebPDecBuffer* const buffer,
if (needs_open_file) {
fout = use_stdout ? ImgIoUtilSetBinaryMode(stdout)
: WFOPEN(out_file_name, "wb");
: fopen(out_file_name, "wb");
if (fout == NULL) {
WFPRINTF(stderr, "Error opening output file %s\n",
(const W_CHAR*)out_file_name);
fprintf(stderr, "Error opening output file %s\n", out_file_name);
return 0;
}
}

View File

@ -18,7 +18,6 @@
#endif
#include <stdlib.h>
#include <string.h>
#include "../examples/unicode.h"
// -----------------------------------------------------------------------------
// File I/O
@ -74,7 +73,7 @@ int ImgIoUtilReadFile(const char* const file_name,
uint8_t* file_data;
size_t file_size;
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);
@ -82,29 +81,29 @@ int ImgIoUtilReadFile(const char* const file_name,
*data = NULL;
*data_size = 0;
in = WFOPEN(file_name, "rb");
in = fopen(file_name, "rb");
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;
}
fseek(in, 0, SEEK_END);
file_size = ftell(in);
fseek(in, 0, SEEK_SET);
// we allocate one extra byte for the \0 terminator
file_data = (uint8_t*)WebPMalloc(file_size + 1);
file_data = (uint8_t*)malloc(file_size + 1);
if (file_data == NULL) {
fclose(in);
WFPRINTF(stderr, "memory allocation failure when reading file %s\n",
(const W_CHAR*)file_name);
fprintf(stderr, "memory allocation failure when reading file %s\n",
file_name);
return 0;
}
ok = (fread(file_data, file_size, 1, in) == 1);
fclose(in);
if (!ok) {
WFPRINTF(stderr, "Could not read %d bytes of data from file %s\n",
(int)file_size, (const W_CHAR*)file_name);
WebPFree(file_data);
fprintf(stderr, "Could not read %d bytes of data from file %s\n",
(int)file_size, file_name);
free(file_data);
return 0;
}
file_data[file_size] = '\0'; // convenient 0-terminator
@ -119,15 +118,14 @@ int ImgIoUtilWriteFile(const char* const file_name,
const uint8_t* data, size_t data_size) {
int ok;
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) {
return 0;
}
out = to_stdout ? ImgIoUtilSetBinaryMode(stdout) : WFOPEN(file_name, "wb");
out = to_stdout ? ImgIoUtilSetBinaryMode(stdout) : fopen(file_name, "wb");
if (out == NULL) {
WFPRINTF(stderr, "Error! Cannot open output file '%s'\n",
(const W_CHAR*)file_name);
fprintf(stderr, "Error! Cannot open output file '%s'\n", file_name);
return 0;
}
ok = (fwrite(data, data_size, 1, out) == 1);
@ -148,11 +146,9 @@ void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
// -----------------------------------------------------------------------------
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height) {
const uint64_t total_size = stride * height;
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
const uint64_t total_size = nmemb * size;
int ok = (total_size == (size_t)total_size);
// check that 'stride' is representable as int:
ok = ok && ((uint64_t)(int)stride == stride);
#if defined(WEBP_MAX_IMAGE_SIZE)
ok = ok && (total_size <= (uint64_t)WEBP_MAX_IMAGE_SIZE);
#endif

View File

@ -29,7 +29,7 @@ FILE* ImgIoUtilSetBinaryMode(FILE* file);
// 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
// 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.
@ -54,8 +54,8 @@ void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
//------------------------------------------------------------------------------
// Returns 0 in case of overflow, memory over-allocation or excessive dimension.
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height);
// Returns 0 in case of overflow of nmemb * size.
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t nmemb, size_t size);
#ifdef __cplusplus
} // extern "C"

View File

@ -206,7 +206,6 @@ struct my_error_mgr {
static void my_error_exit(j_common_ptr dinfo) {
struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err;
fprintf(stderr, "libjpeg error: ");
dinfo->err->output_message(dinfo);
longjmp(myerr->setjmp_buffer, 1);
}
@ -274,7 +273,7 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
ctx.data = data;
ctx.data_size = data_size;
memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp safety
memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp sanity
dinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;

View File

@ -259,15 +259,6 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
goto End;
}
#if LOCAL_PNG_PREREQ(1,5) || \
(LOCAL_PNG_PREREQ(1,4) && PNG_LIBPNG_VER_RELEASE >= 1)
// 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);
}
#endif
info = png_create_info_struct(png);
if (info == NULL) goto Error;
end_info = png_create_info_struct(png);

View File

@ -26,15 +26,15 @@ typedef enum {
DEPTH_FLAG = 1 << 2,
MAXVAL_FLAG = 1 << 3,
TUPLE_FLAG = 1 << 4,
ALL_NEEDED_FLAGS = WIDTH_FLAG | HEIGHT_FLAG | DEPTH_FLAG | MAXVAL_FLAG
ALL_NEEDED_FLAGS = 0x1f
} 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 bytes_per_px; // 1, 3, 4
int depth;
int max_value;
int type; // 5, 6 or 7
int seen_flags;
@ -74,7 +74,6 @@ 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);
@ -96,16 +95,13 @@ static size_t ReadPAMFields(PNMInfo* const info, size_t off) {
info->seen_flags |= MAXVAL_FLAG;
info->max_value = tmp;
} else if (!strcmp(out, "TUPLTYPE RGB_ALPHA")) {
expected_depth = 4;
info->bytes_per_px = 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->bytes_per_px = 3;
info->seen_flags |= TUPLE_FLAG;
} else if (!strcmp(out, "TUPLTYPE GRAYSCALE")) {
expected_depth = 1;
info->bytes_per_px = 1;
info->seen_flags |= TUPLE_FLAG;
} else if (!strcmp(out, "ENDHDR")) {
break;
@ -114,24 +110,23 @@ static size_t ReadPAMFields(PNMInfo* const info, size_t off) {
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] = ' ';
if (!isprint(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 (!(info->seen_flags & TUPLE_FLAG)) {
if (info->depth > 0 && info->depth <= 4 && info->depth != 2) {
info->seen_flags |= TUPLE_FLAG;
info->bytes_per_px = info->depth * (info->max_value > 255 ? 2 : 1);
} else {
fprintf(stderr, "PAM: invalid bitdepth (%d).\n", info->depth);
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);
if (info->seen_flags != ALL_NEEDED_FLAGS) {
fprintf(stderr, "PAM: incomplete header.\n");
return 0;
}
return off;
@ -165,15 +160,16 @@ static size_t ReadHeader(PNMInfo* const info) {
// finish initializing missing fields
info->depth = (info->type == 5) ? 1 : 3;
info->bytes_per_px = info->depth * (info->max_value > 255 ? 2 : 1);
}
// 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->depth <= 0 || info->depth == 2 || info->depth > 4 ||
info->bytes_per_px < info->depth ||
info->max_value <= 0 || info->max_value >= 65536) {
return 0;
}
info->bytes_per_px = info->depth * (info->max_value > 255 ? 2 : 1);
return off;
}
@ -182,7 +178,7 @@ int ReadPNM(const uint8_t* const data, size_t data_size,
struct Metadata* const metadata) {
int ok = 0;
int i, j;
uint64_t stride, pixel_bytes, sample_size, depth;
uint64_t stride, pixel_bytes;
uint8_t* rgb = NULL, *tmp_rgb;
size_t offset;
PNMInfo info;
@ -213,10 +209,8 @@ int ReadPNM(const uint8_t* const data, size_t data_size,
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;
stride =
(uint64_t)(info.bytes_per_px < 3 ? 3 : info.bytes_per_px) * info.width;
if (stride != (size_t)stride ||
!ImgIoUtilCheckSizeArgumentsOverflow(stride, info.height)) {
goto End;
@ -225,63 +219,30 @@ int ReadPNM(const uint8_t* const data, size_t data_size,
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.
// Convert input
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
}
assert(offset + info.bytes_per_px * info.width <= data_size);
if (info.depth == 1) {
// convert grayscale -> RGB
for (i = 0; i < info.width; ++i) {
const uint8_t v = data[offset + i];
tmp_rgb[3 * i + 0] = tmp_rgb[3 * i + 1] = tmp_rgb[3 * i + 2] = v;
}
} else if (info.depth == 3) { // RGB
memcpy(tmp_rgb, data + offset, 3 * info.width * sizeof(*data));
} else if (info.depth == 4) { // RGBA
memcpy(tmp_rgb, data + offset, 4 * info.width * sizeof(*data));
}
offset += info.bytes_per_px * info.width;
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);
ok = (info.depth == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride)
: WebPPictureImportRGB(pic, rgb, (int)stride);
if (!ok) goto End;
ok = 1;

View File

@ -156,8 +156,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
Metadata* const metadata) {
MyData my_data = { data, (toff_t)data_size, 0 };
TIFF* tif;
uint32_t image_width, image_height, tile_width, tile_height;
uint64_t stride;
uint32_t width, height;
uint16_t samples_per_px = 0;
uint16_t extra_samples = 0;
uint16_t* extra_samples_ptr = NULL;
@ -190,36 +189,15 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
}
if (samples_per_px < 3 || samples_per_px > 4) goto End; // not supported
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width) &&
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height))) {
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) &&
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))) {
fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
goto End;
}
stride = (uint64_t)image_width * sizeof(*raster);
if (!ImgIoUtilCheckSizeArgumentsOverflow(stride, image_height)) {
fprintf(stderr, "Error! TIFF image dimension (%d x %d) is too large.\n",
image_width, image_height);
if (!ImgIoUtilCheckSizeArgumentsOverflow((uint64_t)width * height,
sizeof(*raster))) {
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. We also check that they respect WebP's dimension and memory limit.
// Note that a tile can be 6byte/px in some cases. Here we assume
// 4byte/px with sizeof(*raster), to be conservative.
if (TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) &&
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height)) {
if ((tile_width > 32 && tile_width / 2 > image_width) ||
(tile_height > 32 && tile_height / 2 > image_height) ||
ImgIoUtilCheckSizeArgumentsOverflow(
(uint64_t)tile_width * sizeof(*raster), tile_height)) {
fprintf(stderr, "Error! TIFF tile dimension (%d x %d) is too large.\n",
tile_width, tile_height);
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");
@ -227,32 +205,33 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
}
// _Tiffmalloc uses a signed type for size.
alloc_size = (int64_t)(stride * image_height);
alloc_size = (int64_t)((uint64_t)width * height * sizeof(*raster));
if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End;
raster = (uint32*)_TIFFmalloc((tsize_t)alloc_size);
if (raster != NULL) {
if (TIFFReadRGBAImageOriented(tif, image_width, image_height, raster,
if (TIFFReadRGBAImageOriented(tif, width, height, raster,
ORIENTATION_TOPLEFT, 1)) {
pic->width = image_width;
pic->height = image_height;
const int stride = width * sizeof(*raster);
pic->width = width;
pic->height = height;
// TIFF data is ABGR
#ifdef WORDS_BIGENDIAN
TIFFSwabArrayOfLong(raster, image_width * image_height);
TIFFSwabArrayOfLong(raster, width * height);
#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);
for (y = 0; y < height; ++y) {
MultARGBRow(tmp, width);
tmp += stride;
}
}
ok = keep_alpha
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, (int)stride)
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, (int)stride);
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);
}
_TIFFfree(raster);
} else {

View File

@ -22,7 +22,6 @@
#include "webp/decode.h"
#include "webp/demux.h"
#include "webp/encode.h"
#include "../examples/unicode.h"
#include "./imageio_util.h"
#include "./metadata.h"
@ -44,7 +43,7 @@ static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
}
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);
if (status >= VP8_STATUS_OK && status <= VP8_STATUS_NOT_ENOUGH_DATA) {
fprintf(stderr, "(%s)", kStatusMessages[status]);
@ -65,7 +64,7 @@ int LoadWebP(const char* const in_file,
status = WebPGetFeatures(*data, *data_size, bitstream);
if (status != VP8_STATUS_OK) {
WebPFree((void*)*data);
free((void*)*data);
*data = NULL;
*data_size = 0;
PrintWebPError(in_file, status);
@ -95,7 +94,7 @@ VP8StatusCode DecodeWebPIncremental(
{
WebPIDecoder* const idec = WebPIDecode(data, data_size, config);
if (idec == NULL) {
fprintf(stderr, "Failed during WebPIDecode().\n");
fprintf(stderr, "Failed during WebPINewDecoder().\n");
return VP8_STATUS_OUT_OF_MEMORY;
} else {
status = WebPIUpdate(idec, data, data_size);

View File

@ -29,14 +29,12 @@
// code with COBJMACROS.
#include <ole2.h> // CreateStreamOnHGlobal()
#include <shlwapi.h>
#include <tchar.h>
#include <windows.h>
#include <wincodec.h>
#include "../examples/unicode.h"
#include "webp/encode.h"
#include "./imageio_util.h"
#include "./metadata.h"
#include "webp/encode.h"
#define IFS(fn) \
do { \
@ -87,7 +85,7 @@ WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppRGBA_,
static HRESULT OpenInputStream(const char* filename, IStream** stream) {
HRESULT hr = S_OK;
if (!WSTRCMP(filename, "-")) {
if (!strcmp(filename, "-")) {
const uint8_t* data = NULL;
size_t data_size = 0;
const int ok = ImgIoUtilReadFile(filename, &data, &data_size);
@ -110,12 +108,11 @@ static HRESULT OpenInputStream(const char* filename, IStream** stream) {
hr = E_FAIL;
}
} else {
IFS(SHCreateStreamOnFile((const LPTSTR)filename, STGM_READ, stream));
IFS(SHCreateStreamOnFileA(filename, STGM_READ, stream));
}
if (FAILED(hr)) {
_ftprintf(stderr, _T("Error opening input file %s (%08lx)\n"),
(const LPTSTR)filename, hr);
fprintf(stderr, "Error opening input file %s (%08lx)\n", filename, hr);
}
return hr;
}
@ -134,10 +131,7 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
IWICColorContext** color_contexts;
IFS(IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count));
if (FAILED(hr) || count == 0) {
// Treat unsupported operation as a non-fatal error. See crbug.com/webp/506.
return (hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) ? S_OK : hr;
}
if (FAILED(hr) || count == 0) return hr;
color_contexts = (IWICColorContext**)calloc(count, sizeof(*color_contexts));
if (color_contexts == NULL) return E_OUTOFMEMORY;
@ -273,15 +267,10 @@ int ReadPictureWithWIC(const char* const filename,
WICPixelFormatGUID src_pixel_format = GUID_WICPixelFormatUndefined;
const WICFormatImporter* importer = NULL;
GUID src_container_format = GUID_NULL_;
// From Windows Kits\10\Include\10.0.19041.0\um\wincodec.h
WEBP_DEFINE_GUID(GUID_ContainerFormatWebp_,
0xe094b0e2, 0x67f2, 0x45b3,
0xb0, 0xea, 0x11, 0x53, 0x37, 0xca, 0x7c, 0xf3);
static const GUID* kAlphaContainers[] = {
&GUID_ContainerFormatBmp,
&GUID_ContainerFormatPng,
&GUID_ContainerFormatTiff,
&GUID_ContainerFormatWebp_,
NULL
};
int has_alpha = 0;
@ -306,15 +295,9 @@ int ReadPictureWithWIC(const char* const filename,
factory, stream, NULL,
WICDecodeMetadataCacheOnDemand, &decoder));
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
if (SUCCEEDED(hr)) {
if (frame_count == 0) {
fprintf(stderr, "No frame found in input file.\n");
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;
}
if (SUCCEEDED(hr) && frame_count == 0) {
fprintf(stderr, "No frame found in input file.\n");
hr = E_FAIL;
}
IFS(IWICBitmapDecoder_GetFrame(decoder, 0, &frame));
IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format));

View File

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

@ -118,10 +118,6 @@ GROFF = /usr/bin/groff
COL = /usr/bin/col
LDFLAGS = $(EXTRA_LIBS) $(EXTRA_FLAGS) -lm
ifdef BITTRACE
CFLAGS += -DBITTRACE=$(BITTRACE)
endif
ANIM_UTIL_OBJS = \
examples/anim_util.o \
@ -166,7 +162,6 @@ DSP_DEC_OBJS = \
src/dsp/lossless_msa.o \
src/dsp/lossless_neon.o \
src/dsp/lossless_sse2.o \
src/dsp/lossless_sse41.o \
src/dsp/rescaler.o \
src/dsp/rescaler_mips32.o \
src/dsp/rescaler_mips_dsp_r2.o \
@ -190,7 +185,6 @@ DSP_ENC_OBJS = \
src/dsp/cost.o \
src/dsp/cost_mips32.o \
src/dsp/cost_mips_dsp_r2.o \
src/dsp/cost_neon.o \
src/dsp/cost_sse2.o \
src/dsp/enc.o \
src/dsp/enc_mips32.o \
@ -403,7 +397,7 @@ examples/webpinfo: examples/webpinfo.o
examples/anim_diff: examples/libanim_util.a examples/libgifdec.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: override EXTRA_LIBS += $(GIF_LIBS)
examples/anim_diff: EXTRA_LIBS += $(GIF_LIBS)
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
@ -411,27 +405,27 @@ 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/anim_dump: EXTRA_LIBS += $(GIF_LIBS) $(DWEBP_LIBS)
examples/cwebp: examples/libexample_util.a
examples/cwebp: imageio/libimagedec.a
examples/cwebp: src/demux/libwebpdemux.a
examples/cwebp: imageio/libimageio_util.a
examples/cwebp: src/libwebp.a
examples/cwebp: override EXTRA_LIBS += $(CWEBP_LIBS)
examples/cwebp: EXTRA_LIBS += $(CWEBP_LIBS)
examples/dwebp: examples/libexample_util.a
examples/dwebp: imageio/libimagedec.a
examples/dwebp: src/demux/libwebpdemux.a
examples/dwebp: imageio/libimageenc.a
examples/dwebp: imageio/libimageio_util.a
examples/dwebp: src/libwebp.a
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/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/vwebp: examples/libexample_util.a src/demux/libwebpdemux.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/webpmux: examples/libexample_util.a imageio/libimageio_util.a
examples/webpmux: src/mux/libwebpmux.a src/libwebpdecoder.a
@ -439,7 +433,7 @@ examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a
examples/img2webp: imageio/libimagedec.a
examples/img2webp: src/demux/libwebpdemux.a
examples/img2webp: src/mux/libwebpmux.a src/libwebp.a
examples/img2webp: 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
@ -448,7 +442,7 @@ extras/get_disto: imageio/libimagedec.a
extras/get_disto: src/demux/libwebpdemux.a
extras/get_disto: imageio/libimageio_util.a
extras/get_disto: src/libwebp.a
extras/get_disto: override EXTRA_LIBS += $(CWEBP_LIBS)
extras/get_disto: EXTRA_LIBS += $(CWEBP_LIBS)
extras/webp_quality: extras/webp_quality.o
extras/webp_quality: imageio/libimageio_util.a
@ -459,7 +453,7 @@ 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)
extras/vwebp_sdl: EXTRA_LIBS += $(SDL_LIBS)
$(OUT_EXAMPLES) $(EXTRA_EXAMPLES) $(OTHER_EXAMPLES):
$(CC) -o $@ $^ $(LDFLAGS)

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH CWEBP 1 "November 19, 2020"
.TH CWEBP 1 "January 20, 2017"
.SH NAME
cwebp \- compress an image file to a WebP file
.SH SYNOPSIS
@ -13,7 +13,6 @@ command.
.PP
\fBcwebp\fP compresses an image using the WebP format.
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
The basic options are:
.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.
.TP
.BI \-near_lossless " int
Specify the level of near\-lossless image preprocessing. This option adjusts
pixel values to help compressibility, but has minimal impact on the visual
quality. It triggers lossless compression mode automatically. The range is 0
(maximum preprocessing) to 100 (no preprocessing, the default). The typical
value is around 60. Note that lossy with \fB\-q 100\fP can at times yield
better results.
Use near\-lossless image preprocessing. This option adjusts pixel values
to help compressibility, but has minimal impact on the visual quality.
It triggers lossless compression mode automatically.
Range is 0 (maximum preprocessing) to 100 (no preprocessing, the default).
.TP
.BI \-q " float
Specify the compression factor for RGB channels between 0 and 100. The default
@ -135,13 +132,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
specified, a default value of '6' passes will be used.
.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
Turns auto\-filter on. This algorithm will spend additional time optimizing
the filtering strength to reach a well\-balanced quality.

View File

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

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH GIF2WEBP 1 "May 1, 2020"
.TH GIF2WEBP 1 "January 25, 2018"
.SH NAME
gif2webp \- Convert a GIF image to WebP
.SH SYNOPSIS
@ -62,9 +62,9 @@ larger file size and lower compression quality.
.TP
.BI \-min_size
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
uses lossless compression by default, but can be combined with \-q, \-m,
\-lossy or \-mixed options.
picks the dispose method resulting in smallest output for each frame. It uses
lossless compression by default, but can be combined with \-q, \-m, \-lossy or
\-mixed options.
.TP
.BI \-kmin " int
.TP

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH IMG2WEBP 1 "May 1, 2020"
.TH IMG2WEBP 1 "April 3, 2018"
.SH NAME
img2webp \- create animated WebP file from a sequence of input images.
.SH SYNOPSIS
@ -16,8 +16,8 @@ command.
\fBimg2webp\fP compresses a sequence of images using the animated WebP format.
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.
the argument, the command line argument are actually tokenized from this file.
This allows for easy scripting or using large number of arguments.
.SH FILE-LEVEL OPTIONS
The file-level options are applied at the beginning of the compression process,
before the input frames are read.
@ -27,7 +27,7 @@ Specify the name of the output WebP file.
.TP
.BI \-min_size
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
\-mixed options.
.TP

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH VWEBP 1 "June 5, 2019"
.TH VWEBP 1 "July 20, 2018"
.SH NAME
vwebp \- decompress a WebP file and display it in a window
.SH SYNOPSIS

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH WEBPMUX 1 "December 12, 2020"
.TH WEBPMUX 1 "April 23, 2018"
.SH NAME
webpmux \- create animated WebP files from non\-animated WebP images, extract
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
@ -59,7 +59,7 @@ command.
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.
This allows for easy scripting or using large number of arguments.
.SH OPTIONS
.SS GET_OPTIONS (\-get):
.TP
@ -77,11 +77,6 @@ Get nth frame from an animated image. (n = 0 has a special meaning: last frame).
.SS SET_OPTIONS (\-set)
.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
Set ICC profile.
.P

View File

@ -36,7 +36,7 @@ libwebp_la_LIBADD += utils/libwebputils.la
# 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
# symbols in shared libraries to be resolved at library creation.
libwebp_la_LDFLAGS = -no-undefined -version-info 8:2:1
libwebp_la_LDFLAGS = -no-undefined -version-info 7:3:0
libwebpincludedir = $(includedir)/webp
pkgconfig_DATA = libwebp.pc
@ -48,7 +48,7 @@ if BUILD_LIBWEBPDECODER
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:2:1
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 3:3:0
pkgconfig_DATA += libwebpdecoder.pc
endif

View File

@ -183,7 +183,7 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
assert(dec != NULL && io != NULL);
if (row < 0 || num_rows <= 0 || row + num_rows > height) {
return NULL;
return NULL; // sanity check.
}
if (!dec->is_alpha_decoded_) {

View File

@ -102,7 +102,7 @@ static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
int stride;
uint64_t size;
if ((uint64_t)w * kModeBpp[mode] >= (1ull << 31)) {
if ((uint64_t)w * kModeBpp[mode] >= (1ull << 32)) {
return VP8_STATUS_INVALID_PARAM;
}
stride = w * kModeBpp[mode];
@ -117,6 +117,7 @@ static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
}
total_size = size + 2 * uv_size + a_size;
// Security/sanity checks
output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output));
if (output == NULL) {
return VP8_STATUS_OUT_OF_MEMORY;
@ -155,11 +156,11 @@ VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) {
}
if (WebPIsRGBMode(buffer->colorspace)) {
WebPRGBABuffer* const buf = &buffer->u.RGBA;
buf->rgba += (int64_t)(buffer->height - 1) * buf->stride;
buf->rgba += (buffer->height - 1) * buf->stride;
buf->stride = -buf->stride;
} else {
WebPYUVABuffer* const buf = &buffer->u.YUVA;
const int64_t H = buffer->height;
const int H = buffer->height;
buf->y += (H - 1) * buf->y_stride;
buf->y_stride = -buf->y_stride;
buf->u += ((H - 1) >> 1) * buf->u_stride;
@ -187,7 +188,8 @@ VP8StatusCode WebPAllocateDecBuffer(int width, int height,
const int ch = options->crop_height;
const int x = options->crop_left & ~1;
const int y = options->crop_top & ~1;
if (!WebPCheckCropDimensions(width, height, x, y, cw, ch)) {
if (x < 0 || y < 0 || cw <= 0 || ch <= 0 ||
x + cw > width || y + ch > height) {
return VP8_STATUS_INVALID_PARAM; // out of frame boundary.
}
width = cw;

View File

@ -705,7 +705,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
+ cache_size + alpha_size + WEBP_ALIGN_CST;
uint8_t* mem;
if (!CheckSizeOverflow(needed)) return 0; // check for overflow
if (needed != (size_t)needed) return 0; // check for overflow
if (needed > dec->mem_size_) {
WebPSafeFree(dec->mem_);
dec->mem_size_ = 0;
@ -732,7 +732,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
mem += f_info_size;
dec->thread_ctx_.id_ = 0;
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
// filtering strength from previous macroblock row, while the new ones
// are being decoded in parallel. We'll just swap the pointers.

View File

@ -166,11 +166,9 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
MemBuffer* const mem = &idec->mem_;
const int need_compressed_alpha = NeedCompressedAlpha(idec);
const uint8_t* const old_start =
(mem->buf_ == NULL) ? NULL : mem->buf_ + mem->start_;
const uint8_t* const old_start = mem->buf_ + mem->start_;
const uint8_t* const old_base =
need_compressed_alpha ? dec->alpha_data_ : old_start;
assert(mem->buf_ != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_APPEND);
if (data_size > MAX_CHUNK_PAYLOAD) {
// security safeguard: trying to allocate more than what the format
@ -186,7 +184,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
uint8_t* const new_buf =
(uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
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_);
mem->buf_ = new_buf;
mem->buf_size_ = (size_t)extra_size;
@ -194,7 +192,6 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
mem->end_ = current_size;
}
assert(mem->buf_ != NULL);
memcpy(mem->buf_ + mem->end_, data, data_size);
mem->end_ += data_size;
assert(mem->end_ <= mem->buf_size_);
@ -207,9 +204,7 @@ static int RemapMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) {
MemBuffer* const mem = &idec->mem_;
const uint8_t* const old_buf = mem->buf_;
const uint8_t* const old_start =
(old_buf == NULL) ? NULL : old_buf + mem->start_;
assert(old_buf != NULL || mem->start_ == 0);
const uint8_t* const old_start = old_buf + mem->start_;
assert(mem->mode_ == MEM_MODE_MAP);
if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!

View File

@ -25,16 +25,21 @@
static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
WebPDecBuffer* output = p->output;
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 u_dst = buf->u + (size_t)(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 y_dst = buf->y + io->mb_y * buf->y_stride;
uint8_t* const u_dst = buf->u + (io->mb_y >> 1) * buf->u_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_h = io->mb_h;
const int uv_w = (mb_w + 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);
WebPCopyPlane(io->u, io->uv_stride, u_dst, buf->u_stride, uv_w, uv_h);
WebPCopyPlane(io->v, io->uv_stride, v_dst, buf->v_stride, uv_w, uv_h);
int j;
for (j = 0; j < mb_h; ++j) {
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;
}
@ -42,7 +47,7 @@ static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
WebPDecBuffer* const output = p->output;
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,
io->u, io->v, io->uv_stride,
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) {
int num_lines_out = io->mb_h; // a priori guess
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];
const uint8_t* cur_y = io->y;
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 int mb_w = io->mb_w;
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;
(void)expected_num_lines_out;
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);
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
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 dst = base_rgba + (alpha_first ? 0 : 3);
const int has_alpha = WebPDispatchAlpha(alpha, io->width, mb_w,
@ -205,7 +210,7 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p,
const WEBP_CSP_MODE colorspace = p->output->colorspace;
const WebPRGBABuffer* const buf = &p->output->u.RGBA;
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;
#if (WEBP_SWAP_16BIT_CSP == 1)
uint8_t* alpha_dst = base_rgba;
@ -271,9 +276,9 @@ static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
int expected_num_lines_out) {
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) {
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);
assert(expected_num_lines_out == num_lines_out);
if (num_lines_out > 0) { // unmultiply the Y
@ -298,57 +303,46 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
const int uv_out_height = (out_height + 1) >> 1;
const int uv_in_width = (io->mb_w + 1) >> 1;
const int uv_in_height = (io->mb_h + 1) >> 1;
// scratch memory for luma rescaler
const size_t work_size = 2 * (size_t)out_width;
const size_t work_size = 2 * out_width; // scratch memory for luma rescaler
const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones
uint64_t total_size;
size_t rescaler_size;
size_t tmp_size, rescaler_size;
rescaler_t* work;
WebPRescaler* scalers;
const int num_rescalers = has_alpha ? 4 : 3;
total_size = ((uint64_t)work_size + 2 * uv_work_size) * sizeof(*work);
tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work);
if (has_alpha) {
total_size += (uint64_t)work_size * sizeof(*work);
tmp_size += work_size * sizeof(*work);
}
rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST;
total_size += rescaler_size;
if (!CheckSizeOverflow(total_size)) {
return 0;
}
p->memory = WebPSafeMalloc(1ULL, (size_t)total_size);
p->memory = WebPSafeMalloc(1ULL, tmp_size + rescaler_size);
if (p->memory == NULL) {
return 0; // memory error
}
work = (rescaler_t*)p->memory;
scalers = (WebPRescaler*)WEBP_ALIGN(
(const uint8_t*)work + total_size - rescaler_size);
scalers = (WebPRescaler*)WEBP_ALIGN((const uint8_t*)work + tmp_size);
p->scaler_y = &scalers[0];
p->scaler_u = &scalers[1];
p->scaler_v = &scalers[2];
p->scaler_a = has_alpha ? &scalers[3] : NULL;
if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
buf->y, out_width, out_height, buf->y_stride, 1,
work) ||
!WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
work + work_size) ||
!WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
work + work_size + uv_work_size)) {
return 0;
}
WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
buf->y, out_width, out_height, buf->y_stride, 1,
work);
WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
work + work_size);
WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
work + work_size + uv_work_size);
p->emit = EmitRescaledYUV;
if (has_alpha) {
if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
buf->a, out_width, out_height, buf->a_stride, 1,
work + work_size + 2 * uv_work_size)) {
return 0;
}
WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
buf->a, out_width, out_height, buf->a_stride, 1,
work + work_size + 2 * uv_work_size);
p->emit_alpha = EmitRescaledAlphaYUV;
WebPInitAlphaProcessing();
}
@ -362,7 +356,7 @@ static int ExportRGB(WebPDecParams* const p, int y_pos) {
const WebPYUV444Converter convert =
WebPYUV444Converters[p->output->colorspace];
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;
// 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.
@ -389,15 +383,15 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
while (j < mb_h) {
const int y_lines_in =
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;
if (WebPRescaleNeededLines(p->scaler_u, uv_mb_h - uv_j)) {
const int u_lines_in = WebPRescalerImport(
p->scaler_u, uv_mb_h - uv_j, io->u + (size_t)uv_j * io->uv_stride,
io->uv_stride);
const int v_lines_in = WebPRescalerImport(
p->scaler_v, uv_mb_h - uv_j, io->v + (size_t)uv_j * io->uv_stride,
io->uv_stride);
const int u_lines_in =
WebPRescalerImport(p->scaler_u, uv_mb_h - uv_j,
io->u + uv_j * io->uv_stride, io->uv_stride);
const int v_lines_in =
WebPRescalerImport(p->scaler_v, uv_mb_h - uv_j,
io->v + uv_j * io->uv_stride, io->uv_stride);
(void)v_lines_in; // remove a gcc warning
assert(u_lines_in == v_lines_in);
uv_j += u_lines_in;
@ -409,7 +403,7 @@ static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
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 int alpha_first =
(colorspace == MODE_ARGB || colorspace == MODE_Argb);
@ -437,7 +431,7 @@ static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos,
int max_lines_out) {
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)
uint8_t* alpha_dst = base_rgba;
#else
@ -476,7 +470,7 @@ static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
int lines_left = expected_num_out_lines;
const int y_end = p->last_y + lines_left;
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,
io->a + row_offset * io->width, io->width);
lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left);
@ -491,58 +485,51 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
const int out_height = io->scaled_height;
const int uv_in_width = (io->mb_w + 1) >> 1;
const int uv_in_height = (io->mb_h + 1) >> 1;
// scratch memory for one rescaler
const size_t work_size = 2 * (size_t)out_width;
const size_t work_size = 2 * out_width; // scratch memory for one rescaler
rescaler_t* work; // rescalers work area
uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
uint64_t tmp_size1, tmp_size2, total_size;
size_t rescaler_size;
size_t tmp_size1, tmp_size2, total_size, rescaler_size;
WebPRescaler* scalers;
const int num_rescalers = has_alpha ? 4 : 3;
tmp_size1 = (uint64_t)num_rescalers * work_size;
tmp_size2 = (uint64_t)num_rescalers * out_width;
tmp_size1 = 3 * work_size;
tmp_size2 = 3 * out_width;
if (has_alpha) {
tmp_size1 += work_size;
tmp_size2 += out_width;
}
total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp);
rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST;
total_size += rescaler_size;
if (!CheckSizeOverflow(total_size)) {
return 0;
}
p->memory = WebPSafeMalloc(1ULL, (size_t)total_size);
p->memory = WebPSafeMalloc(1ULL, total_size + rescaler_size);
if (p->memory == NULL) {
return 0; // memory error
}
work = (rescaler_t*)p->memory;
tmp = (uint8_t*)(work + tmp_size1);
scalers = (WebPRescaler*)WEBP_ALIGN(
(const uint8_t*)work + total_size - rescaler_size);
scalers = (WebPRescaler*)WEBP_ALIGN((const uint8_t*)work + total_size);
p->scaler_y = &scalers[0];
p->scaler_u = &scalers[1];
p->scaler_v = &scalers[2];
p->scaler_a = has_alpha ? &scalers[3] : NULL;
if (!WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
tmp + 0 * out_width, out_width, out_height, 0, 1,
work + 0 * work_size) ||
!WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
tmp + 1 * out_width, out_width, out_height, 0, 1,
work + 1 * work_size) ||
!WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
tmp + 2 * out_width, out_width, out_height, 0, 1,
work + 2 * work_size)) {
return 0;
}
WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
tmp + 0 * out_width, out_width, out_height, 0, 1,
work + 0 * work_size);
WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
tmp + 1 * out_width, out_width, out_height, 0, 1,
work + 1 * work_size);
WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
tmp + 2 * out_width, out_width, out_height, 0, 1,
work + 2 * work_size);
p->emit = EmitRescaledRGB;
WebPInitYUV444Converters();
if (has_alpha) {
if (!WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
tmp + 3 * out_width, out_width, out_height, 0, 1,
work + 3 * work_size)) {
return 0;
}
WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
tmp + 3 * out_width, out_width, out_height, 0, 1,
work + 3 * work_size);
p->emit_alpha = EmitRescaledAlphaRGB;
if (p->output->colorspace == MODE_RGBA_4444 ||
p->output->colorspace == MODE_rgbA_4444) {

View File

@ -61,17 +61,12 @@ static const uint16_t kAcTable[128] = {
void VP8ParseQuant(VP8Decoder* const dec) {
VP8BitReader* const br = &dec->br_;
const int base_q0 = VP8GetValue(br, 7, "global-header");
const int dqy1_dc = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 4, "global-header") : 0;
const int dqy2_dc = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 4, "global-header") : 0;
const int dqy2_ac = VP8Get(br, "global-header") ?
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 int base_q0 = VP8GetValue(br, 7);
const int dqy1_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dqy2_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dqy2_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dquv_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const int dquv_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0;
const VP8SegmentHeader* const hdr = &dec->segment_hdr_;
int i;

View File

@ -296,21 +296,20 @@ static void ParseIntraMode(VP8BitReader* const br,
// to decode more than 1 keyframe.
if (dec->segment_hdr_.update_map_) {
// Hardcoded tree parsing
block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0], "segments")
? VP8GetBit(br, dec->proba_.segments_[1], "segments")
: VP8GetBit(br, dec->proba_.segments_[2], "segments") + 2;
block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0])
? VP8GetBit(br, dec->proba_.segments_[1])
: 2 + VP8GetBit(br, dec->proba_.segments_[2]);
} else {
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_) {
// Hardcoded 16x16 intra-mode decision tree.
const int ymode =
VP8GetBit(br, 156, "pred-modes") ?
(VP8GetBit(br, 128, "pred-modes") ? TM_PRED : H_PRED) :
(VP8GetBit(br, 163, "pred-modes") ? V_PRED : DC_PRED);
VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED)
: (VP8GetBit(br, 163) ? V_PRED : DC_PRED);
block->imodes_[0] = ymode;
memset(top, ymode, 4 * sizeof(*top));
memset(left, ymode, 4 * sizeof(*left));
@ -324,25 +323,22 @@ static void ParseIntraMode(VP8BitReader* const br,
const uint8_t* const prob = kBModesProba[top[x]][ymode];
#if (USE_GENERIC_TREE == 1)
// Generic tree-parsing
int i = kYModesIntra4[VP8GetBit(br, prob[0], "pred-modes")];
int i = kYModesIntra4[VP8GetBit(br, prob[0])];
while (i > 0) {
i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i], "pred-modes")];
i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
}
ymode = -i;
#else
// Hardcoded tree parsing
ymode = !VP8GetBit(br, prob[0], "pred-modes") ? B_DC_PRED :
!VP8GetBit(br, prob[1], "pred-modes") ? B_TM_PRED :
!VP8GetBit(br, prob[2], "pred-modes") ? B_VE_PRED :
!VP8GetBit(br, prob[3], "pred-modes") ?
(!VP8GetBit(br, prob[4], "pred-modes") ? B_HE_PRED :
(!VP8GetBit(br, prob[5], "pred-modes") ? B_RD_PRED
: B_VR_PRED)) :
(!VP8GetBit(br, prob[6], "pred-modes") ? B_LD_PRED :
(!VP8GetBit(br, prob[7], "pred-modes") ? B_VL_PRED :
(!VP8GetBit(br, prob[8], "pred-modes") ? B_HD_PRED
: B_HU_PRED))
);
ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED :
!VP8GetBit(br, prob[1]) ? B_TM_PRED :
!VP8GetBit(br, prob[2]) ? B_VE_PRED :
!VP8GetBit(br, prob[3]) ?
(!VP8GetBit(br, prob[4]) ? B_HE_PRED :
(!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) :
(!VP8GetBit(br, prob[6]) ? B_LD_PRED :
(!VP8GetBit(br, prob[7]) ? B_VL_PRED :
(!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED)));
#endif // USE_GENERIC_TREE
top[x] = ymode;
}
@ -352,9 +348,9 @@ static void ParseIntraMode(VP8BitReader* const br,
}
}
// Hardcoded UVMode decision tree
block->uvmode_ = !VP8GetBit(br, 142, "pred-modes-uv") ? DC_PRED
: !VP8GetBit(br, 114, "pred-modes-uv") ? V_PRED
: VP8GetBit(br, 183, "pred-modes-uv") ? TM_PRED : H_PRED;
block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
: !VP8GetBit(br, 114) ? V_PRED
: VP8GetBit(br, 183) ? TM_PRED : H_PRED;
}
int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) {
@ -518,10 +514,8 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
for (b = 0; b < NUM_BANDS; ++b) {
for (c = 0; c < NUM_CTX; ++c) {
for (p = 0; p < NUM_PROBAS; ++p) {
const int v =
VP8GetBit(br, CoeffsUpdateProba[t][b][c][p], "global-header") ?
VP8GetValue(br, 8, "global-header") :
CoeffsProba0[t][b][c][p];
const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ?
VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p];
proba->bands_[t][b].probas_[c][p] = v;
}
}
@ -530,8 +524,9 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
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_) {
dec->skip_p_ = VP8GetValue(br, 8, "global-header");
dec->skip_p_ = VP8GetValue(br, 8);
}
}

View File

@ -161,26 +161,23 @@ static int ParseSegmentHeader(VP8BitReader* br,
VP8SegmentHeader* hdr, VP8Proba* proba) {
assert(br != NULL);
assert(hdr != NULL);
hdr->use_segment_ = VP8Get(br, "global-header");
hdr->use_segment_ = VP8Get(br);
if (hdr->use_segment_) {
hdr->update_map_ = VP8Get(br, "global-header");
if (VP8Get(br, "global-header")) { // update data
hdr->update_map_ = VP8Get(br);
if (VP8Get(br)) { // update data
int s;
hdr->absolute_delta_ = VP8Get(br, "global-header");
hdr->absolute_delta_ = VP8Get(br);
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
hdr->quantizer_[s] = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 7, "global-header") : 0;
hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;
}
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
hdr->filter_strength_[s] = VP8Get(br, "global-header") ?
VP8GetSignedValue(br, 6, "global-header") : 0;
hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0;
}
}
if (hdr->update_map_) {
int s;
for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
proba->segments_[s] = VP8Get(br, "global-header") ?
VP8GetValue(br, 8, "global-header") : 255u;
proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u;
}
}
} else {
@ -208,7 +205,7 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
size_t last_part;
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_;
if (size < 3 * last_part) {
// 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
static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) {
VP8FilterHeader* const hdr = &dec->filter_hdr_;
hdr->simple_ = VP8Get(br, "global-header");
hdr->level_ = VP8GetValue(br, 6, "global-header");
hdr->sharpness_ = VP8GetValue(br, 3, "global-header");
hdr->use_lf_delta_ = VP8Get(br, "global-header");
hdr->simple_ = VP8Get(br);
hdr->level_ = VP8GetValue(br, 6);
hdr->sharpness_ = VP8GetValue(br, 3);
hdr->use_lf_delta_ = VP8Get(br);
if (hdr->use_lf_delta_) {
if (VP8Get(br, "global-header")) { // update lf-delta?
if (VP8Get(br)) { // update lf-delta?
int i;
for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {
if (VP8Get(br, "global-header")) {
hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header");
if (VP8Get(br)) {
hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6);
}
}
for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
if (VP8Get(br, "global-header")) {
hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header");
if (VP8Get(br)) {
hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6);
}
}
}
@ -335,7 +332,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
io->scaled_width = io->width;
io->scaled_height = io->height;
io->mb_w = io->width; // for soundness
io->mb_w = io->width; // sanity check
io->mb_h = io->height; // ditto
VP8ResetProba(&dec->proba_);
@ -355,8 +352,8 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
buf_size -= frm_hdr->partition_length_;
if (frm_hdr->key_frame_) {
pic_hdr->colorspace_ = VP8Get(br, "global-header");
pic_hdr->clamp_type_ = VP8Get(br, "global-header");
pic_hdr->colorspace_ = VP8Get(br);
pic_hdr->clamp_type_ = VP8Get(br);
}
if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) {
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
@ -381,7 +378,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
"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);
@ -406,28 +403,28 @@ static const uint8_t kZigzag[16] = {
// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2
static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
int v;
if (!VP8GetBit(br, p[3], "coeffs")) {
if (!VP8GetBit(br, p[4], "coeffs")) {
if (!VP8GetBit(br, p[3])) {
if (!VP8GetBit(br, p[4])) {
v = 2;
} else {
v = 3 + VP8GetBit(br, p[5], "coeffs");
v = 3 + VP8GetBit(br, p[5]);
}
} else {
if (!VP8GetBit(br, p[6], "coeffs")) {
if (!VP8GetBit(br, p[7], "coeffs")) {
v = 5 + VP8GetBit(br, 159, "coeffs");
if (!VP8GetBit(br, p[6])) {
if (!VP8GetBit(br, p[7])) {
v = 5 + VP8GetBit(br, 159);
} else {
v = 7 + 2 * VP8GetBit(br, 165, "coeffs");
v += VP8GetBit(br, 145, "coeffs");
v = 7 + 2 * VP8GetBit(br, 165);
v += VP8GetBit(br, 145);
}
} else {
const uint8_t* tab;
const int bit1 = VP8GetBit(br, p[8], "coeffs");
const int bit0 = VP8GetBit(br, p[9 + bit1], "coeffs");
const int bit1 = VP8GetBit(br, p[8]);
const int bit0 = VP8GetBit(br, p[9 + bit1]);
const int cat = 2 * bit1 + bit0;
v = 0;
for (tab = kCat3456[cat]; *tab; ++tab) {
v += v + VP8GetBit(br, *tab, "coeffs");
v += v + VP8GetBit(br, *tab);
}
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) {
const uint8_t* p = prob[n]->probas_[ctx];
for (; n < 16; ++n) {
if (!VP8GetBit(br, p[0], "coeffs")) {
if (!VP8GetBit(br, p[0])) {
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];
if (n == 16) return 16;
}
{ // non zero coeff
const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];
int v;
if (!VP8GetBit(br, p[2], "coeffs")) {
if (!VP8GetBit(br, p[2])) {
v = 1;
p = p_ctx[1];
} else {
v = GetLargeValue(br, p);
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;
@ -471,34 +468,36 @@ static int GetCoeffsAlt(VP8BitReader* const br,
int ctx, const quant_t dq, int n, int16_t* out) {
const uint8_t* p = prob[n]->probas_[ctx];
for (; n < 16; ++n) {
if (!VP8GetBitAlt(br, p[0], "coeffs")) {
if (!VP8GetBitAlt(br, p[0])) {
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];
if (n == 16) return 16;
}
{ // non zero coeff
const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];
int v;
if (!VP8GetBitAlt(br, p[2], "coeffs")) {
if (!VP8GetBitAlt(br, p[2])) {
v = 1;
p = p_ctx[1];
} else {
v = GetLargeValue(br, p);
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;
}
WEBP_DSP_INIT_FUNC(InitGetCoeffs) {
if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
GetCoeffs = GetCoeffsAlt;
} else {
GetCoeffs = GetCoeffsFast;
static WEBP_TSAN_IGNORE_FUNCTION void InitGetCoeffs(void) {
if (GetCoeffs == NULL) {
if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
GetCoeffs = GetCoeffsAlt;
} else {
GetCoeffs = GetCoeffsFast;
}
}
}

View File

@ -31,7 +31,7 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 2
#define DEC_MIN_VERSION 0
#define DEC_REV_VERSION 1
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).

View File

@ -362,8 +362,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
// When reading htrees, some might be unused, as the format allows it.
// We will still read them but put them in this htree_group_bogus.
HTreeGroup htree_group_bogus;
HuffmanCode* huffman_tables = NULL;
HuffmanCode* huffman_table = NULL;
HuffmanCode* huffman_tables_bogus = NULL;
HuffmanCode* next = NULL;
int num_htree_groups = 1;
int num_htree_groups_max = 1;
int max_alphabet_size = 0;
@ -414,6 +418,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
if (*mapped_group == -1) *mapped_group = num_htree_groups++;
huffman_image[i] = *mapped_group;
}
huffman_tables_bogus = (HuffmanCode*)WebPSafeMalloc(
table_size, sizeof(*huffman_tables_bogus));
if (huffman_tables_bogus == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
goto Error;
}
} else {
num_htree_groups = num_htree_groups_max;
}
@ -443,71 +453,63 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
goto Error;
}
huffman_table = huffman_tables;
next = huffman_tables;
for (i = 0; i < num_htree_groups_max; ++i) {
// If the index "i" is unused in the Huffman image, just make sure the
// coefficients are valid but do not store them.
if (mapping != NULL && mapping[i] == -1) {
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
if (j == 0 && color_cache_bits > 0) {
alphabet_size += (1 << color_cache_bits);
}
// Passing in NULL so that nothing gets filled.
if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) {
goto Error;
}
// If the index "i" is unused in the Huffman image, read the coefficients
// but store them to a bogus htree_group.
const int is_bogus = (mapping != NULL && mapping[i] == -1);
HTreeGroup* const htree_group =
is_bogus ? &htree_group_bogus :
&htree_groups[(mapping == NULL) ? i : mapping[i]];
HuffmanCode** const htrees = htree_group->htrees;
HuffmanCode* huffman_tables_i = is_bogus ? huffman_tables_bogus : next;
int size;
int total_size = 0;
int is_trivial_literal = 1;
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
htrees[j] = huffman_tables_i;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += 1 << color_cache_bits;
}
} else {
HTreeGroup* const htree_group =
&htree_groups[(mapping == NULL) ? i : mapping[i]];
HuffmanCode** const htrees = htree_group->htrees;
int size;
int total_size = 0;
int is_trivial_literal = 1;
int max_bits = 0;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
htrees[j] = huffman_table;
if (j == 0 && color_cache_bits > 0) {
alphabet_size += (1 << color_cache_bits);
}
size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table);
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];
}
size =
ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables_i);
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
is_trivial_literal = (huffman_tables_i->bits == 0);
}
total_size += huffman_tables_i->bits;
huffman_tables_i += 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);
}
if (!is_bogus) next = huffman_tables_i;
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;
@ -519,6 +521,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
Error:
WebPSafeFree(code_lengths);
WebPSafeFree(huffman_tables_bogus);
WebPSafeFree(mapping);
if (!ok) {
WebPSafeFree(huffman_image);
@ -559,11 +562,8 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
memory += work_size * sizeof(*work);
scaled_data = (uint32_t*)memory;
if (!WebPRescalerInit(dec->rescaler, in_width, in_height,
(uint8_t*)scaled_data, out_width, out_height,
0, num_channels, work)) {
return 0;
}
WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,
out_width, out_height, 0, num_channels, work);
return 1;
}
#endif // WEBP_REDUCE_SIZE
@ -577,14 +577,13 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
int rgba_stride, uint8_t* const rgba) {
uint32_t* const src = (uint32_t*)rescaler->dst;
uint8_t* dst = rgba;
const int dst_width = rescaler->dst_width;
int num_lines_out = 0;
while (WebPRescalerHasPendingOutput(rescaler)) {
uint8_t* const dst = rgba + num_lines_out * rgba_stride;
WebPRescalerExportRow(rescaler);
WebPMultARGBRow(src, dst_width, 1);
VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
dst += rgba_stride;
++num_lines_out;
}
return num_lines_out;
@ -598,8 +597,8 @@ static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
int num_lines_in = 0;
int num_lines_out = 0;
while (num_lines_in < mb_h) {
uint8_t* const row_in = in + (uint64_t)num_lines_in * in_stride;
uint8_t* const row_out = out + (uint64_t)num_lines_out * out_stride;
uint8_t* const row_in = in + num_lines_in * in_stride;
uint8_t* const row_out = out + num_lines_out * out_stride;
const int lines_left = mb_h - num_lines_in;
const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
int lines_imported;
@ -758,11 +757,11 @@ static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
static void ApplyInverseTransforms(VP8LDecoder* const dec,
int start_row, int num_rows,
static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
const uint32_t* const rows) {
int n = dec->next_transform_;
const int cache_pixs = dec->width_ * num_rows;
const int start_row = dec->last_row_;
const int end_row = start_row + num_rows;
const uint32_t* rows_in = rows;
uint32_t* const rows_out = dec->argb_cache_;
@ -793,15 +792,15 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
VP8Io* const io = dec->io_;
uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
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)) {
// Nothing to output (this time).
} else {
const WebPDecBuffer* const output = dec->output_;
if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA
const WebPRGBABuffer* const buf = &output->u.RGBA;
uint8_t* const rgba =
buf->rgba + (int64_t)dec->last_out_row_ * buf->stride;
uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
const int num_rows_out =
#if !defined(WEBP_REDUCE_SIZE)
io->use_scaling ?
@ -952,6 +951,7 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
break;
default:
goto Copy;
break;
}
CopySmallPattern8b(src, dst, length, pattern);
return;
@ -1196,7 +1196,6 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
VP8LFillBitWindow(br);
dist_code = GetCopyDistance(dist_symbol, br);
dist = PlaneCodeToDistance(width, dist_code);
if (VP8LIsEndOfStream(br)) break;
if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
goto Error;
@ -1519,7 +1518,7 @@ static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
assert(dec->width_ <= final_width);
dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
if (dec->pixels_ == NULL) {
dec->argb_cache_ = NULL; // for soundness
dec->argb_cache_ = NULL; // for sanity check
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
return 0;
}
@ -1529,7 +1528,7 @@ static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;
dec->argb_cache_ = NULL; // for soundness
dec->argb_cache_ = NULL; // for sanity check
dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
if (dec->pixels_ == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
@ -1557,7 +1556,7 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
const int cache_pixs = width * num_rows_to_process;
uint8_t* const dst = output + width * cur_row;
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);
AlphaApplyFilter(alph_dec,
cur_row, cur_row + num_rows_to_process, dst, width);
@ -1671,6 +1670,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
VP8Io* io = NULL;
WebPDecParams* params = NULL;
// Sanity checks.
if (dec == NULL) return 0;
assert(dec->hdr_.huffman_tables_ != NULL);

View File

@ -37,7 +37,7 @@ struct VP8LTransform {
int bits_; // subsampling bits defining transform window.
int xsize_; // transform window X index.
int ysize_; // transform window Y index.
uint32_t* data_; // transform data.
uint32_t *data_; // transform data.
};
typedef struct {
@ -48,23 +48,23 @@ typedef struct {
int huffman_mask_;
int huffman_subsample_bits_;
int huffman_xsize_;
uint32_t* huffman_image_;
uint32_t *huffman_image_;
int num_htree_groups_;
HTreeGroup* htree_groups_;
HuffmanCode* huffman_tables_;
HTreeGroup *htree_groups_;
HuffmanCode *huffman_tables_;
} VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder;
struct VP8LDecoder {
VP8StatusCode status_;
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.
uint32_t* argb_cache_; // Scratch buffer for temporary BGRA storage.
uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
VP8LBitReader br_;
int incremental_; // if true, incremental decoding is expected
@ -86,8 +86,8 @@ struct VP8LDecoder {
// or'd bitset storing the transforms types.
uint32_t transforms_seen_;
uint8_t* rescaler_memory; // Working memory for rescaling work.
WebPRescaler* rescaler; // Common rescaler for all channels.
uint8_t *rescaler_memory; // Working memory for rescaling work.
WebPRescaler *rescaler; // Common rescaler for all channels.
};
//------------------------------------------------------------------------------

View File

@ -785,13 +785,6 @@ VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
//------------------------------------------------------------------------------
// Cropping and rescaling.
int WebPCheckCropDimensions(int image_width, int image_height,
int x, int y, int w, int h) {
return !(x < 0 || y < 0 || w <= 0 || h <= 0 ||
x >= image_width || w > image_width || w > image_width - x ||
y >= image_height || h > image_height || h > image_height - y);
}
int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
VP8Io* const io, WEBP_CSP_MODE src_colorspace) {
const int W = io->width;
@ -799,7 +792,7 @@ int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
int x = 0, y = 0, w = W, h = H;
// Cropping
io->use_cropping = (options != NULL) && options->use_cropping;
io->use_cropping = (options != NULL) && (options->use_cropping > 0);
if (io->use_cropping) {
w = options->crop_width;
h = options->crop_height;
@ -809,7 +802,7 @@ int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
x &= ~1;
y &= ~1;
}
if (!WebPCheckCropDimensions(W, H, x, y, w, h)) {
if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) {
return 0; // out of frame boundary error
}
}
@ -821,7 +814,7 @@ int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
io->mb_h = h;
// Scaling
io->use_scaling = (options != NULL) && options->use_scaling;
io->use_scaling = (options != NULL) && (options->use_scaling > 0);
if (io->use_scaling) {
int scaled_width = options->scaled_width;
int scaled_height = options->scaled_height;
@ -842,8 +835,8 @@ int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
if (io->use_scaling) {
// disable filter (only for large downscaling ratio).
io->bypass_filtering |= (io->scaled_width < W * 3 / 4) &&
(io->scaled_height < H * 3 / 4);
io->bypass_filtering = (io->scaled_width < W * 3 / 4) &&
(io->scaled_height < H * 3 / 4);
io->fancy_upsampling = 0;
}
return 1;

View File

@ -77,10 +77,6 @@ VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
//------------------------------------------------------------------------------
// Misc utils
// Returns true if crop dimensions are within image bounds.
int WebPCheckCropDimensions(int image_width, int image_height,
int x, int y, int w, int h);
// Initializes VP8Io with custom setup, io and teardown functions. The default
// hooks will use the supplied 'params' as io->opaque handle.
void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io);

View File

@ -13,6 +13,6 @@ noinst_HEADERS =
noinst_HEADERS += ../webp/format_constants.h
libwebpdemux_la_LIBADD = ../libwebp.la
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:8:0
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:5:0
libwebpdemuxincludedir = $(includedir)/webp
pkgconfig_DATA = libwebpdemux.pc

View File

@ -87,19 +87,11 @@ WebPAnimDecoder* WebPAnimDecoderNewInternal(
int abi_version) {
WebPAnimDecoderOptions options;
WebPAnimDecoder* dec = NULL;
WebPBitstreamFeatures features;
if (webp_data == NULL ||
WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_DEMUX_ABI_VERSION)) {
return NULL;
}
// Validate the bitstream before doing expensive allocations. The demuxer may
// be more tolerant than the decoder.
if (WebPGetFeatures(webp_data->bytes, webp_data->size, &features) !=
VP8_STATUS_OK) {
return NULL;
}
// Note: calloc() so that the pointer members are initialized to NULL.
dec = (WebPAnimDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
if (dec == NULL) goto Error;
@ -153,7 +145,7 @@ static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width,
uint32_t canvas_height) {
const uint64_t size =
(uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf);
if (!CheckSizeOverflow(size)) return 0;
if (size != (size_t)size) return 0;
memset(buf, 0, (size_t)size);
return 1;
}
@ -174,7 +166,7 @@ static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset,
static int CopyCanvas(const uint8_t* src, uint8_t* dst,
uint32_t width, uint32_t height) {
const uint64_t size = (uint64_t)width * height * NUM_CHANNELS;
if (!CheckSizeOverflow(size)) return 0;
if (size != (size_t)size) return 0;
assert(src != NULL && dst != NULL);
memcpy(dst, src, (size_t)size);
return 1;
@ -354,15 +346,12 @@ int WebPAnimDecoderGetNext(WebPAnimDecoder* dec,
{
const uint8_t* in = iter.fragment.bytes;
const size_t in_size = iter.fragment.size;
const uint32_t stride = width * NUM_CHANNELS; // at most 25 + 2 bits
const uint64_t out_offset = (uint64_t)iter.y_offset * stride +
(uint64_t)iter.x_offset * NUM_CHANNELS; // 53b
const uint64_t size = (uint64_t)iter.height * stride; // at most 25 + 27b
const size_t out_offset =
(iter.y_offset * width + iter.x_offset) * NUM_CHANNELS;
WebPDecoderConfig* const config = &dec->config_;
WebPRGBABuffer* const buf = &config->output.u.RGBA;
if ((size_t)size != size) goto Error;
buf->stride = (int)stride;
buf->size = (size_t)size;
buf->stride = NUM_CHANNELS * width;
buf->size = buf->stride * iter.height;
buf->rgba = dec->curr_frame_ + out_offset;
if (WebPDecode(in, in_size, config) != VP8_STATUS_OK) {

View File

@ -24,7 +24,7 @@
#include "src/webp/format_constants.h"
#define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 2
#define DMUX_MIN_VERSION 0
#define DMUX_REV_VERSION 1
typedef struct {
@ -221,16 +221,12 @@ static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
const size_t chunk_start_offset = mem->start_;
const uint32_t fourcc = ReadLE32(mem);
const uint32_t payload_size = ReadLE32(mem);
uint32_t payload_size_padded;
size_t payload_available;
size_t chunk_size;
const uint32_t payload_size_padded = payload_size + (payload_size & 1);
const size_t payload_available = (payload_size_padded > MemDataSize(mem))
? MemDataSize(mem) : payload_size_padded;
const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available;
if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
payload_size_padded = payload_size + (payload_size & 1);
payload_available = (payload_size_padded > MemDataSize(mem))
? MemDataSize(mem) : payload_size_padded;
chunk_size = CHUNK_HEADER_SIZE + payload_available;
if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR;
if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA;
@ -316,7 +312,6 @@ static ParseStatus ParseAnimationFrame(
int bits;
MemBuffer* const mem = &dmux->mem_;
Frame* frame;
size_t start_offset;
ParseStatus status =
NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame);
if (status != PARSE_OK) return status;
@ -337,11 +332,7 @@ static ParseStatus ParseAnimationFrame(
// Store a frame only if the animation flag is set there is some data for
// this frame is available.
start_offset = mem->start_;
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) {
added_frame = AddFrame(dmux, frame);
if (added_frame) {
@ -455,11 +446,9 @@ static ParseStatus ParseVP8XChunks(WebPDemuxer* const dmux) {
const size_t chunk_start_offset = mem->start_;
const uint32_t fourcc = ReadLE32(mem);
const uint32_t chunk_size = ReadLE32(mem);
uint32_t chunk_size_padded;
const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1);
if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
chunk_size_padded = chunk_size + (chunk_size & 1);
if (SizeIsInvalid(mem, chunk_size_padded)) return PARSE_ERROR;
switch (fourcc) {

View File

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

View File

@ -40,13 +40,11 @@ ENC_SOURCES =
ENC_SOURCES += cost.c
ENC_SOURCES += enc.c
ENC_SOURCES += lossless_enc.c
ENC_SOURCES += quant.h
ENC_SOURCES += ssim.c
libwebpdspdecode_sse41_la_SOURCES =
libwebpdspdecode_sse41_la_SOURCES += alpha_processing_sse41.c
libwebpdspdecode_sse41_la_SOURCES += dec_sse41.c
libwebpdspdecode_sse41_la_SOURCES += lossless_sse41.c
libwebpdspdecode_sse41_la_SOURCES += upsampling_sse41.c
libwebpdspdecode_sse41_la_SOURCES += yuv_sse41.c
libwebpdspdecode_sse41_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
@ -123,7 +121,6 @@ libwebpdsp_sse41_la_CFLAGS = $(AM_CFLAGS) $(SSE41_FLAGS)
libwebpdsp_sse41_la_LIBADD = libwebpdspdecode_sse41.la
libwebpdsp_neon_la_SOURCES =
libwebpdsp_neon_la_SOURCES += cost_neon.c
libwebpdsp_neon_la_SOURCES += enc_neon.c
libwebpdsp_neon_la_SOURCES += lossless_enc_neon.c
libwebpdsp_neon_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)

View File

@ -157,8 +157,7 @@ void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse) {
}
}
void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
const uint8_t* WEBP_RESTRICT const alpha,
void WebPMultRow_C(uint8_t* const ptr, const uint8_t* const alpha,
int width, int inverse) {
int x;
for (x = 0; x < width; ++x) {
@ -179,8 +178,7 @@ void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
#undef MFIX
void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr,
const uint8_t* WEBP_RESTRICT const alpha,
void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
int width, int inverse);
//------------------------------------------------------------------------------
@ -195,8 +193,8 @@ void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
}
}
void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride,
const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
void WebPMultRows(uint8_t* ptr, int stride,
const uint8_t* alpha, int alpha_stride,
int width, int num_rows, int inverse) {
int n;
for (n = 0; n < num_rows; ++n) {
@ -292,9 +290,9 @@ static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444,
}
#if !WEBP_NEON_OMIT_C_CODE
static int DispatchAlpha_C(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
static int DispatchAlpha_C(const uint8_t* alpha, int alpha_stride,
int width, int height,
uint8_t* WEBP_RESTRICT dst, int dst_stride) {
uint8_t* dst, int dst_stride) {
uint32_t alpha_mask = 0xff;
int i, j;
@ -311,10 +309,9 @@ static int DispatchAlpha_C(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
return (alpha_mask != 0xff);
}
static void DispatchAlphaToGreen_C(const uint8_t* WEBP_RESTRICT alpha,
int alpha_stride, int width, int height,
uint32_t* WEBP_RESTRICT dst,
int dst_stride) {
static void DispatchAlphaToGreen_C(const uint8_t* alpha, int alpha_stride,
int width, int height,
uint32_t* dst, int dst_stride) {
int i, j;
for (j = 0; j < height; ++j) {
for (i = 0; i < width; ++i) {
@ -325,9 +322,9 @@ static void DispatchAlphaToGreen_C(const uint8_t* WEBP_RESTRICT alpha,
}
}
static int ExtractAlpha_C(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
static int ExtractAlpha_C(const uint8_t* argb, int argb_stride,
int width, int height,
uint8_t* WEBP_RESTRICT alpha, int alpha_stride) {
uint8_t* alpha, int alpha_stride) {
uint8_t alpha_mask = 0xff;
int i, j;
@ -343,8 +340,7 @@ static int ExtractAlpha_C(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
return (alpha_mask == 0xff);
}
static void ExtractGreen_C(const uint32_t* WEBP_RESTRICT argb,
uint8_t* WEBP_RESTRICT alpha, int size) {
static void ExtractGreen_C(const uint32_t* argb, uint8_t* alpha, int size) {
int i;
for (i = 0; i < size; ++i) alpha[i] = argb[i] >> 8;
}
@ -363,11 +359,6 @@ static int HasAlpha32b_C(const uint8_t* src, int length) {
return 0;
}
static void AlphaReplace_C(uint32_t* src, int length, uint32_t color) {
int x;
for (x = 0; x < length; ++x) if ((src[x] >> 24) == 0) src[x] = color;
}
//------------------------------------------------------------------------------
// Simple channel manipulations.
@ -376,11 +367,8 @@ static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
}
#ifdef WORDS_BIGENDIAN
static void PackARGB_C(const uint8_t* WEBP_RESTRICT a,
const uint8_t* WEBP_RESTRICT r,
const uint8_t* WEBP_RESTRICT g,
const uint8_t* WEBP_RESTRICT b,
int len, uint32_t* WEBP_RESTRICT out) {
static void PackARGB_C(const uint8_t* a, const uint8_t* r, const uint8_t* g,
const uint8_t* b, int len, uint32_t* out) {
int i;
for (i = 0; i < len; ++i) {
out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
@ -388,10 +376,8 @@ static void PackARGB_C(const uint8_t* WEBP_RESTRICT a,
}
#endif
static void PackRGB_C(const uint8_t* WEBP_RESTRICT r,
const uint8_t* WEBP_RESTRICT g,
const uint8_t* WEBP_RESTRICT b,
int len, int step, uint32_t* WEBP_RESTRICT out) {
static void PackRGB_C(const uint8_t* r, const uint8_t* g, const uint8_t* b,
int len, int step, uint32_t* out) {
int i, offset = 0;
for (i = 0; i < len; ++i) {
out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]);
@ -401,26 +387,19 @@ static void PackRGB_C(const uint8_t* WEBP_RESTRICT r,
void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int);
void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int);
int (*WebPDispatchAlpha)(const uint8_t* WEBP_RESTRICT, int, int, int,
uint8_t* WEBP_RESTRICT, int);
void (*WebPDispatchAlphaToGreen)(const uint8_t* WEBP_RESTRICT, int, int, int,
uint32_t* WEBP_RESTRICT, int);
int (*WebPExtractAlpha)(const uint8_t* WEBP_RESTRICT, int, int, int,
uint8_t* WEBP_RESTRICT, int);
void (*WebPExtractGreen)(const uint32_t* WEBP_RESTRICT argb,
uint8_t* WEBP_RESTRICT alpha, int size);
int (*WebPDispatchAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
void (*WebPDispatchAlphaToGreen)(const uint8_t*, int, int, int, uint32_t*, int);
int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
void (*WebPExtractGreen)(const uint32_t* argb, uint8_t* alpha, int size);
#ifdef WORDS_BIGENDIAN
void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r, const uint8_t* g,
const uint8_t* b, int, uint32_t*);
#endif
void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r,
const uint8_t* WEBP_RESTRICT g,
const uint8_t* WEBP_RESTRICT b,
int len, int step, uint32_t* WEBP_RESTRICT out);
void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
int len, int step, uint32_t* out);
int (*WebPHasAlpha8b)(const uint8_t* src, int length);
int (*WebPHasAlpha32b)(const uint8_t* src, int length);
void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color);
//------------------------------------------------------------------------------
// Init function
@ -449,14 +428,13 @@ WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
WebPHasAlpha8b = HasAlpha8b_C;
WebPHasAlpha32b = HasAlpha32b_C;
WebPAlphaReplace = AlphaReplace_C;
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_HAVE_SSE2)
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
WebPInitAlphaProcessingSSE2();
#if defined(WEBP_HAVE_SSE41)
#if defined(WEBP_USE_SSE41)
if (VP8GetCPUInfo(kSSE4_1)) {
WebPInitAlphaProcessingSSE41();
}
@ -470,7 +448,7 @@ WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
#endif
}
#if defined(WEBP_HAVE_NEON)
#if defined(WEBP_USE_NEON)
if (WEBP_NEON_OMIT_C_CODE ||
(VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
WebPInitAlphaProcessingNEON();
@ -491,5 +469,4 @@ WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
assert(WebPPackRGB != NULL);
assert(WebPHasAlpha8b != NULL);
assert(WebPHasAlpha32b != NULL);
assert(WebPAlphaReplace != NULL);
}

View File

@ -80,9 +80,9 @@ static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first,
//------------------------------------------------------------------------------
static int DispatchAlpha_NEON(const uint8_t* WEBP_RESTRICT alpha,
int alpha_stride, int width, int height,
uint8_t* WEBP_RESTRICT dst, int dst_stride) {
static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride,
int width, int height,
uint8_t* dst, int dst_stride) {
uint32_t alpha_mask = 0xffu;
uint8x8_t mask8 = vdup_n_u8(0xff);
uint32_t tmp[2];
@ -113,10 +113,9 @@ static int DispatchAlpha_NEON(const uint8_t* WEBP_RESTRICT alpha,
return (alpha_mask != 0xffffffffu);
}
static void DispatchAlphaToGreen_NEON(const uint8_t* WEBP_RESTRICT alpha,
int alpha_stride, int width, int height,
uint32_t* WEBP_RESTRICT dst,
int dst_stride) {
static void DispatchAlphaToGreen_NEON(const uint8_t* alpha, int alpha_stride,
int width, int height,
uint32_t* dst, int dst_stride) {
int i, j;
uint8x8x4_t greens; // leave A/R/B channels zero'd.
greens.val[0] = vdup_n_u8(0);
@ -133,9 +132,9 @@ static void DispatchAlphaToGreen_NEON(const uint8_t* WEBP_RESTRICT alpha,
}
}
static int ExtractAlpha_NEON(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride,
int width, int height,
uint8_t* WEBP_RESTRICT alpha, int alpha_stride) {
uint8_t* alpha, int alpha_stride) {
uint32_t alpha_mask = 0xffu;
uint8x8_t mask8 = vdup_n_u8(0xff);
uint32_t tmp[2];
@ -164,8 +163,8 @@ static int ExtractAlpha_NEON(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
return (alpha_mask == 0xffffffffu);
}
static void ExtractGreen_NEON(const uint32_t* WEBP_RESTRICT argb,
uint8_t* WEBP_RESTRICT alpha, int size) {
static void ExtractGreen_NEON(const uint32_t* argb,
uint8_t* alpha, int size) {
int i;
for (i = 0; i + 16 <= size; i += 16) {
const uint8x16x4_t rgbX = vld4q_u8((const uint8_t*)(argb + i));

View File

@ -18,9 +18,9 @@
//------------------------------------------------------------------------------
static int DispatchAlpha_SSE2(const uint8_t* WEBP_RESTRICT alpha,
int alpha_stride, int width, int height,
uint8_t* WEBP_RESTRICT dst, int dst_stride) {
static int DispatchAlpha_SSE2(const uint8_t* alpha, int alpha_stride,
int width, int height,
uint8_t* dst, int dst_stride) {
// alpha_and stores an 'and' operation of all the alpha[] values. The final
// value is not 0xff if any of the alpha[] is not equal to 0xff.
uint32_t alpha_and = 0xff;
@ -72,10 +72,9 @@ static int DispatchAlpha_SSE2(const uint8_t* WEBP_RESTRICT alpha,
return (alpha_and != 0xff);
}
static void DispatchAlphaToGreen_SSE2(const uint8_t* WEBP_RESTRICT alpha,
int alpha_stride, int width, int height,
uint32_t* WEBP_RESTRICT dst,
int dst_stride) {
static void DispatchAlphaToGreen_SSE2(const uint8_t* alpha, int alpha_stride,
int width, int height,
uint32_t* dst, int dst_stride) {
int i, j;
const __m128i zero = _mm_setzero_si128();
const int limit = width & ~15;
@ -99,9 +98,9 @@ static void DispatchAlphaToGreen_SSE2(const uint8_t* WEBP_RESTRICT alpha,
}
}
static int ExtractAlpha_SSE2(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
static int ExtractAlpha_SSE2(const uint8_t* argb, int argb_stride,
int width, int height,
uint8_t* WEBP_RESTRICT alpha, int alpha_stride) {
uint8_t* alpha, int alpha_stride) {
// alpha_and stores an 'and' operation of all the alpha[] values. The final
// value is not 0xff if any of the alpha[] is not equal to 0xff.
uint32_t alpha_and = 0xff;
@ -215,7 +214,7 @@ static void ApplyAlphaMultiply_SSE2(uint8_t* rgba, int alpha_first,
// Alpha detection
static int HasAlpha8b_SSE2(const uint8_t* src, int length) {
const __m128i all_0xff = _mm_set1_epi8((char)0xff);
const __m128i all_0xff = _mm_set1_epi8(0xff);
int i = 0;
for (; i + 16 <= length; i += 16) {
const __m128i v = _mm_loadu_si128((const __m128i*)(src + i));
@ -229,7 +228,7 @@ static int HasAlpha8b_SSE2(const uint8_t* src, int length) {
static int HasAlpha32b_SSE2(const uint8_t* src, int length) {
const __m128i alpha_mask = _mm_set1_epi32(0xff);
const __m128i all_0xff = _mm_set1_epi8((char)0xff);
const __m128i all_0xff = _mm_set1_epi8(0xff);
int i = 0;
// We don't know if we can access the last 3 bytes after the last alpha
// value 'src[4 * length - 4]' (because we don't know if alpha is the first
@ -266,27 +265,6 @@ static int HasAlpha32b_SSE2(const uint8_t* src, int length) {
return 0;
}
static void AlphaReplace_SSE2(uint32_t* src, int length, uint32_t color) {
const __m128i m_color = _mm_set1_epi32(color);
const __m128i zero = _mm_setzero_si128();
int i = 0;
for (; i + 8 <= length; i += 8) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0));
const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 4));
const __m128i b0 = _mm_srai_epi32(a0, 24);
const __m128i b1 = _mm_srai_epi32(a1, 24);
const __m128i c0 = _mm_cmpeq_epi32(b0, zero);
const __m128i c1 = _mm_cmpeq_epi32(b1, zero);
const __m128i d0 = _mm_and_si128(c0, m_color);
const __m128i d1 = _mm_and_si128(c1, m_color);
const __m128i e0 = _mm_andnot_si128(c0, a0);
const __m128i e1 = _mm_andnot_si128(c1, a1);
_mm_storeu_si128((__m128i*)(src + i + 0), _mm_or_si128(d0, e0));
_mm_storeu_si128((__m128i*)(src + i + 4), _mm_or_si128(d1, e1));
}
for (; i < length; ++i) if ((src[i] >> 24) == 0) src[i] = color;
}
// -----------------------------------------------------------------------------
// Apply alpha value to rows
@ -318,8 +296,7 @@ static void MultARGBRow_SSE2(uint32_t* const ptr, int width, int inverse) {
if (width > 0) WebPMultARGBRow_C(ptr + x, width, inverse);
}
static void MultRow_SSE2(uint8_t* WEBP_RESTRICT const ptr,
const uint8_t* WEBP_RESTRICT const alpha,
static void MultRow_SSE2(uint8_t* const ptr, const uint8_t* const alpha,
int width, int inverse) {
int x = 0;
if (!inverse) {
@ -357,7 +334,6 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) {
WebPHasAlpha8b = HasAlpha8b_SSE2;
WebPHasAlpha32b = HasAlpha32b_SSE2;
WebPAlphaReplace = AlphaReplace_SSE2;
}
#else // !WEBP_USE_SSE2

View File

@ -19,9 +19,9 @@
//------------------------------------------------------------------------------
static int ExtractAlpha_SSE41(const uint8_t* WEBP_RESTRICT argb,
int argb_stride, int width, int height,
uint8_t* WEBP_RESTRICT alpha, int alpha_stride) {
static int ExtractAlpha_SSE41(const uint8_t* argb, int argb_stride,
int width, int height,
uint8_t* alpha, int alpha_stride) {
// alpha_and stores an 'and' operation of all the alpha[] values. The final
// value is not 0xff if any of the alpha[] is not equal to 0xff.
uint32_t alpha_and = 0xff;

View File

@ -377,7 +377,6 @@ VP8SetResidualCoeffsFunc VP8SetResidualCoeffs;
extern void VP8EncDspCostInitMIPS32(void);
extern void VP8EncDspCostInitMIPSdspR2(void);
extern void VP8EncDspCostInitSSE2(void);
extern void VP8EncDspCostInitNEON(void);
WEBP_DSP_INIT_FUNC(VP8EncDspCostInit) {
VP8GetResidualCost = GetResidualCost_C;
@ -395,15 +394,10 @@ WEBP_DSP_INIT_FUNC(VP8EncDspCostInit) {
VP8EncDspCostInitMIPSdspR2();
}
#endif
#if defined(WEBP_HAVE_SSE2)
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8EncDspCostInitSSE2();
}
#endif
#if defined(WEBP_HAVE_NEON)
if (VP8GetCPUInfo(kNEON)) {
VP8EncDspCostInitNEON();
}
#endif
}
}

View File

@ -1,122 +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.
// -----------------------------------------------------------------------------
//
// ARM NEON version of cost functions
#include "src/dsp/dsp.h"
#if defined(WEBP_USE_NEON)
#include "src/dsp/neon.h"
#include "src/enc/cost_enc.h"
static const uint8_t position[16] = { 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16 };
static void SetResidualCoeffs_NEON(const int16_t* const coeffs,
VP8Residual* const res) {
const int16x8_t minus_one = vdupq_n_s16(-1);
const int16x8_t coeffs_0 = vld1q_s16(coeffs);
const int16x8_t coeffs_1 = vld1q_s16(coeffs + 8);
const uint16x8_t eob_0 = vtstq_s16(coeffs_0, minus_one);
const uint16x8_t eob_1 = vtstq_s16(coeffs_1, minus_one);
const uint8x16_t eob = vcombine_u8(vqmovn_u16(eob_0), vqmovn_u16(eob_1));
const uint8x16_t masked = vandq_u8(eob, vld1q_u8(position));
#ifdef __aarch64__
res->last = vmaxvq_u8(masked) - 1;
#else
const uint8x8_t eob_8x8 = vmax_u8(vget_low_u8(masked), vget_high_u8(masked));
const uint16x8_t eob_16x8 = vmovl_u8(eob_8x8);
const uint16x4_t eob_16x4 =
vmax_u16(vget_low_u16(eob_16x8), vget_high_u16(eob_16x8));
const uint32x4_t eob_32x4 = vmovl_u16(eob_16x4);
uint32x2_t eob_32x2 =
vmax_u32(vget_low_u32(eob_32x4), vget_high_u32(eob_32x4));
eob_32x2 = vpmax_u32(eob_32x2, eob_32x2);
vst1_lane_s32(&res->last, vreinterpret_s32_u32(eob_32x2), 0);
--res->last;
#endif // __aarch64__
res->coeffs = coeffs;
}
static int GetResidualCost_NEON(int ctx0, const VP8Residual* const res) {
uint8_t levels[16], ctxs[16];
uint16_t abs_levels[16];
int n = res->first;
// should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1
const int p0 = res->prob[n][ctx0][0];
CostArrayPtr const costs = res->costs;
const uint16_t* t = costs[n][ctx0];
// bit_cost(1, p0) is already incorporated in t[] tables, but only if ctx != 0
// (as required by the syntax). For ctx0 == 0, we need to add it here or it'll
// be missing during the loop.
int cost = (ctx0 == 0) ? VP8BitCost(1, p0) : 0;
if (res->last < 0) {
return VP8BitCost(0, p0);
}
{ // precompute clamped levels and contexts, packed to 8b.
const uint8x16_t kCst2 = vdupq_n_u8(2);
const uint8x16_t kCst67 = vdupq_n_u8(MAX_VARIABLE_LEVEL);
const int16x8_t c0 = vld1q_s16(res->coeffs);
const int16x8_t c1 = vld1q_s16(res->coeffs + 8);
const uint16x8_t E0 = vreinterpretq_u16_s16(vabsq_s16(c0));
const uint16x8_t E1 = vreinterpretq_u16_s16(vabsq_s16(c1));
const uint8x16_t F = vcombine_u8(vqmovn_u16(E0), vqmovn_u16(E1));
const uint8x16_t G = vminq_u8(F, kCst2); // context = 0,1,2
const uint8x16_t H = vminq_u8(F, kCst67); // clamp_level in [0..67]
vst1q_u8(ctxs, G);
vst1q_u8(levels, H);
vst1q_u16(abs_levels, E0);
vst1q_u16(abs_levels + 8, E1);
}
for (; n < res->last; ++n) {
const int ctx = ctxs[n];
const int level = levels[n];
const int flevel = abs_levels[n]; // full level
cost += VP8LevelFixedCosts[flevel] + t[level]; // simplified VP8LevelCost()
t = costs[n + 1][ctx];
}
// Last coefficient is always non-zero
{
const int level = levels[n];
const int flevel = abs_levels[n];
assert(flevel != 0);
cost += VP8LevelFixedCosts[flevel] + t[level];
if (n < 15) {
const int b = VP8EncBands[n + 1];
const int ctx = ctxs[n];
const int last_p0 = res->prob[b][ctx][0];
cost += VP8BitCost(0, last_p0);
}
}
return cost;
}
//------------------------------------------------------------------------------
// Entry point
extern void VP8EncDspCostInitNEON(void);
WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitNEON(void) {
VP8SetResidualCoeffs = SetResidualCoeffs_NEON;
VP8GetResidualCost = GetResidualCost_NEON;
}
#else // !WEBP_USE_NEON
WEBP_DSP_INIT_STUB(VP8EncDspCostInitNEON)
#endif // WEBP_USE_NEON

View File

@ -55,18 +55,12 @@ static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
: "a"(info_type), "c"(0));
}
#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1
#elif (defined(_M_X64) || defined(_M_IX86)) && \
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1
#include <intrin.h>
#define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0
#define WEBP_HAVE_MSC_CPUID
#elif _MSC_VER > 1310
#include <intrin.h>
#elif defined(WEBP_MSC_SSE2)
#define GetCPUInfo __cpuid
#define WEBP_HAVE_MSC_CPUID
#endif
#endif
// NaCl has no support for xgetbv or the raw opcode.
@ -100,7 +94,7 @@ static WEBP_INLINE uint64_t xgetbv(void) {
#define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains.
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_HAVE_MSC_CPUID)
#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2)
// helper function for run-time detection of slow SSSE3 platforms
static int CheckSlowModel(int info) {
@ -179,40 +173,15 @@ static int AndroidCPUInfo(CPUFeature feature) {
const AndroidCpuFamily cpu_family = android_getCpuFamily();
const uint64_t cpu_features = android_getCpuFeatures();
if (feature == kNEON) {
return cpu_family == ANDROID_CPU_FAMILY_ARM &&
(cpu_features & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
return (cpu_family == ANDROID_CPU_FAMILY_ARM &&
0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON));
}
return 0;
}
VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo;
#elif defined(EMSCRIPTEN) // also needs to be before generic NEON test
// Use compile flags as an indicator of SIMD support instead of a runtime check.
static int wasmCPUInfo(CPUFeature feature) {
switch (feature) {
#ifdef WEBP_HAVE_SSE2
case kSSE2:
return 1;
#endif
#ifdef WEBP_HAVE_SSE41
case kSSE3:
case kSlowSSSE3:
case kSSE4_1:
return 1;
#endif
#ifdef WEBP_HAVE_NEON
case kNEON:
return 1;
#endif
default:
break;
}
return 0;
}
VP8CPUInfo VP8GetCPUInfo = wasmCPUInfo;
#elif defined(WEBP_HAVE_NEON)
// In most cases this function doesn't check for NEON support (it's assumed by
// the configuration), but enables turning off NEON at runtime, for testing
// purposes, by setting VP8DecGetCPUInfo = NULL.
#elif defined(WEBP_USE_NEON)
// define a dummy function to enable turning off NEON at runtime by setting
// VP8DecGetCPUInfo = NULL
static int armCPUInfo(CPUFeature feature) {
if (feature != kNEON) return 0;
#if defined(__linux__) && defined(WEBP_HAVE_NEON_RTCD)

View File

@ -807,10 +807,10 @@ WEBP_DSP_INIT_FUNC(VP8DspInit) {
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_HAVE_SSE2)
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8DspInitSSE2();
#if defined(WEBP_HAVE_SSE41)
#if defined(WEBP_USE_SSE41)
if (VP8GetCPUInfo(kSSE4_1)) {
VP8DspInitSSE41();
}
@ -834,7 +834,7 @@ WEBP_DSP_INIT_FUNC(VP8DspInit) {
#endif
}
#if defined(WEBP_HAVE_NEON)
#if defined(WEBP_USE_NEON)
if (WEBP_NEON_OMIT_C_CODE ||
(VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
VP8DspInitNEON();

View File

@ -1283,12 +1283,12 @@ static void DC4_NEON(uint8_t* dst) { // DC
const uint8x8_t A = vld1_u8(dst - BPS); // top row
const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
const uint16x4_t p1 = vpadd_u16(p0, p0);
const uint8x8_t L0 = vld1_u8(dst + 0 * BPS - 1);
const uint8x8_t L1 = vld1_u8(dst + 1 * BPS - 1);
const uint8x8_t L2 = vld1_u8(dst + 2 * BPS - 1);
const uint8x8_t L3 = vld1_u8(dst + 3 * BPS - 1);
const uint16x8_t s0 = vaddl_u8(L0, L1);
const uint16x8_t s1 = vaddl_u8(L2, L3);
const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1));
const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1));
const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1));
const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1));
const uint16x8_t s0 = vaddq_u16(L0, L1);
const uint16x8_t s1 = vaddq_u16(L2, L3);
const uint16x8_t s01 = vaddq_u16(s0, s1);
const uint16x8_t sum = vaddq_u16(s01, vcombine_u16(p1, p1));
const uint8x8_t dc0 = vrshrn_n_u16(sum, 3); // (sum + 4) >> 3
@ -1361,8 +1361,7 @@ static void RD4_NEON(uint8_t* dst) { // Down-right
const uint32_t J = dst[-1 + 1 * BPS];
const uint32_t K = dst[-1 + 2 * BPS];
const uint32_t L = dst[-1 + 3 * BPS];
const uint64x1_t LKJI____ =
vcreate_u64((uint64_t)L | (K << 8) | (J << 16) | (I << 24));
const uint64x1_t LKJI____ = vcreate_u64(L | (K << 8) | (J << 16) | (I << 24));
const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC);
const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8));
const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16));
@ -1428,30 +1427,25 @@ static WEBP_INLINE void DC8_NEON(uint8_t* dst, int do_top, int do_left) {
if (do_top) {
const uint8x8_t A = vld1_u8(dst - BPS); // top row
#if defined(__aarch64__)
const uint16_t p2 = vaddlv_u8(A);
sum_top = vdupq_n_u16(p2);
#else
const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
const uint16x4_t p1 = vpadd_u16(p0, p0);
const uint16x4_t p2 = vpadd_u16(p1, p1);
sum_top = vcombine_u16(p2, p2);
#endif
}
if (do_left) {
const uint8x8_t L0 = vld1_u8(dst + 0 * BPS - 1);
const uint8x8_t L1 = vld1_u8(dst + 1 * BPS - 1);
const uint8x8_t L2 = vld1_u8(dst + 2 * BPS - 1);
const uint8x8_t L3 = vld1_u8(dst + 3 * BPS - 1);
const uint8x8_t L4 = vld1_u8(dst + 4 * BPS - 1);
const uint8x8_t L5 = vld1_u8(dst + 5 * BPS - 1);
const uint8x8_t L6 = vld1_u8(dst + 6 * BPS - 1);
const uint8x8_t L7 = vld1_u8(dst + 7 * BPS - 1);
const uint16x8_t s0 = vaddl_u8(L0, L1);
const uint16x8_t s1 = vaddl_u8(L2, L3);
const uint16x8_t s2 = vaddl_u8(L4, L5);
const uint16x8_t s3 = vaddl_u8(L6, L7);
const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + 0 * BPS - 1));
const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + 1 * BPS - 1));
const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + 2 * BPS - 1));
const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + 3 * BPS - 1));
const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + 4 * BPS - 1));
const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + 5 * BPS - 1));
const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + 6 * BPS - 1));
const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + 7 * BPS - 1));
const uint16x8_t s0 = vaddq_u16(L0, L1);
const uint16x8_t s1 = vaddq_u16(L2, L3);
const uint16x8_t s2 = vaddq_u16(L4, L5);
const uint16x8_t s3 = vaddq_u16(L6, L7);
const uint16x8_t s01 = vaddq_u16(s0, s1);
const uint16x8_t s23 = vaddq_u16(s2, s3);
sum_left = vaddq_u16(s01, s23);
@ -1511,34 +1505,29 @@ static WEBP_INLINE void DC16_NEON(uint8_t* dst, int do_top, int do_left) {
if (do_top) {
const uint8x16_t A = vld1q_u8(dst - BPS); // top row
#if defined(__aarch64__)
const uint16_t p3 = vaddlvq_u8(A);
sum_top = vdupq_n_u16(p3);
#else
const uint16x8_t p0 = vpaddlq_u8(A); // cascading summation of the top
const uint16x4_t p1 = vadd_u16(vget_low_u16(p0), vget_high_u16(p0));
const uint16x4_t p2 = vpadd_u16(p1, p1);
const uint16x4_t p3 = vpadd_u16(p2, p2);
sum_top = vcombine_u16(p3, p3);
#endif
}
if (do_left) {
int i;
sum_left = vdupq_n_u16(0);
for (i = 0; i < 16; i += 8) {
const uint8x8_t L0 = vld1_u8(dst + (i + 0) * BPS - 1);
const uint8x8_t L1 = vld1_u8(dst + (i + 1) * BPS - 1);
const uint8x8_t L2 = vld1_u8(dst + (i + 2) * BPS - 1);
const uint8x8_t L3 = vld1_u8(dst + (i + 3) * BPS - 1);
const uint8x8_t L4 = vld1_u8(dst + (i + 4) * BPS - 1);
const uint8x8_t L5 = vld1_u8(dst + (i + 5) * BPS - 1);
const uint8x8_t L6 = vld1_u8(dst + (i + 6) * BPS - 1);
const uint8x8_t L7 = vld1_u8(dst + (i + 7) * BPS - 1);
const uint16x8_t s0 = vaddl_u8(L0, L1);
const uint16x8_t s1 = vaddl_u8(L2, L3);
const uint16x8_t s2 = vaddl_u8(L4, L5);
const uint16x8_t s3 = vaddl_u8(L6, L7);
const uint16x8_t L0 = vmovl_u8(vld1_u8(dst + (i + 0) * BPS - 1));
const uint16x8_t L1 = vmovl_u8(vld1_u8(dst + (i + 1) * BPS - 1));
const uint16x8_t L2 = vmovl_u8(vld1_u8(dst + (i + 2) * BPS - 1));
const uint16x8_t L3 = vmovl_u8(vld1_u8(dst + (i + 3) * BPS - 1));
const uint16x8_t L4 = vmovl_u8(vld1_u8(dst + (i + 4) * BPS - 1));
const uint16x8_t L5 = vmovl_u8(vld1_u8(dst + (i + 5) * BPS - 1));
const uint16x8_t L6 = vmovl_u8(vld1_u8(dst + (i + 6) * BPS - 1));
const uint16x8_t L7 = vmovl_u8(vld1_u8(dst + (i + 7) * BPS - 1));
const uint16x8_t s0 = vaddq_u16(L0, L1);
const uint16x8_t s1 = vaddq_u16(L2, L3);
const uint16x8_t s2 = vaddq_u16(L4, L5);
const uint16x8_t s3 = vaddq_u16(L6, L7);
const uint16x8_t s01 = vaddq_u16(s0, s1);
const uint16x8_t s23 = vaddq_u16(s2, s3);
const uint16x8_t sum = vaddq_u16(s01, s23);

View File

@ -326,7 +326,7 @@ static WEBP_INLINE void Update2Pixels_SSE2(__m128i* const pi, __m128i* const qi,
const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7);
const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7);
const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi);
const __m128i sign_bit = _mm_set1_epi8((char)0x80);
const __m128i sign_bit = _mm_set1_epi8(0x80);
*pi = _mm_adds_epi8(*pi, delta);
*qi = _mm_subs_epi8(*qi, delta);
FLIP_SIGN_BIT2(*pi, *qi);
@ -338,9 +338,9 @@ static WEBP_INLINE void NeedsFilter_SSE2(const __m128i* const p1,
const __m128i* const q0,
const __m128i* const q1,
int thresh, __m128i* const mask) {
const __m128i m_thresh = _mm_set1_epi8((char)thresh);
const __m128i m_thresh = _mm_set1_epi8(thresh);
const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1)
const __m128i kFE = _mm_set1_epi8((char)0xFE);
const __m128i kFE = _mm_set1_epi8(0xFE);
const __m128i t2 = _mm_and_si128(t1, kFE); // set lsb of each byte to zero
const __m128i t3 = _mm_srli_epi16(t2, 1); // abs(p1 - q1) / 2
@ -360,7 +360,7 @@ static WEBP_INLINE void DoFilter2_SSE2(__m128i* const p1, __m128i* const p0,
__m128i* const q0, __m128i* const q1,
int thresh) {
__m128i a, mask;
const __m128i sign_bit = _mm_set1_epi8((char)0x80);
const __m128i sign_bit = _mm_set1_epi8(0x80);
// convert p1/q1 to int8_t (for GetBaseDelta_SSE2)
const __m128i p1s = _mm_xor_si128(*p1, sign_bit);
const __m128i q1s = _mm_xor_si128(*q1, sign_bit);
@ -380,7 +380,7 @@ static WEBP_INLINE void DoFilter4_SSE2(__m128i* const p1, __m128i* const p0,
const __m128i* const mask,
int hev_thresh) {
const __m128i zero = _mm_setzero_si128();
const __m128i sign_bit = _mm_set1_epi8((char)0x80);
const __m128i sign_bit = _mm_set1_epi8(0x80);
const __m128i k64 = _mm_set1_epi8(64);
const __m128i k3 = _mm_set1_epi8(3);
const __m128i k4 = _mm_set1_epi8(4);
@ -427,7 +427,7 @@ static WEBP_INLINE void DoFilter6_SSE2(__m128i* const p2, __m128i* const p1,
const __m128i* const mask,
int hev_thresh) {
const __m128i zero = _mm_setzero_si128();
const __m128i sign_bit = _mm_set1_epi8((char)0x80);
const __m128i sign_bit = _mm_set1_epi8(0x80);
__m128i a, not_hev;
// compute hev mask
@ -941,7 +941,7 @@ static void VR4_SSE2(uint8_t* dst) { // Vertical-Right
const __m128i ABCD0 = _mm_srli_si128(XABCD, 1);
const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0);
const __m128i _XABCD = _mm_slli_si128(XABCD, 1);
const __m128i IXABCD = _mm_insert_epi16(_XABCD, (short)(I | (X << 8)), 0);
const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0);
const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0);
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);

View File

@ -26,23 +26,6 @@ extern "C" {
#define BPS 32 // this is the common stride for enc/dec
//------------------------------------------------------------------------------
// WEBP_RESTRICT
// Declares a pointer with the restrict type qualifier if available.
// This allows code to hint to the compiler that only this pointer references a
// particular object or memory region within the scope of the block in which it
// is declared. This may allow for improved optimizations due to the lack of
// pointer aliasing. See also:
// https://en.cppreference.com/w/c/language/restrict
#if defined(__GNUC__)
#define WEBP_RESTRICT __restrict__
#elif defined(_MSC_VER)
#define WEBP_RESTRICT __restrict
#else
#define WEBP_RESTRICT
#endif
//------------------------------------------------------------------------------
// CPU detection
@ -68,7 +51,9 @@ extern "C" {
# define __has_builtin(x) 0
#endif
#if !defined(HAVE_CONFIG_H)
// for now, none of the optimizations below are available in emscripten
#if !defined(EMSCRIPTEN)
#if defined(_MSC_VER) && _MSC_VER > 1310 && \
(defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_SSE2 // Visual C++ SSE2 targets
@ -78,37 +63,23 @@ extern "C" {
(defined(_M_X64) || defined(_M_IX86))
#define WEBP_MSC_SSE41 // Visual C++ SSE4.1 targets
#endif
#endif
// WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp
// files without intrinsics, allowing the corresponding Init() to be called.
// Files containing intrinsics will need to be built targeting the instruction
// set so should succeed on one of the earlier tests.
#if (defined(__SSE2__) || defined(WEBP_MSC_SSE2)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE2))
#if defined(__SSE2__) || defined(WEBP_MSC_SSE2) || defined(WEBP_HAVE_SSE2)
#define WEBP_USE_SSE2
#endif
#if defined(WEBP_USE_SSE2) && !defined(WEBP_HAVE_SSE2)
#define WEBP_HAVE_SSE2
#endif
#if (defined(__SSE4_1__) || defined(WEBP_MSC_SSE41)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE41))
#if defined(__SSE4_1__) || defined(WEBP_MSC_SSE41) || defined(WEBP_HAVE_SSE41)
#define WEBP_USE_SSE41
#endif
#if defined(WEBP_USE_SSE41) && !defined(WEBP_HAVE_SSE41)
#define WEBP_HAVE_SSE41
#endif
#undef WEBP_MSC_SSE41
#undef WEBP_MSC_SSE2
// The intrinsics currently cause compiler errors with arm-nacl-gcc and the
// inline assembly would need to be modified for use with Native Client.
#if ((defined(__ARM_NEON__) || defined(__aarch64__)) && \
(!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_NEON))) && \
#if (defined(__ARM_NEON__) || \
defined(__aarch64__) || defined(WEBP_HAVE_NEON)) && \
!defined(__native_client__)
#define WEBP_USE_NEON
#endif
@ -124,10 +95,6 @@ extern "C" {
#define WEBP_USE_INTRINSICS
#endif
#if defined(WEBP_USE_NEON) && !defined(WEBP_HAVE_NEON)
#define WEBP_HAVE_NEON
#endif
#if defined(__mips__) && !defined(__mips64) && \
defined(__mips_isa_rev) && (__mips_isa_rev >= 1) && (__mips_isa_rev < 6)
#define WEBP_USE_MIPS32
@ -143,11 +110,13 @@ extern "C" {
#define WEBP_USE_MSA
#endif
#endif /* EMSCRIPTEN */
#ifndef WEBP_DSP_OMIT_C_CODE
#define WEBP_DSP_OMIT_C_CODE 1
#endif
#if defined(WEBP_USE_NEON) && WEBP_DSP_OMIT_C_CODE
#if (defined(__aarch64__) || defined(__ARM_NEON__)) && WEBP_DSP_OMIT_C_CODE
#define WEBP_NEON_OMIT_C_CODE 1
#else
#define WEBP_NEON_OMIT_C_CODE 0
@ -224,12 +193,6 @@ extern "C" {
#endif
#endif
// If 'ptr' is NULL, returns NULL. Otherwise returns 'ptr + off'.
// Prevents undefined behavior sanitizer nullptr-with-nonzero-offset warning.
#if !defined(WEBP_OFFSET_PTR)
#define WEBP_OFFSET_PTR(ptr, off) (((ptr) == NULL) ? NULL : ((ptr) + (off)))
#endif
// Regularize the definition of WEBP_SWAP_16BIT_CSP (backward compatibility)
#if !defined(WEBP_SWAP_16BIT_CSP)
#define WEBP_SWAP_16BIT_CSP 0
@ -283,9 +246,9 @@ extern VP8Fdct VP8FTransform2; // performs two transforms at a time
extern VP8WHT VP8FTransformWHT;
// Predictions
// *dst is the destination block. *top and *left can be NULL.
typedef void (*VP8IntraPreds)(uint8_t* dst, const uint8_t* left,
typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left,
const uint8_t* top);
typedef void (*VP8Intra4Preds)(uint8_t* dst, const uint8_t* top);
typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top);
extern VP8Intra4Preds VP8EncPredLuma4;
extern VP8IntraPreds VP8EncPredLuma16;
extern VP8IntraPreds VP8EncPredChroma8;
@ -609,29 +572,26 @@ extern void (*WebPApplyAlphaMultiply4444)(
// Dispatch the values from alpha[] plane to the ARGB destination 'dst'.
// Returns true if alpha[] plane has non-trivial values different from 0xff.
extern int (*WebPDispatchAlpha)(const uint8_t* WEBP_RESTRICT alpha,
int alpha_stride, int width, int height,
uint8_t* WEBP_RESTRICT dst, int dst_stride);
extern int (*WebPDispatchAlpha)(const uint8_t* alpha, int alpha_stride,
int width, int height,
uint8_t* dst, int dst_stride);
// Transfer packed 8b alpha[] values to green channel in dst[], zero'ing the
// A/R/B values. 'dst_stride' is the stride for dst[] in uint32_t units.
extern void (*WebPDispatchAlphaToGreen)(const uint8_t* WEBP_RESTRICT alpha,
int alpha_stride, int width, int height,
uint32_t* WEBP_RESTRICT dst,
int dst_stride);
extern void (*WebPDispatchAlphaToGreen)(const uint8_t* alpha, int alpha_stride,
int width, int height,
uint32_t* dst, int dst_stride);
// Extract the alpha values from 32b values in argb[] and pack them into alpha[]
// (this is the opposite of WebPDispatchAlpha).
// Returns true if there's only trivial 0xff alpha values.
extern int (*WebPExtractAlpha)(const uint8_t* WEBP_RESTRICT argb,
int argb_stride, int width, int height,
uint8_t* WEBP_RESTRICT alpha,
int alpha_stride);
extern int (*WebPExtractAlpha)(const uint8_t* argb, int argb_stride,
int width, int height,
uint8_t* alpha, int alpha_stride);
// Extract the green values from 32b values in argb[] and pack them into alpha[]
// (this is the opposite of WebPDispatchAlphaToGreen).
extern void (*WebPExtractGreen)(const uint32_t* WEBP_RESTRICT argb,
uint8_t* WEBP_RESTRICT alpha, int size);
extern void (*WebPExtractGreen)(const uint32_t* argb, uint8_t* alpha, int size);
// Pre-Multiply operation transforms x into x * A / 255 (where x=Y,R,G or B).
// Un-Multiply operation transforms x into x * 255 / A.
@ -644,42 +604,34 @@ void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
int inverse);
// Same for a row of single values, with side alpha values.
extern void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr,
const uint8_t* WEBP_RESTRICT const alpha,
extern void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
int width, int inverse);
// Same a WebPMultRow(), but for several 'num_rows' rows.
void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride,
const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
void WebPMultRows(uint8_t* ptr, int stride,
const uint8_t* alpha, int alpha_stride,
int width, int num_rows, int inverse);
// Plain-C versions, used as fallback by some implementations.
void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
const uint8_t* WEBP_RESTRICT const alpha,
void WebPMultRow_C(uint8_t* const ptr, const uint8_t* const alpha,
int width, int inverse);
void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse);
#ifdef WORDS_BIGENDIAN
// ARGB packing function: a/r/g/b input is rgba or bgra order.
extern void (*WebPPackARGB)(const uint8_t* WEBP_RESTRICT a,
const uint8_t* WEBP_RESTRICT r,
const uint8_t* WEBP_RESTRICT g,
const uint8_t* WEBP_RESTRICT b,
int len, uint32_t* WEBP_RESTRICT out);
extern void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r,
const uint8_t* g, const uint8_t* b, int len,
uint32_t* out);
#endif
// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order.
extern void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r,
const uint8_t* WEBP_RESTRICT g,
const uint8_t* WEBP_RESTRICT b,
int len, int step, uint32_t* WEBP_RESTRICT out);
extern void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
int len, int step, uint32_t* out);
// This function returns true if src[i] contains a value different from 0xff.
extern int (*WebPHasAlpha8b)(const uint8_t* src, int length);
// This function returns true if src[4*i] contains a value different from 0xff.
extern int (*WebPHasAlpha32b)(const uint8_t* src, int length);
// replaces transparent values in src[] by 'color'.
extern void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color);
// To be called first before using the above.
void WebPInitAlphaProcessing(void);

View File

@ -773,10 +773,10 @@ WEBP_DSP_INIT_FUNC(VP8EncDspInit) {
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_HAVE_SSE2)
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8EncDspInitSSE2();
#if defined(WEBP_HAVE_SSE41)
#if defined(WEBP_USE_SSE41)
if (VP8GetCPUInfo(kSSE4_1)) {
VP8EncDspInitSSE41();
}
@ -800,7 +800,7 @@ WEBP_DSP_INIT_FUNC(VP8EncDspInit) {
#endif
}
#if defined(WEBP_HAVE_NEON)
#if defined(WEBP_USE_NEON)
if (WEBP_NEON_OMIT_C_CODE ||
(VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
VP8EncDspInitNEON();

View File

@ -777,7 +777,7 @@ static WEBP_INLINE void VR4_SSE2(uint8_t* dst,
const __m128i ABCD0 = _mm_srli_si128(XABCD, 1);
const __m128i abcd = _mm_avg_epu8(XABCD, ABCD0);
const __m128i _XABCD = _mm_slli_si128(XABCD, 1);
const __m128i IXABCD = _mm_insert_epi16(_XABCD, (short)(I | (X << 8)), 0);
const __m128i IXABCD = _mm_insert_epi16(_XABCD, I | (X << 8), 0);
const __m128i avg1 = _mm_avg_epu8(IXABCD, ABCD0);
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb);

View File

@ -33,9 +33,9 @@ static WEBP_INLINE void PredictLine_C(const uint8_t* src, const uint8_t* pred,
uint8_t* dst, int length, int inverse) {
int i;
if (inverse) {
for (i = 0; i < length; ++i) dst[i] = (uint8_t)(src[i] + pred[i]);
for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i];
} else {
for (i = 0; i < length; ++i) dst[i] = (uint8_t)(src[i] - pred[i]);
for (i = 0; i < length; ++i) dst[i] = src[i] - pred[i];
}
}
@ -155,7 +155,7 @@ static WEBP_INLINE void DoGradientFilter_C(const uint8_t* in,
const int pred = GradientPredictor_C(preds[w - 1],
preds[w - stride],
preds[w - stride - 1]);
out[w] = (uint8_t)(in[w] + (inverse ? pred : -pred));
out[w] = in[w] + (inverse ? pred : -pred);
}
++row;
preds += stride;
@ -194,7 +194,7 @@ static void HorizontalUnfilter_C(const uint8_t* prev, const uint8_t* in,
uint8_t pred = (prev == NULL) ? 0 : prev[0];
int i;
for (i = 0; i < width; ++i) {
out[i] = (uint8_t)(pred + in[i]);
out[i] = pred + in[i];
pred = out[i];
}
}
@ -206,7 +206,7 @@ static void VerticalUnfilter_C(const uint8_t* prev, const uint8_t* in,
HorizontalUnfilter_C(NULL, in, out, width);
} else {
int i;
for (i = 0; i < width; ++i) out[i] = (uint8_t)(prev[i] + in[i]);
for (i = 0; i < width; ++i) out[i] = prev[i] + in[i];
}
}
#endif // !WEBP_NEON_OMIT_C_CODE
@ -220,7 +220,7 @@ static void GradientUnfilter_C(const uint8_t* prev, const uint8_t* in,
int i;
for (i = 0; i < width; ++i) {
top = prev[i]; // need to read this first, in case prev==out
left = (uint8_t)(in[i] + GradientPredictor_C(left, top, top_left));
left = in[i] + GradientPredictor_C(left, top, top_left);
top_left = top;
out[i] = left;
}
@ -254,7 +254,7 @@ WEBP_DSP_INIT_FUNC(VP8FiltersInit) {
#endif
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_HAVE_SSE2)
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8FiltersInitSSE2();
}
@ -271,7 +271,7 @@ WEBP_DSP_INIT_FUNC(VP8FiltersInit) {
#endif
}
#if defined(WEBP_HAVE_NEON)
#if defined(WEBP_USE_NEON)
if (WEBP_NEON_OMIT_C_CODE ||
(VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
VP8FiltersInitNEON();

View File

@ -163,8 +163,7 @@ static void GradientPredictDirect_SSE2(const uint8_t* const row,
_mm_storel_epi64((__m128i*)(out + i), H);
}
for (; i < length; ++i) {
const int delta = GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]);
out[i] = (uint8_t)(row[i] - delta);
out[i] = row[i] - GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]);
}
}
@ -189,7 +188,7 @@ static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* in,
// Filter line-by-line.
while (row < last_row) {
out[0] = (uint8_t)(in[0] - in[-stride]);
out[0] = in[0] - in[-stride];
GradientPredictDirect_SSE2(in + 1, in + 1 - stride, out + 1, width - 1);
++row;
in += stride;
@ -224,7 +223,7 @@ static void HorizontalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
uint8_t* out, int width) {
int i;
__m128i last;
out[0] = (uint8_t)(in[0] + (prev == NULL ? 0 : prev[0]));
out[0] = in[0] + (prev == NULL ? 0 : prev[0]);
if (width <= 1) return;
last = _mm_set_epi32(0, 0, 0, out[0]);
for (i = 1; i + 8 <= width; i += 8) {
@ -239,7 +238,7 @@ static void HorizontalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
_mm_storel_epi64((__m128i*)(out + i), A7);
last = _mm_srli_epi64(A7, 56);
}
for (; i < width; ++i) out[i] = (uint8_t)(in[i] + out[i - 1]);
for (; i < width; ++i) out[i] = in[i] + out[i - 1];
}
static void VerticalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
@ -260,7 +259,7 @@ static void VerticalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
_mm_storeu_si128((__m128i*)&out[i + 0], C0);
_mm_storeu_si128((__m128i*)&out[i + 16], C1);
}
for (; i < width; ++i) out[i] = (uint8_t)(in[i] + prev[i]);
for (; i < width; ++i) out[i] = in[i] + prev[i];
}
}
@ -297,8 +296,7 @@ static void GradientPredictInverse_SSE2(const uint8_t* const in,
_mm_storel_epi64((__m128i*)&row[i], out);
}
for (; i < length; ++i) {
const int delta = GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]);
row[i] = (uint8_t)(in[i] + delta);
row[i] = in[i] + GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]);
}
}
}
@ -308,7 +306,7 @@ static void GradientUnfilter_SSE2(const uint8_t* prev, const uint8_t* in,
if (prev == NULL) {
HorizontalUnfilter_SSE2(NULL, in, out, width);
} else {
out[0] = (uint8_t)(in[0] + prev[0]); // predict from above
out[0] = in[0] + prev[0]; // predict from above
GradientPredictInverse_SSE2(in + 1, prev + 1, out + 1, width - 1);
}
}
@ -320,12 +318,7 @@ extern void VP8FiltersInitSSE2(void);
WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitSSE2(void) {
WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_SSE2;
#if defined(CHROMIUM)
// TODO(crbug.com/654974)
(void)VerticalUnfilter_SSE2;
#else
WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_SSE2;
#endif
WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_SSE2;
WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_SSE2;

View File

@ -81,7 +81,7 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is
// inlined.
#if defined(__arm__) && defined(__GNUC__) && LOCAL_GCC_VERSION <= 0x409
#if defined(__arm__) && LOCAL_GCC_VERSION <= 0x409
# define LOCAL_INLINE __attribute__ ((noinline))
#else
# define LOCAL_INLINE WEBP_INLINE
@ -107,93 +107,88 @@ static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
//------------------------------------------------------------------------------
// Predictors
uint32_t VP8LPredictor0_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor0_C(uint32_t left, const uint32_t* const top) {
(void)top;
(void)left;
return ARGB_BLACK;
}
uint32_t VP8LPredictor1_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor1_C(uint32_t left, const uint32_t* const top) {
(void)top;
return left;
}
uint32_t VP8LPredictor2_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor2_C(uint32_t left, const uint32_t* const top) {
(void)left;
return top[0];
}
uint32_t VP8LPredictor3_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor3_C(uint32_t left, const uint32_t* const top) {
(void)left;
return top[1];
}
uint32_t VP8LPredictor4_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor4_C(uint32_t left, const uint32_t* const top) {
(void)left;
return top[-1];
}
uint32_t VP8LPredictor5_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor5_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average3(left, top[0], top[1]);
return pred;
}
uint32_t VP8LPredictor6_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor6_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[-1]);
return pred;
}
uint32_t VP8LPredictor7_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor7_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[0]);
return pred;
}
uint32_t VP8LPredictor8_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor8_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[-1], top[0]);
(void)left;
return pred;
}
uint32_t VP8LPredictor9_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor9_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[0], top[1]);
(void)left;
return pred;
}
uint32_t VP8LPredictor10_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor10_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
return pred;
}
uint32_t VP8LPredictor11_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor11_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Select(top[0], left, top[-1]);
return pred;
}
uint32_t VP8LPredictor12_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor12_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
return pred;
}
uint32_t VP8LPredictor13_C(uint32_t left, const uint32_t* const top) {
static uint32_t Predictor13_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
return pred;
}
static void PredictorAdd0_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) {
int x;
(void)upper;
for (x = 0; x < num_pixels; ++x) out[x] = VP8LAddPixels(in[x], ARGB_BLACK);
}
GENERATE_PREDICTOR_ADD(Predictor0_C, PredictorAdd0_C)
static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) {
int i;
uint32_t left = out[-1];
(void)upper;
for (i = 0; i < num_pixels; ++i) {
out[i] = left = VP8LAddPixels(in[i], left);
}
(void)upper;
}
GENERATE_PREDICTOR_ADD(VP8LPredictor2_C, PredictorAdd2_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor3_C, PredictorAdd3_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor4_C, PredictorAdd4_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor5_C, PredictorAdd5_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor6_C, PredictorAdd6_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor7_C, PredictorAdd7_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor8_C, PredictorAdd8_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor9_C, PredictorAdd9_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor10_C, PredictorAdd10_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor11_C, PredictorAdd11_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor12_C, PredictorAdd12_C)
GENERATE_PREDICTOR_ADD(VP8LPredictor13_C, PredictorAdd13_C)
GENERATE_PREDICTOR_ADD(Predictor2_C, PredictorAdd2_C)
GENERATE_PREDICTOR_ADD(Predictor3_C, PredictorAdd3_C)
GENERATE_PREDICTOR_ADD(Predictor4_C, PredictorAdd4_C)
GENERATE_PREDICTOR_ADD(Predictor5_C, PredictorAdd5_C)
GENERATE_PREDICTOR_ADD(Predictor6_C, PredictorAdd6_C)
GENERATE_PREDICTOR_ADD(Predictor7_C, PredictorAdd7_C)
GENERATE_PREDICTOR_ADD(Predictor8_C, PredictorAdd8_C)
GENERATE_PREDICTOR_ADD(Predictor9_C, PredictorAdd9_C)
GENERATE_PREDICTOR_ADD(Predictor10_C, PredictorAdd10_C)
GENERATE_PREDICTOR_ADD(Predictor11_C, PredictorAdd11_C)
GENERATE_PREDICTOR_ADD(Predictor12_C, PredictorAdd12_C)
GENERATE_PREDICTOR_ADD(Predictor13_C, PredictorAdd13_C)
//------------------------------------------------------------------------------
@ -275,14 +270,14 @@ void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
int i;
for (i = 0; i < num_pixels; ++i) {
const uint32_t argb = src[i];
const int8_t green = (int8_t)(argb >> 8);
const uint32_t green = argb >> 8;
const uint32_t red = argb >> 16;
int new_red = red & 0xff;
int new_blue = argb & 0xff;
new_red += ColorTransformDelta(m->green_to_red_, green);
new_red &= 0xff;
new_blue += ColorTransformDelta(m->green_to_blue_, green);
new_blue += ColorTransformDelta(m->red_to_blue_, (int8_t)new_red);
new_blue += ColorTransformDelta(m->red_to_blue_, new_red);
new_blue &= 0xff;
dst[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
}
@ -562,6 +557,7 @@ VP8LPredictorFunc VP8LPredictors[16];
// exposed plain-C implementations
VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16];
VP8LPredictorFunc VP8LPredictors_C[16];
VP8LTransformColorInverseFunc VP8LTransformColorInverse;
@ -575,7 +571,6 @@ VP8LMapARGBFunc VP8LMapColor32b;
VP8LMapAlphaFunc VP8LMapColor8b;
extern void VP8LDspInitSSE2(void);
extern void VP8LDspInitSSE41(void);
extern void VP8LDspInitNEON(void);
extern void VP8LDspInitMIPSdspR2(void);
extern void VP8LDspInitMSA(void);
@ -600,7 +595,8 @@ extern void VP8LDspInitMSA(void);
} while (0);
WEBP_DSP_INIT_FUNC(VP8LDspInit) {
COPY_PREDICTOR_ARRAY(VP8LPredictor, VP8LPredictors)
COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors)
COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors_C)
COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd)
COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd_C)
@ -622,14 +618,9 @@ WEBP_DSP_INIT_FUNC(VP8LDspInit) {
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_HAVE_SSE2)
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8LDspInitSSE2();
#if defined(WEBP_HAVE_SSE41)
if (VP8GetCPUInfo(kSSE4_1)) {
VP8LDspInitSSE41();
}
#endif
}
#endif
#if defined(WEBP_USE_MIPS_DSP_R2)
@ -644,7 +635,7 @@ WEBP_DSP_INIT_FUNC(VP8LDspInit) {
#endif
}
#if defined(WEBP_HAVE_NEON)
#if defined(WEBP_USE_NEON)
if (WEBP_NEON_OMIT_C_CODE ||
(VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
VP8LDspInitNEON();

View File

@ -30,22 +30,7 @@ extern "C" {
typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top);
extern VP8LPredictorFunc VP8LPredictors[16];
uint32_t VP8LPredictor0_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor1_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor2_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor3_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor4_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor5_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor6_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor7_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor8_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor9_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor10_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor11_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor12_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor13_C(uint32_t left, const uint32_t* const top);
extern VP8LPredictorFunc VP8LPredictors_C[16];
// These Add/Sub function expects upper[-1] and out[-1] to be readable.
typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* in,
const uint32_t* upper, int num_pixels,

View File

@ -177,13 +177,24 @@ uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(out[x - 1], upper + x); \
out[x] = VP8LAddPixels(in[x], pred); \
} \
}
// It subtracts the prediction from the input pixel and stores the residual
// in the output pixel.
#define GENERATE_PREDICTOR_SUB(PREDICTOR, PREDICTOR_SUB) \
static void PREDICTOR_SUB(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(in[x - 1], upper + x); \
out[x] = VP8LSubPixels(in[x], pred); \
} \
}
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -329,15 +329,6 @@ const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = {
static float FastSLog2Slow_C(uint32_t v) {
assert(v >= LOG_LOOKUP_IDX_MAX);
if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
#if !defined(WEBP_HAVE_SLOW_CLZ_CTZ)
// use clz if available
const int log_cnt = BitsLog2Floor(v) - 7;
const uint32_t y = 1 << log_cnt;
int correction = 0;
const float v_f = (float)v;
const uint32_t orig_v = v;
v >>= log_cnt;
#else
int log_cnt = 0;
uint32_t y = 1;
int correction = 0;
@ -348,7 +339,6 @@ static float FastSLog2Slow_C(uint32_t v) {
v = v >> 1;
y = y << 1;
} while (v >= LOG_LOOKUP_IDX_MAX);
#endif
// vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256
// Xf = floor(Xf) * (1 + (v % y) / v)
// log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v)
@ -365,14 +355,6 @@ static float FastSLog2Slow_C(uint32_t v) {
static float FastLog2Slow_C(uint32_t v) {
assert(v >= LOG_LOOKUP_IDX_MAX);
if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
#if !defined(WEBP_HAVE_SLOW_CLZ_CTZ)
// use clz if available
const int log_cnt = BitsLog2Floor(v) - 7;
const uint32_t y = 1 << log_cnt;
const uint32_t orig_v = v;
double log_2;
v >>= log_cnt;
#else
int log_cnt = 0;
uint32_t y = 1;
const uint32_t orig_v = v;
@ -382,7 +364,6 @@ static float FastLog2Slow_C(uint32_t v) {
v = v >> 1;
y = y << 1;
} while (v >= LOG_LOOKUP_IDX_MAX);
#endif
log_2 = kLog2Table[v] + log_cnt;
if (orig_v >= APPROX_LOG_MAX) {
// Since the division is still expensive, add this correction factor only
@ -534,17 +515,13 @@ static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, int8_t color) {
return ((int)color_pred * color) >> 5;
}
static WEBP_INLINE int8_t U32ToS8(uint32_t v) {
return (int8_t)(v & 0xff);
}
void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
int num_pixels) {
int i;
for (i = 0; i < num_pixels; ++i) {
const uint32_t argb = data[i];
const int8_t green = U32ToS8(argb >> 8);
const int8_t red = U32ToS8(argb >> 16);
const uint32_t green = argb >> 8;
const uint32_t red = argb >> 16;
int new_red = red & 0xff;
int new_blue = argb & 0xff;
new_red -= ColorTransformDelta(m->green_to_red_, green);
@ -558,7 +535,7 @@ void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
uint32_t argb) {
const int8_t green = U32ToS8(argb >> 8);
const uint32_t green = argb >> 8;
int new_red = argb >> 16;
new_red -= ColorTransformDelta(green_to_red, green);
return (new_red & 0xff);
@ -567,9 +544,9 @@ static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
uint8_t red_to_blue,
uint32_t argb) {
const int8_t green = U32ToS8(argb >> 8);
const int8_t red = U32ToS8(argb >> 16);
uint8_t new_blue = argb & 0xff;
const uint32_t green = argb >> 8;
const uint32_t red = argb >> 16;
uint8_t new_blue = argb;
new_blue -= ColorTransformDelta(green_to_blue, green);
new_blue -= ColorTransformDelta(red_to_blue, red);
return (new_blue & 0xff);
@ -581,7 +558,7 @@ void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int stride,
while (tile_height-- > 0) {
int x;
for (x = 0; x < tile_width; ++x) {
++histo[TransformColorRed((uint8_t)green_to_red, argb[x])];
++histo[TransformColorRed(green_to_red, argb[x])];
}
argb += stride;
}
@ -594,8 +571,7 @@ void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride,
while (tile_height-- > 0) {
int x;
for (x = 0; x < tile_width; ++x) {
++histo[TransformColorBlue((uint8_t)green_to_blue, (uint8_t)red_to_blue,
argb[x])];
++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[x])];
}
argb += stride;
}
@ -721,6 +697,140 @@ void VP8LHistogramAdd(const VP8LHistogram* const a,
//------------------------------------------------------------------------------
// Image transforms.
static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1);
}
static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
return Average2(Average2(a0, a2), a1);
}
static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
uint32_t a2, uint32_t a3) {
return Average2(Average2(a0, a1), Average2(a2, a3));
}
static WEBP_INLINE uint32_t Clip255(uint32_t a) {
if (a < 256) {
return a;
}
// return 0, when a is a negative integer.
// return 255, when a is positive.
return ~a >> 24;
}
static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) {
return Clip255(a + b - c);
}
static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
uint32_t c2) {
const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);
const int r = AddSubtractComponentFull((c0 >> 16) & 0xff,
(c1 >> 16) & 0xff,
(c2 >> 16) & 0xff);
const int g = AddSubtractComponentFull((c0 >> 8) & 0xff,
(c1 >> 8) & 0xff,
(c2 >> 8) & 0xff);
const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
}
static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) {
return Clip255(a + (a - b) / 2);
}
static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
uint32_t c2) {
const uint32_t ave = Average2(c0, c1);
const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24);
const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff);
const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff);
const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff);
return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
}
// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined.
#if defined(__arm__) && \
(LOCAL_GCC_VERSION == 0x409 || LOCAL_GCC_VERSION == 0x408)
# define LOCAL_INLINE __attribute__ ((noinline))
#else
# define LOCAL_INLINE WEBP_INLINE
#endif
static LOCAL_INLINE int Sub3(int a, int b, int c) {
const int pb = b - c;
const int pa = a - c;
return abs(pb) - abs(pa);
}
#undef LOCAL_INLINE
static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
const int pa_minus_pb =
Sub3((a >> 24) , (b >> 24) , (c >> 24) ) +
Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) +
Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff);
return (pa_minus_pb <= 0) ? a : b;
}
//------------------------------------------------------------------------------
// Predictors
static uint32_t Predictor2(uint32_t left, const uint32_t* const top) {
(void)left;
return top[0];
}
static uint32_t Predictor3(uint32_t left, const uint32_t* const top) {
(void)left;
return top[1];
}
static uint32_t Predictor4(uint32_t left, const uint32_t* const top) {
(void)left;
return top[-1];
}
static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average3(left, top[0], top[1]);
return pred;
}
static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[-1]);
return pred;
}
static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[0]);
return pred;
}
static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[-1], top[0]);
(void)left;
return pred;
}
static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[0], top[1]);
(void)left;
return pred;
}
static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
return pred;
}
static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Select(top[0], left, top[-1]);
return pred;
}
static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
return pred;
}
static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
return pred;
}
//------------------------------------------------------------------------------
static void PredictorSub0_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) {
int i;
@ -735,33 +845,18 @@ static void PredictorSub1_C(const uint32_t* in, const uint32_t* upper,
(void)upper;
}
// It subtracts the prediction from the input pixel and stores the residual
// in the output pixel.
#define GENERATE_PREDICTOR_SUB(PREDICTOR_I) \
static void PredictorSub##PREDICTOR_I##_C(const uint32_t* in, \
const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = \
VP8LPredictor##PREDICTOR_I##_C(in[x - 1], upper + x); \
out[x] = VP8LSubPixels(in[x], pred); \
} \
}
GENERATE_PREDICTOR_SUB(2)
GENERATE_PREDICTOR_SUB(3)
GENERATE_PREDICTOR_SUB(4)
GENERATE_PREDICTOR_SUB(5)
GENERATE_PREDICTOR_SUB(6)
GENERATE_PREDICTOR_SUB(7)
GENERATE_PREDICTOR_SUB(8)
GENERATE_PREDICTOR_SUB(9)
GENERATE_PREDICTOR_SUB(10)
GENERATE_PREDICTOR_SUB(11)
GENERATE_PREDICTOR_SUB(12)
GENERATE_PREDICTOR_SUB(13)
GENERATE_PREDICTOR_SUB(Predictor2, PredictorSub2_C)
GENERATE_PREDICTOR_SUB(Predictor3, PredictorSub3_C)
GENERATE_PREDICTOR_SUB(Predictor4, PredictorSub4_C)
GENERATE_PREDICTOR_SUB(Predictor5, PredictorSub5_C)
GENERATE_PREDICTOR_SUB(Predictor6, PredictorSub6_C)
GENERATE_PREDICTOR_SUB(Predictor7, PredictorSub7_C)
GENERATE_PREDICTOR_SUB(Predictor8, PredictorSub8_C)
GENERATE_PREDICTOR_SUB(Predictor9, PredictorSub9_C)
GENERATE_PREDICTOR_SUB(Predictor10, PredictorSub10_C)
GENERATE_PREDICTOR_SUB(Predictor11, PredictorSub11_C)
GENERATE_PREDICTOR_SUB(Predictor12, PredictorSub12_C)
GENERATE_PREDICTOR_SUB(Predictor13, PredictorSub13_C)
//------------------------------------------------------------------------------
@ -862,10 +957,10 @@ WEBP_DSP_INIT_FUNC(VP8LEncDspInit) {
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_HAVE_SSE2)
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
VP8LEncDspInitSSE2();
#if defined(WEBP_HAVE_SSE41)
#if defined(WEBP_USE_SSE41)
if (VP8GetCPUInfo(kSSE4_1)) {
VP8LEncDspInitSSE41();
}
@ -889,7 +984,7 @@ WEBP_DSP_INIT_FUNC(VP8LEncDspInit) {
#endif
}
#if defined(WEBP_HAVE_NEON)
#if defined(WEBP_USE_NEON)
if (WEBP_NEON_OMIT_C_CODE ||
(VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
VP8LEncDspInitNEON();

View File

@ -232,55 +232,76 @@ static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
//------------------------------------------------------------------------------
// Entropy
// TODO(https://crbug.com/webp/499): this function produces different results
// from the C code due to use of double/float resulting in output differences
// when compared to -noasm.
#if !(defined(WEBP_HAVE_SLOW_CLZ_CTZ) || defined(__i386__) || defined(_M_IX86))
// Checks whether the X or Y contribution is worth computing and adding.
// Used in loop unrolling.
#define ANALYZE_X_OR_Y(x_or_y, j) \
do { \
if ((x_or_y)[i + (j)] != 0) retval -= VP8LFastSLog2((x_or_y)[i + (j)]); \
} while (0)
// Checks whether the X + Y contribution is worth computing and adding.
// Used in loop unrolling.
#define ANALYZE_XY(j) \
do { \
if (tmp[j] != 0) { \
retval -= VP8LFastSLog2(tmp[j]); \
ANALYZE_X_OR_Y(X, j); \
} \
} while (0)
static float CombinedShannonEntropy_SSE2(const int X[256], const int Y[256]) {
int i;
double retval = 0.;
int sumX = 0, sumXY = 0;
const __m128i zero = _mm_setzero_si128();
int sumX, sumXY;
int32_t tmp[4];
__m128i zero = _mm_setzero_si128();
// Sums up X + Y, 4 ints at a time (and will merge it at the end for sumXY).
__m128i sumXY_128 = zero;
__m128i sumX_128 = zero;
for (i = 0; i < 256; i += 16) {
const __m128i x0 = _mm_loadu_si128((const __m128i*)(X + i + 0));
const __m128i y0 = _mm_loadu_si128((const __m128i*)(Y + i + 0));
const __m128i x1 = _mm_loadu_si128((const __m128i*)(X + i + 4));
const __m128i y1 = _mm_loadu_si128((const __m128i*)(Y + i + 4));
const __m128i x2 = _mm_loadu_si128((const __m128i*)(X + i + 8));
const __m128i y2 = _mm_loadu_si128((const __m128i*)(Y + i + 8));
const __m128i x3 = _mm_loadu_si128((const __m128i*)(X + i + 12));
const __m128i y3 = _mm_loadu_si128((const __m128i*)(Y + i + 12));
const __m128i x4 = _mm_packs_epi16(_mm_packs_epi32(x0, x1),
_mm_packs_epi32(x2, x3));
const __m128i y4 = _mm_packs_epi16(_mm_packs_epi32(y0, y1),
_mm_packs_epi32(y2, y3));
const int32_t mx = _mm_movemask_epi8(_mm_cmpgt_epi8(x4, zero));
int32_t my = _mm_movemask_epi8(_mm_cmpgt_epi8(y4, zero)) | mx;
while (my) {
const int32_t j = BitsCtz(my);
int xy;
if ((mx >> j) & 1) {
const int x = X[i + j];
sumXY += x;
retval -= VP8LFastSLog2(x);
}
xy = X[i + j] + Y[i + j];
sumX += xy;
retval -= VP8LFastSLog2(xy);
my &= my - 1;
for (i = 0; i < 256; i += 4) {
const __m128i x = _mm_loadu_si128((const __m128i*)(X + i));
const __m128i y = _mm_loadu_si128((const __m128i*)(Y + i));
// Check if any X is non-zero: this actually provides a speedup as X is
// usually sparse.
if (_mm_movemask_epi8(_mm_cmpeq_epi32(x, zero)) != 0xFFFF) {
const __m128i xy_128 = _mm_add_epi32(x, y);
sumXY_128 = _mm_add_epi32(sumXY_128, xy_128);
sumX_128 = _mm_add_epi32(sumX_128, x);
// Analyze the different X + Y.
_mm_storeu_si128((__m128i*)tmp, xy_128);
ANALYZE_XY(0);
ANALYZE_XY(1);
ANALYZE_XY(2);
ANALYZE_XY(3);
} else {
// X is fully 0, so only deal with Y.
sumXY_128 = _mm_add_epi32(sumXY_128, y);
ANALYZE_X_OR_Y(Y, 0);
ANALYZE_X_OR_Y(Y, 1);
ANALYZE_X_OR_Y(Y, 2);
ANALYZE_X_OR_Y(Y, 3);
}
}
// Sum up sumX_128 to get sumX.
_mm_storeu_si128((__m128i*)tmp, sumX_128);
sumX = tmp[3] + tmp[2] + tmp[1] + tmp[0];
// Sum up sumXY_128 to get sumXY.
_mm_storeu_si128((__m128i*)tmp, sumXY_128);
sumXY = tmp[3] + tmp[2] + tmp[1] + tmp[0];
retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY);
return (float)retval;
}
#else
#define DONT_USE_COMBINED_SHANNON_ENTROPY_SSE2_FUNC // won't be faster
#endif
#undef ANALYZE_X_OR_Y
#undef ANALYZE_XY
//------------------------------------------------------------------------------
@ -342,7 +363,7 @@ static void BundleColorMap_SSE2(const uint8_t* const row, int width, int xbits,
assert(xbits <= 3);
switch (xbits) {
case 0: {
const __m128i ff = _mm_set1_epi16((short)0xff00);
const __m128i ff = _mm_set1_epi16(0xff00);
const __m128i zero = _mm_setzero_si128();
// Store 0xff000000 | (row[x] << 8).
for (x = 0; x + 16 <= width; x += 16, dst += 16) {
@ -361,7 +382,7 @@ static void BundleColorMap_SSE2(const uint8_t* const row, int width, int xbits,
break;
}
case 1: {
const __m128i ff = _mm_set1_epi16((short)0xff00);
const __m128i ff = _mm_set1_epi16(0xff00);
const __m128i mul = _mm_set1_epi16(0x110);
for (x = 0; x + 16 <= width; x += 16, dst += 8) {
// 0a0b | (where a/b are 4 bits).
@ -434,27 +455,24 @@ static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper,
_mm_storeu_si128((__m128i*)&out[i], res);
}
if (i != num_pixels) {
VP8LPredictorsSub_C[0](in + i, NULL, num_pixels - i, out + i);
VP8LPredictorsSub_C[0](in + i, upper + i, num_pixels - i, out + i);
}
(void)upper;
}
#define GENERATE_PREDICTOR_1(X, IN) \
static void PredictorSub##X##_SSE2(const uint32_t* const in, \
const uint32_t* const upper, \
int num_pixels, uint32_t* const out) { \
int i; \
for (i = 0; i + 4 <= num_pixels; i += 4) { \
const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \
const __m128i pred = _mm_loadu_si128((const __m128i*)&(IN)); \
const __m128i res = _mm_sub_epi8(src, pred); \
_mm_storeu_si128((__m128i*)&out[i], res); \
} \
if (i != num_pixels) { \
VP8LPredictorsSub_C[(X)](in + i, WEBP_OFFSET_PTR(upper, i), \
num_pixels - i, out + i); \
} \
}
#define GENERATE_PREDICTOR_1(X, IN) \
static void PredictorSub##X##_SSE2(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int i; \
for (i = 0; i + 4 <= num_pixels; i += 4) { \
const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \
const __m128i pred = _mm_loadu_si128((const __m128i*)&(IN)); \
const __m128i res = _mm_sub_epi8(src, pred); \
_mm_storeu_si128((__m128i*)&out[i], res); \
} \
if (i != num_pixels) { \
VP8LPredictorsSub_C[(X)](in + i, upper + i, num_pixels - i, out + i); \
} \
}
GENERATE_PREDICTOR_1(1, in[i - 1]) // Predictor1: L
GENERATE_PREDICTOR_1(2, upper[i]) // Predictor2: T
@ -638,9 +656,7 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) {
VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE2;
VP8LAddVector = AddVector_SSE2;
VP8LAddVectorEq = AddVectorEq_SSE2;
#if !defined(DONT_USE_COMBINED_SHANNON_ENTROPY_SSE2_FUNC)
VP8LCombinedShannonEntropy = CombinedShannonEntropy_SSE2;
#endif
VP8LVectorMismatch = VectorMismatch_SSE2;
VP8LBundleColorMap = BundleColorMap_SSE2;

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