mirror of
https://github.com/webmproject/libwebp.git
synced 2025-07-16 05:49:51 +02:00
Compare commits
47 Commits
v0.4.2-rc2
...
v0.4.3
Author | SHA1 | Date | |
---|---|---|---|
326b5fb863 | |||
a661e50bcb | |||
fcd94e925a | |||
569fe5789e | |||
bd852f5d81 | |||
2d58b64f51 | |||
a0d8ca576f | |||
34b1d29e3c | |||
75619881e6 | |||
a98757650a | |||
a6d4859725 | |||
77544d5f5b | |||
6dea15784d | |||
f7cd57b23d | |||
1d6b250b07 | |||
f97b3f86bf | |||
4ba83c1759 | |||
d34e8e3d18 | |||
bbbc524fb4 | |||
0339fa26eb | |||
5a0c2207f4 | |||
6e3a31d595 | |||
b49a578135 | |||
0a4391a196 | |||
90f1ec58a9 | |||
b61ce861f3 | |||
df1081bb82 | |||
39aa055529 | |||
f814f429ca | |||
8508ab99a7 | |||
5769623b6f | |||
b2e71a9080 | |||
1273e84517 | |||
3ae78eb757 | |||
5c1eeda922 | |||
c5ceea4899 | |||
d0859d69de | |||
046732ca65 | |||
4426f50179 | |||
e297fc7171 | |||
855fe4354b | |||
b7eb6d55c7 | |||
5691bdd9da | |||
8301da1380 | |||
6a2209aa36 | |||
36cad6abe8 | |||
e2ecae62f0 |
128
Android.mk
128
Android.mk
@ -10,8 +10,6 @@ ifeq ($(APP_OPTIM),release)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
|
|
||||||
ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),)
|
ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),)
|
||||||
# Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal
|
# Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal
|
||||||
# instructions to be generated for armv7a code. Instead target the neon code
|
# instructions to be generated for armv7a code. Instead target the neon code
|
||||||
@ -21,7 +19,7 @@ else
|
|||||||
NEON := c
|
NEON := c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LOCAL_SRC_FILES := \
|
dec_srcs := \
|
||||||
src/dec/alpha.c \
|
src/dec/alpha.c \
|
||||||
src/dec/buffer.c \
|
src/dec/buffer.c \
|
||||||
src/dec/frame.c \
|
src/dec/frame.c \
|
||||||
@ -32,6 +30,11 @@ LOCAL_SRC_FILES := \
|
|||||||
src/dec/vp8.c \
|
src/dec/vp8.c \
|
||||||
src/dec/vp8l.c \
|
src/dec/vp8l.c \
|
||||||
src/dec/webp.c \
|
src/dec/webp.c \
|
||||||
|
|
||||||
|
demux_srcs := \
|
||||||
|
src/demux/demux.c \
|
||||||
|
|
||||||
|
dsp_dec_srcs := \
|
||||||
src/dsp/alpha_processing.c \
|
src/dsp/alpha_processing.c \
|
||||||
src/dsp/alpha_processing_sse2.c \
|
src/dsp/alpha_processing_sse2.c \
|
||||||
src/dsp/cpu.c \
|
src/dsp/cpu.c \
|
||||||
@ -40,11 +43,6 @@ LOCAL_SRC_FILES := \
|
|||||||
src/dsp/dec_mips32.c \
|
src/dsp/dec_mips32.c \
|
||||||
src/dsp/dec_neon.$(NEON) \
|
src/dsp/dec_neon.$(NEON) \
|
||||||
src/dsp/dec_sse2.c \
|
src/dsp/dec_sse2.c \
|
||||||
src/dsp/enc.c \
|
|
||||||
src/dsp/enc_avx2.c \
|
|
||||||
src/dsp/enc_mips32.c \
|
|
||||||
src/dsp/enc_neon.$(NEON) \
|
|
||||||
src/dsp/enc_sse2.c \
|
|
||||||
src/dsp/lossless.c \
|
src/dsp/lossless.c \
|
||||||
src/dsp/lossless_mips32.c \
|
src/dsp/lossless_mips32.c \
|
||||||
src/dsp/lossless_neon.$(NEON) \
|
src/dsp/lossless_neon.$(NEON) \
|
||||||
@ -55,6 +53,15 @@ LOCAL_SRC_FILES := \
|
|||||||
src/dsp/yuv.c \
|
src/dsp/yuv.c \
|
||||||
src/dsp/yuv_mips32.c \
|
src/dsp/yuv_mips32.c \
|
||||||
src/dsp/yuv_sse2.c \
|
src/dsp/yuv_sse2.c \
|
||||||
|
|
||||||
|
dsp_enc_srcs := \
|
||||||
|
src/dsp/enc.c \
|
||||||
|
src/dsp/enc_avx2.c \
|
||||||
|
src/dsp/enc_mips32.c \
|
||||||
|
src/dsp/enc_neon.$(NEON) \
|
||||||
|
src/dsp/enc_sse2.c \
|
||||||
|
|
||||||
|
enc_srcs := \
|
||||||
src/enc/alpha.c \
|
src/enc/alpha.c \
|
||||||
src/enc/analysis.c \
|
src/enc/analysis.c \
|
||||||
src/enc/backward_references.c \
|
src/enc/backward_references.c \
|
||||||
@ -75,19 +82,38 @@ LOCAL_SRC_FILES := \
|
|||||||
src/enc/tree.c \
|
src/enc/tree.c \
|
||||||
src/enc/vp8l.c \
|
src/enc/vp8l.c \
|
||||||
src/enc/webpenc.c \
|
src/enc/webpenc.c \
|
||||||
|
|
||||||
|
mux_srcs := \
|
||||||
|
src/mux/muxedit.c \
|
||||||
|
src/mux/muxinternal.c \
|
||||||
|
src/mux/muxread.c \
|
||||||
|
|
||||||
|
utils_dec_srcs := \
|
||||||
src/utils/bit_reader.c \
|
src/utils/bit_reader.c \
|
||||||
src/utils/bit_writer.c \
|
|
||||||
src/utils/color_cache.c \
|
src/utils/color_cache.c \
|
||||||
src/utils/filters.c \
|
src/utils/filters.c \
|
||||||
src/utils/huffman.c \
|
src/utils/huffman.c \
|
||||||
src/utils/huffman_encode.c \
|
|
||||||
src/utils/quant_levels.c \
|
|
||||||
src/utils/quant_levels_dec.c \
|
src/utils/quant_levels_dec.c \
|
||||||
src/utils/random.c \
|
src/utils/random.c \
|
||||||
src/utils/rescaler.c \
|
src/utils/rescaler.c \
|
||||||
src/utils/thread.c \
|
src/utils/thread.c \
|
||||||
src/utils/utils.c \
|
src/utils/utils.c \
|
||||||
|
|
||||||
|
utils_enc_srcs := \
|
||||||
|
src/utils/bit_writer.c \
|
||||||
|
src/utils/huffman_encode.c \
|
||||||
|
src/utils/quant_levels.c \
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# libwebpdecoder
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
$(dec_srcs) \
|
||||||
|
$(dsp_dec_srcs) \
|
||||||
|
$(utils_dec_srcs) \
|
||||||
|
|
||||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
|
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
|
||||||
|
|
||||||
@ -96,6 +122,38 @@ LOCAL_ARM_MODE := arm
|
|||||||
|
|
||||||
LOCAL_STATIC_LIBRARIES := cpufeatures
|
LOCAL_STATIC_LIBRARIES := cpufeatures
|
||||||
|
|
||||||
|
LOCAL_MODULE := webpdecoder_static
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
ifeq ($(ENABLE_SHARED),1)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_WHOLE_STATIC_LIBRARIES := webpdecoder_static
|
||||||
|
|
||||||
|
LOCAL_MODULE := webpdecoder
|
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
endif # ENABLE_SHARED=1
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# libwebp
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
$(dsp_enc_srcs) \
|
||||||
|
$(enc_srcs) \
|
||||||
|
$(utils_enc_srcs) \
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
|
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
|
||||||
|
|
||||||
|
# prefer arm over thumb mode for performance gains
|
||||||
|
LOCAL_ARM_MODE := arm
|
||||||
|
|
||||||
|
LOCAL_WHOLE_STATIC_LIBRARIES := webpdecoder_static
|
||||||
|
|
||||||
LOCAL_MODULE := webp
|
LOCAL_MODULE := webp
|
||||||
|
|
||||||
ifeq ($(ENABLE_SHARED),1)
|
ifeq ($(ENABLE_SHARED),1)
|
||||||
@ -104,6 +162,54 @@ else
|
|||||||
include $(BUILD_STATIC_LIBRARY)
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# libwebpdemux
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := $(demux_srcs)
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
|
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
|
||||||
|
|
||||||
|
# prefer arm over thumb mode for performance gains
|
||||||
|
LOCAL_ARM_MODE := arm
|
||||||
|
|
||||||
|
LOCAL_MODULE := webpdemux
|
||||||
|
|
||||||
|
ifeq ($(ENABLE_SHARED),1)
|
||||||
|
LOCAL_SHARED_LIBRARIES := webp
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
else
|
||||||
|
LOCAL_STATIC_LIBRARIES := webp
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
endif
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# libwebpmux
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := $(mux_srcs)
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
|
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
|
||||||
|
|
||||||
|
# prefer arm over thumb mode for performance gains
|
||||||
|
LOCAL_ARM_MODE := arm
|
||||||
|
|
||||||
|
LOCAL_MODULE := webpmux
|
||||||
|
|
||||||
|
ifeq ($(ENABLE_SHARED),1)
|
||||||
|
LOCAL_SHARED_LIBRARIES := webp
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
else
|
||||||
|
LOCAL_STATIC_LIBRARIES := webp
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
endif
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
include $(LOCAL_PATH)/examples/Android.mk
|
include $(LOCAL_PATH)/examples/Android.mk
|
||||||
|
|
||||||
$(call import-module,android/cpufeatures)
|
$(call import-module,android/cpufeatures)
|
||||||
|
51
ChangeLog
51
ChangeLog
@ -1,3 +1,50 @@
|
|||||||
|
a661e50 Disable NEON code on Native Client
|
||||||
|
fcd94e9 update ChangeLog (tag: v0.4.3-rc1)
|
||||||
|
569fe57 update NEWS
|
||||||
|
bd852f5 bump version to 0.4.3
|
||||||
|
2d58b64 WebPPictureRescale: add a note about 0 width/height
|
||||||
|
a0d8ca5 examples/Android.mk: add webpmux_example target
|
||||||
|
34b1d29 Android.mk: add webpmux target
|
||||||
|
7561988 Android.mk: add webpdemux target
|
||||||
|
a987576 Android.mk: add webpdecoder{,_static} targets
|
||||||
|
a6d4859 Android.mk: split source lists per-directory
|
||||||
|
77544d5 fix iOS arm64 build with Xcode 6.3
|
||||||
|
6dea157 doc/webp-container-spec: note MSB order for chunk diagrams
|
||||||
|
f7cd57b doc/webp-container-spec: cosmetics
|
||||||
|
1d6b250 vwebp: clear canvas at the beginning of each loop
|
||||||
|
f97b3f8 webp-container-spec: clarify background clear on loop
|
||||||
|
4ba83c1 vwebp: remove unnecessary static Help() prototype
|
||||||
|
d34e8e3 vwebp/animation: display last frame on end-of-loop
|
||||||
|
bbbc524 dec/vp8: clear 'dither_' on skipped blocks
|
||||||
|
0339fa2 lossless_neon: enable subtract green for aarch64
|
||||||
|
5a0c220 Regression fix for lossless decoding
|
||||||
|
6e3a31d wicdec: (msvs) quiet some /analyze warnings
|
||||||
|
b49a578 dwebp/WritePNG: mark png variables volatile
|
||||||
|
0a4391a dwebp: include setjmp.h w/WEBP_HAVE_PNG
|
||||||
|
90f1ec5 dwebp: correct sign in format strings
|
||||||
|
b61ce86 VP8LEncodeStream: add an assert
|
||||||
|
df1081b dsp/cpu: (msvs) add include for __cpuidex
|
||||||
|
39aa055 dsp/cpu: (msvs) avoid immintrin.h on _M_ARM
|
||||||
|
f814f42 dsp/cpu: add include for _xgetbv() w/MSVS
|
||||||
|
8508ab9 cpu: fix AVX2 detection for gcc/clang targets
|
||||||
|
5769623 fix handling of zero-sized partition #0 corner case
|
||||||
|
b2e71a9 make the 'last_cpuinfo_used' variable names unique
|
||||||
|
1273e84 add -Wformat-nonliteral and -Wformat-security
|
||||||
|
3ae78eb multi-thread fix: lock each entry points with a static var
|
||||||
|
5c1eeda webp-container-spec: remove references to fragments
|
||||||
|
c5ceea4 enc_neon: fix building with non-Xcode clang (iOS)
|
||||||
|
d0859d6 iosbuild: add x64_64 simulator support
|
||||||
|
046732c WebPEncode: Support encoding same pic twice (even if modified)
|
||||||
|
4426f50 webp/types.h: use inline for clang++/-std=c++11
|
||||||
|
e297fc7 gif2webp: Use the default hint instead of WEBP_HINT_GRAPH.
|
||||||
|
855fe43 Makefile.vc: add a 'legacy' RTLIBCFG option
|
||||||
|
b7eb6d5 gif2webp: Support GIF_DISPOSE_RESTORE_PREVIOUS
|
||||||
|
5691bdd gif2webp: Handle frames with odd offsets + disposal to background.
|
||||||
|
8301da1 stopwatch.h: fix includes
|
||||||
|
6a2209a update ChangeLog (tag: v0.4.2, origin/0.4.2, 0.4.2)
|
||||||
|
36cad6a bit_reader.h: cosmetics: fix a typo
|
||||||
|
e2ecae6 enc_mips32: workaround gcc-4.9 bug
|
||||||
|
243e68d update ChangeLog (tag: v0.4.2-rc2)
|
||||||
eec5f5f enc/vp8enci.h: update version number
|
eec5f5f enc/vp8enci.h: update version number
|
||||||
0c1b98d update NEWS
|
0c1b98d update NEWS
|
||||||
69b0fc9 update AUTHORS
|
69b0fc9 update AUTHORS
|
||||||
@ -51,7 +98,7 @@ fc3c175 dsp: detect mips64 & disable mips32 code
|
|||||||
c1a7955 cwebp.1: restore quality description
|
c1a7955 cwebp.1: restore quality description
|
||||||
57a7e73 correct alpha_dithering_strength ABI check
|
57a7e73 correct alpha_dithering_strength ABI check
|
||||||
6c83157 correct WebPMemoryWriterClear ABI check
|
6c83157 correct WebPMemoryWriterClear ABI check
|
||||||
8af2771 update ChangeLog (tag: v0.4.1, 0.4.1)
|
8af2771 update ChangeLog (tag: v0.4.1, origin/0.4.1, 0.4.1)
|
||||||
f59c0b4 iosbuild.sh: specify optimization flags
|
f59c0b4 iosbuild.sh: specify optimization flags
|
||||||
8d34ea3 update ChangeLog (tag: v0.4.1-rc1)
|
8d34ea3 update ChangeLog (tag: v0.4.1-rc1)
|
||||||
dbc3da6 makefile.unix: add vwebp.1 to the dist target
|
dbc3da6 makefile.unix: add vwebp.1 to the dist target
|
||||||
@ -71,7 +118,7 @@ c2fc52e restore encode API compatibility
|
|||||||
793368e restore decode API compatibility
|
793368e restore decode API compatibility
|
||||||
b8984f3 gif2webp: fix compile with giflib 5.1.0
|
b8984f3 gif2webp: fix compile with giflib 5.1.0
|
||||||
222f9b1 gif2webp: simplify giflib version checking
|
222f9b1 gif2webp: simplify giflib version checking
|
||||||
d2cc61b Extend MakeARGB32() to accept Alpha channel. (master)
|
d2cc61b Extend MakeARGB32() to accept Alpha channel.
|
||||||
4595b62 Merge "use explicit size of kErrorMessages[] arrays"
|
4595b62 Merge "use explicit size of kErrorMessages[] arrays"
|
||||||
157de01 Merge "Actuate memory stats for PRINT_MEMORY_INFO"
|
157de01 Merge "Actuate memory stats for PRINT_MEMORY_INFO"
|
||||||
fbda2f4 JPEG decoder: delay conversion to YUV to WebPEncode() call
|
fbda2f4 JPEG decoder: delay conversion to YUV to WebPEncode() call
|
||||||
|
@ -27,7 +27,7 @@ PLATFORM_LDFLAGS = /SAFESEH
|
|||||||
NOLOGO = /nologo
|
NOLOGO = /nologo
|
||||||
CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
|
CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
|
||||||
CCDEBUG = cl.exe $(NOLOGO) /Od /Gm /Zi /D_DEBUG /RTC1
|
CCDEBUG = cl.exe $(NOLOGO) /Od /Gm /Zi /D_DEBUG /RTC1
|
||||||
CFLAGS = /Isrc $(NOLOGO) /W3 /EHsc /c /GS
|
CFLAGS = /Isrc $(NOLOGO) /W3 /EHsc /c
|
||||||
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
|
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
|
||||||
CFLAGS = $(CFLAGS) /DHAVE_WINCODEC_H /DWEBP_USE_THREAD
|
CFLAGS = $(CFLAGS) /DHAVE_WINCODEC_H /DWEBP_USE_THREAD
|
||||||
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
|
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
|
||||||
@ -54,6 +54,11 @@ AVX2_FLAGS = /arch:AVX2
|
|||||||
!IF "$(RTLIBCFG)" == "static"
|
!IF "$(RTLIBCFG)" == "static"
|
||||||
RTLIB = /MT
|
RTLIB = /MT
|
||||||
RTLIBD = /MTd
|
RTLIBD = /MTd
|
||||||
|
!ELSE IF "$(RTLIBCFG)" == "legacy"
|
||||||
|
RTLIBCFG = static
|
||||||
|
RTLIB = /MT
|
||||||
|
RTLIBD = /MTd
|
||||||
|
CFLAGS = $(CFLAGS) /GS- /arch:IA32
|
||||||
!ELSE
|
!ELSE
|
||||||
RTLIB = /MD
|
RTLIB = /MD
|
||||||
RTLIBD = /MDd
|
RTLIBD = /MDd
|
||||||
@ -139,6 +144,7 @@ CFGSET = TRUE
|
|||||||
!MESSAGE - all - build (de)mux-based targets for CFG
|
!MESSAGE - all - build (de)mux-based targets for CFG
|
||||||
!MESSAGE
|
!MESSAGE
|
||||||
!MESSAGE RTLIBCFG controls the runtime library linkage - 'static' or 'dynamic'.
|
!MESSAGE RTLIBCFG controls the runtime library linkage - 'static' or 'dynamic'.
|
||||||
|
!MESSAGE 'legacy' will produce a Windows 2000 compatible library.
|
||||||
!MESSAGE OBJDIR is the path where you like to build (obj, bins, etc.),
|
!MESSAGE OBJDIR is the path where you like to build (obj, bins, etc.),
|
||||||
!MESSAGE defaults to ..\obj
|
!MESSAGE defaults to ..\obj
|
||||||
|
|
||||||
|
7
NEWS
7
NEWS
@ -1,3 +1,10 @@
|
|||||||
|
- 3/3/15: version 0.4.3
|
||||||
|
This is a binary compatible release.
|
||||||
|
* Android / gcc / iOS / MSVS build fixes and improvements
|
||||||
|
* lossless decode fix (issue #239 -- since 0.4.0)
|
||||||
|
* documentation / vwebp updates for animation
|
||||||
|
* multi-threading fix (issue #234)
|
||||||
|
|
||||||
- 10/13/14: version 0.4.2
|
- 10/13/14: version 0.4.2
|
||||||
This is a binary compatible release.
|
This is a binary compatible release.
|
||||||
* Android / gcc build fixes
|
* Android / gcc build fixes
|
||||||
|
2
README
2
README
@ -4,7 +4,7 @@
|
|||||||
\__\__/\____/\_____/__/ ____ ___
|
\__\__/\____/\_____/__/ ____ ___
|
||||||
/ _/ / \ \ / _ \/ _/
|
/ _/ / \ \ / _ \/ _/
|
||||||
/ \_/ / / \ \ __/ \__
|
/ \_/ / / \ \ __/ \__
|
||||||
\____/____/\_____/_____/____/v0.4.2
|
\____/____/\_____/_____/____/v0.4.3
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
============
|
============
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libwebp], [0.4.2],
|
AC_INIT([libwebp], [0.4.3],
|
||||||
[http://code.google.com/p/webp/issues],,
|
[http://code.google.com/p/webp/issues],,
|
||||||
[http://developers.google.com/speed/webp])
|
[http://developers.google.com/speed/webp])
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
@ -54,6 +54,7 @@ AC_DEFUN([TEST_AND_ADD_CFLAGS],
|
|||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra])
|
||||||
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat-nonliteral])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat-security])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat-security])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-declarations])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-declarations])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes])
|
||||||
|
@ -46,25 +46,16 @@ for:
|
|||||||
* **Animation.** An image may have multiple frames with pauses between them,
|
* **Animation.** An image may have multiple frames with pauses between them,
|
||||||
making it an animation.
|
making it an animation.
|
||||||
|
|
||||||
* **Image Fragmentation.** A single bitstream in WebP has an inherent
|
|
||||||
limitation for width or height of 2^14 pixels, and, when using VP8, a 512
|
|
||||||
KiB limit on the size of the first compressed partition. To support larger
|
|
||||||
images, the format supports images that are composed of multiple fragments,
|
|
||||||
each encoded as a separate bitstream. All fragments logically form a single
|
|
||||||
image: they have common metadata, color profile, etc. Image fragmentation
|
|
||||||
may also improve efficiency for larger images, e.g., grass can be encoded
|
|
||||||
differently than sky.
|
|
||||||
|
|
||||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||||
document are to be interpreted as described in [RFC 2119][].
|
document are to be interpreted as described in [RFC 2119][].
|
||||||
|
|
||||||
|
Bit numbering in chunk diagrams starts at `0` for the most significant bit
|
||||||
|
('MSB 0') as described in [RFC 1166][].
|
||||||
|
|
||||||
**Note:** Out of the features mentioned above, lossy compression, lossless
|
**Note:** Out of the features mentioned above, lossy compression, lossless
|
||||||
compression, transparency, metadata, color profile and animation are finalized
|
compression, transparency, metadata, color profile and animation are finalized
|
||||||
and are to be considered stable. On the other hand, image fragmentation is
|
and are to be considered stable.
|
||||||
experimental as of now, and is open to discussion, feedback and comments.
|
|
||||||
The same is indicated using annotation "_status: experimental_" in the relevant
|
|
||||||
sections of this document.
|
|
||||||
|
|
||||||
Terminology & Basics
|
Terminology & Basics
|
||||||
------------------------
|
------------------------
|
||||||
@ -79,7 +70,7 @@ Below are additional terms used throughout this document:
|
|||||||
_Reader/Writer_
|
_Reader/Writer_
|
||||||
|
|
||||||
: Code that reads WebP files is referred to as a _reader_, while code that
|
: Code that reads WebP files is referred to as a _reader_, while code that
|
||||||
writes them is referred to as a _writer_.
|
writes them is referred to as a _writer_.
|
||||||
|
|
||||||
_uint16_
|
_uint16_
|
||||||
|
|
||||||
@ -101,10 +92,12 @@ _FourCC_
|
|||||||
_1-based_
|
_1-based_
|
||||||
|
|
||||||
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
|
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
|
||||||
would store value _25_ as _24_.
|
would store value _25_ as _24_.
|
||||||
|
|
||||||
RIFF file format
|
|
||||||
|
RIFF File Format
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The WebP file format is based on the RIFF (resource interchange file format)
|
The WebP file format is based on the RIFF (resource interchange file format)
|
||||||
document format.
|
document format.
|
||||||
|
|
||||||
@ -144,7 +137,8 @@ _ChunkHeader('ABCD')_
|
|||||||
chunks that apply to any RIFF file format, while FourCCs specific to a file
|
chunks that apply to any RIFF file format, while FourCCs specific to a file
|
||||||
format are all lowercase. WebP does not follow this convention.
|
format are all lowercase. WebP does not follow this convention.
|
||||||
|
|
||||||
WebP file header
|
|
||||||
|
WebP File Header
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
0 1 2 3
|
0 1 2 3
|
||||||
@ -164,8 +158,8 @@ WebP file header
|
|||||||
File Size: 32 bits (_uint32_)
|
File Size: 32 bits (_uint32_)
|
||||||
|
|
||||||
: The size of the file in bytes starting at offset 8. The maximum value of
|
: The size of the file in bytes starting at offset 8. The maximum value of
|
||||||
this field is 2^32 minus 10 bytes and thus the size of the whole file is at
|
this field is 2^32 minus 10 bytes and thus the size of the whole file is at
|
||||||
most 4GiB minus 2 bytes.
|
most 4GiB minus 2 bytes.
|
||||||
|
|
||||||
'WEBP': 32 bits
|
'WEBP': 32 bits
|
||||||
|
|
||||||
@ -177,7 +171,8 @@ the 'WEBP' FourCC. The file SHOULD NOT contain anything after it. As the size
|
|||||||
of any chunk is even, the size given by the RIFF header is also even. The
|
of any chunk is even, the size given by the RIFF header is also even. The
|
||||||
contents of individual chunks will be described in the following sections.
|
contents of individual chunks will be described in the following sections.
|
||||||
|
|
||||||
Simple file format (lossy)
|
|
||||||
|
Simple File Format (Lossy)
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
This layout SHOULD be used if the image requires _lossy_ encoding and does not
|
This layout SHOULD be used if the image requires _lossy_ encoding and does not
|
||||||
@ -215,7 +210,8 @@ width and height. That is assumed to be the width and height of the canvas.
|
|||||||
The VP8 specification describes how to decode the image into Y'CbCr
|
The VP8 specification describes how to decode the image into Y'CbCr
|
||||||
format. To convert to RGB, Rec. 601 SHOULD be used.
|
format. To convert to RGB, Rec. 601 SHOULD be used.
|
||||||
|
|
||||||
Simple file format (lossless)
|
|
||||||
|
Simple File Format (Lossless)
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
**Note:** Older readers may not support files using the lossless format.
|
**Note:** Older readers may not support files using the lossless format.
|
||||||
@ -253,7 +249,8 @@ The current specification of the VP8L bitstream can be found at
|
|||||||
contains the VP8L image width and height. That is assumed to be the width
|
contains the VP8L image width and height. That is assumed to be the width
|
||||||
and height of the canvas.
|
and height of the canvas.
|
||||||
|
|
||||||
Extended file format
|
|
||||||
|
Extended File Format
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
**Note:** Older readers may not support files using the extended format.
|
**Note:** Older readers may not support files using the extended format.
|
||||||
@ -278,10 +275,6 @@ For a _still image_, the _image data_ consists of a single frame, whereas for
|
|||||||
an _animated image_, it consists of multiple frames. More details about frames
|
an _animated image_, it consists of multiple frames. More details about frames
|
||||||
can be found in the [Animation](#animation) section.
|
can be found in the [Animation](#animation) section.
|
||||||
|
|
||||||
Moreover, each frame can be fragmented or non-fragmented, as will be described
|
|
||||||
in the [Extended WebP file header](#extended_header) section. More details about
|
|
||||||
fragments can be found in the [Fragments](#fragments) section.
|
|
||||||
|
|
||||||
All chunks SHOULD be placed in the same order as listed above. If a chunk
|
All chunks SHOULD be placed in the same order as listed above. If a chunk
|
||||||
appears in the wrong place, the file is invalid, but readers MAY parse the
|
appears in the wrong place, the file is invalid, but readers MAY parse the
|
||||||
file, ignoring the chunks that come too late.
|
file, ignoring the chunks that come too late.
|
||||||
@ -302,7 +295,7 @@ Extended WebP file header:
|
|||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| ChunkHeader('VP8X') |
|
| ChunkHeader('VP8X') |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|Rsv|I|L|E|X|A|F| Reserved |
|
|Rsv|I|L|E|X|A|R| Reserved |
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
| Canvas Width Minus One | ...
|
| Canvas Width Minus One | ...
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
@ -320,7 +313,7 @@ ICC profile (I): 1 bit
|
|||||||
Alpha (L): 1 bit
|
Alpha (L): 1 bit
|
||||||
|
|
||||||
: Set if any of the frames of the image contain transparency information
|
: Set if any of the frames of the image contain transparency information
|
||||||
("alpha").
|
("alpha").
|
||||||
|
|
||||||
EXIF metadata (E): 1 bit
|
EXIF metadata (E): 1 bit
|
||||||
|
|
||||||
@ -333,11 +326,11 @@ XMP metadata (X): 1 bit
|
|||||||
Animation (A): 1 bit
|
Animation (A): 1 bit
|
||||||
|
|
||||||
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be
|
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be
|
||||||
used to control the animation.
|
used to control the animation.
|
||||||
|
|
||||||
Image Fragmentation (F): 1 bit _\[status: experimental\]_
|
Reserved (R): 1 bit
|
||||||
|
|
||||||
: Set if any of the frames in the image are represented by fragments.
|
: SHOULD be `0`.
|
||||||
|
|
||||||
Reserved: 24 bits
|
Reserved: 24 bits
|
||||||
|
|
||||||
@ -382,9 +375,9 @@ animation.
|
|||||||
Background Color: 32 bits (_uint32_)
|
Background Color: 32 bits (_uint32_)
|
||||||
|
|
||||||
: The default background color of the canvas in \[Blue, Green, Red, Alpha\]
|
: The default background color of the canvas in \[Blue, Green, Red, Alpha\]
|
||||||
byte order. This color MAY be used to fill the unused space on the canvas around
|
byte order. This color MAY be used to fill the unused space on the canvas
|
||||||
the frames, as well as the transparent pixels of the first frame. Background
|
around the frames, as well as the transparent pixels of the first frame.
|
||||||
color is also used when disposal method is `1`.
|
Background color is also used when disposal method is `1`.
|
||||||
|
|
||||||
**Note**:
|
**Note**:
|
||||||
|
|
||||||
@ -394,6 +387,9 @@ color is also used when disposal method is `1`.
|
|||||||
* Viewer applications SHOULD treat the background color value as a hint, and
|
* Viewer applications SHOULD treat the background color value as a hint, and
|
||||||
are not required to use it.
|
are not required to use it.
|
||||||
|
|
||||||
|
* The canvas is cleared at the start of each loop. The background color MAY be
|
||||||
|
used to achieve this.
|
||||||
|
|
||||||
Loop Count: 16 bits (_uint16_)
|
Loop Count: 16 bits (_uint16_)
|
||||||
|
|
||||||
: The number of times to loop the animation. `0` means infinitely.
|
: The number of times to loop the animation. `0` means infinitely.
|
||||||
@ -402,7 +398,6 @@ This chunk MUST appear if the _Animation_ flag in the VP8X chunk is set.
|
|||||||
If the _Animation_ flag is not set and this chunk is present, it
|
If the _Animation_ flag is not set and this chunk is present, it
|
||||||
SHOULD be ignored.
|
SHOULD be ignored.
|
||||||
|
|
||||||
|
|
||||||
ANMF chunk:
|
ANMF chunk:
|
||||||
|
|
||||||
For animated images, this chunk contains information about a _single_ frame.
|
For animated images, this chunk contains information about a _single_ frame.
|
||||||
@ -445,8 +440,8 @@ Frame Height Minus One: 24 bits (_uint24_)
|
|||||||
Frame Duration: 24 bits (_uint24_)
|
Frame Duration: 24 bits (_uint24_)
|
||||||
|
|
||||||
: The time to wait before displaying the next frame, in 1 millisecond units.
|
: The time to wait before displaying the next frame, in 1 millisecond units.
|
||||||
In particular, frame duration of 0 is useful when one wants to update multiple
|
In particular, frame duration of 0 is useful when one wants to update
|
||||||
areas of the canvas at once during the animation.
|
multiple areas of the canvas at once during the animation.
|
||||||
|
|
||||||
Reserved: 6 bits
|
Reserved: 6 bits
|
||||||
|
|
||||||
@ -454,13 +449,13 @@ Reserved: 6 bits
|
|||||||
|
|
||||||
Blending method (B): 1 bit
|
Blending method (B): 1 bit
|
||||||
|
|
||||||
: Indicates how transparent pixels of _the current frame_ are to be blended with
|
: Indicates how transparent pixels of _the current frame_ are to be blended
|
||||||
corresponding pixels of the previous canvas:
|
with corresponding pixels of the previous canvas:
|
||||||
|
|
||||||
* `0`: Use alpha blending. After disposing of the previous frame, render the
|
* `0`: Use alpha blending. After disposing of the previous frame, render the
|
||||||
current frame on the canvas using [alpha-blending](#alpha-blending). If the
|
current frame on the canvas using [alpha-blending](#alpha-blending). If
|
||||||
current frame does not have an alpha channel, assume alpha value of 255,
|
the current frame does not have an alpha channel, assume alpha value of
|
||||||
effectively replacing the rectangle.
|
255, effectively replacing the rectangle.
|
||||||
|
|
||||||
* `1`: Do not blend. After disposing of the previous frame, render the
|
* `1`: Do not blend. After disposing of the previous frame, render the
|
||||||
current frame on the canvas by overwriting the rectangle covered by the
|
current frame on the canvas by overwriting the rectangle covered by the
|
||||||
@ -468,13 +463,13 @@ corresponding pixels of the previous canvas:
|
|||||||
|
|
||||||
Disposal method (D): 1 bit
|
Disposal method (D): 1 bit
|
||||||
|
|
||||||
: Indicates how _the current frame_ is to be treated after it has been displayed
|
: Indicates how _the current frame_ is to be treated after it has been
|
||||||
(before rendering the next frame) on the canvas:
|
displayed (before rendering the next frame) on the canvas:
|
||||||
|
|
||||||
* `0`: Do not dispose. Leave the canvas as is.
|
* `0`: Do not dispose. Leave the canvas as is.
|
||||||
|
|
||||||
* `1`: Dispose to background color. Fill the _rectangle_ on the canvas covered
|
* `1`: Dispose to background color. Fill the _rectangle_ on the canvas
|
||||||
by the _current frame_ with background color specified in the
|
covered by the _current frame_ with background color specified in the
|
||||||
[ANIM chunk](#anim_chunk).
|
[ANIM chunk](#anim_chunk).
|
||||||
|
|
||||||
**Notes**:
|
**Notes**:
|
||||||
@ -506,9 +501,7 @@ Disposal method (D): 1 bit
|
|||||||
|
|
||||||
Frame Data: _Chunk Size_ - `16` bytes
|
Frame Data: _Chunk Size_ - `16` bytes
|
||||||
|
|
||||||
: For a fragmented frame, it consists of multiple [fragment chunks](#fragments).
|
: Consists of:
|
||||||
|
|
||||||
: For a non-fragmented frame, it consists of:
|
|
||||||
|
|
||||||
* An optional [alpha subchunk](#alpha) for the frame.
|
* An optional [alpha subchunk](#alpha) for the frame.
|
||||||
|
|
||||||
@ -519,49 +512,6 @@ Frame Data: _Chunk Size_ - `16` bytes
|
|||||||
**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
|
**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
|
||||||
_padded_ chunks as described by the [RIFF file format](#riff-file-format).
|
_padded_ chunks as described by the [RIFF file format](#riff-file-format).
|
||||||
|
|
||||||
#### Fragments _\[status: experimental\]_
|
|
||||||
|
|
||||||
For images that are represented by fragments, this chunk contains data for
|
|
||||||
a single fragment. If the _Image Fragmentation Flag_ is not set, then this chunk
|
|
||||||
SHOULD NOT be present.
|
|
||||||
|
|
||||||
0 1 2 3
|
|
||||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
| ChunkHeader('FRGM') |
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
| Fragment X | ...
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
... Fragment Y | Fragment Data |
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
|
|
||||||
Fragment X: 24 bits (_uint24_)
|
|
||||||
|
|
||||||
: The X coordinate of the upper left corner of the fragment is `Fragment X * 2`
|
|
||||||
|
|
||||||
Fragment Y: 24 bits (_uint24_)
|
|
||||||
|
|
||||||
: The Y coordinate of the upper left corner of the fragment is `Fragment Y * 2`
|
|
||||||
|
|
||||||
Fragment Data: _Chunk Size_ - `6` bytes
|
|
||||||
|
|
||||||
: It contains:
|
|
||||||
|
|
||||||
* An optional [alpha subchunk](#alpha) for the fragment.
|
|
||||||
* The [bitstream subchunk](#bitstream-vp8vp8l) for the fragment.
|
|
||||||
* An optional list of [unknown chunks](#unknown-chunks).
|
|
||||||
|
|
||||||
Note: The width and height of the fragment is obtained from the bitstream
|
|
||||||
subchunk.
|
|
||||||
|
|
||||||
The fragments of a frame SHOULD have the following properties:
|
|
||||||
|
|
||||||
* They collectively cover the whole frame.
|
|
||||||
|
|
||||||
* No pair of fragments have any overlapping region on the frame.
|
|
||||||
|
|
||||||
* No portion of any fragment should be located outside of the canvas.
|
|
||||||
|
|
||||||
#### Alpha
|
#### Alpha
|
||||||
|
|
||||||
0 1 2 3
|
0 1 2 3
|
||||||
@ -579,8 +529,8 @@ Reserved (Rsv): 2 bits
|
|||||||
Pre-processing (P): 2 bits
|
Pre-processing (P): 2 bits
|
||||||
|
|
||||||
: These INFORMATIVE bits are used to signal the pre-processing that has
|
: These INFORMATIVE bits are used to signal the pre-processing that has
|
||||||
been performed during compression. The decoder can use this information to
|
been performed during compression. The decoder can use this information to
|
||||||
e.g. dither the values or smooth the gradients prior to display.
|
e.g. dither the values or smooth the gradients prior to display.
|
||||||
|
|
||||||
* `0`: no pre-processing
|
* `0`: no pre-processing
|
||||||
* `1`: level reduction
|
* `1`: level reduction
|
||||||
@ -643,8 +593,8 @@ Alpha bitstream: _Chunk Size_ - `1` bytes
|
|||||||
|
|
||||||
: Encoded alpha bitstream.
|
: Encoded alpha bitstream.
|
||||||
|
|
||||||
This optional chunk contains encoded alpha data for this frame/fragment. A
|
This optional chunk contains encoded alpha data for this frame. A frame
|
||||||
frame/fragment containing a 'VP8L' chunk SHOULD NOT contain this chunk.
|
containing a 'VP8L' chunk SHOULD NOT contain this chunk.
|
||||||
|
|
||||||
**Rationale**: The transparency information is already part of the 'VP8L'
|
**Rationale**: The transparency information is already part of the 'VP8L'
|
||||||
chunk.
|
chunk.
|
||||||
@ -675,15 +625,15 @@ compression method is '0') or compressed using the lossless format
|
|||||||
|
|
||||||
#### Bitstream (VP8/VP8L)
|
#### Bitstream (VP8/VP8L)
|
||||||
|
|
||||||
This chunk contains compressed bitstream data for a single frame/fragment.
|
This chunk contains compressed bitstream data for a single frame.
|
||||||
|
|
||||||
A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the
|
A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the
|
||||||
significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using
|
significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using
|
||||||
"VP8L" as its tag.
|
"VP8L" as its tag.
|
||||||
|
|
||||||
The formats of VP8 and VP8L chunks are as described in sections
|
The formats of VP8 and VP8L chunks are as described in sections
|
||||||
[Simple file format (lossy)](#simple-file-format-lossy)
|
[Simple File Format (Lossy)](#simple-file-format-lossy)
|
||||||
and [Simple file format (lossless)](#simple-file-format-lossless) respectively.
|
and [Simple File Format (Lossless)](#simple-file-format-lossless) respectively.
|
||||||
|
|
||||||
#### Color profile
|
#### Color profile
|
||||||
|
|
||||||
@ -731,7 +681,6 @@ EXIF Metadata: _Chunk Size_ bytes
|
|||||||
|
|
||||||
: image metadata in EXIF format.
|
: image metadata in EXIF format.
|
||||||
|
|
||||||
|
|
||||||
XMP chunk:
|
XMP chunk:
|
||||||
|
|
||||||
0 1 2 3
|
0 1 2 3
|
||||||
@ -762,47 +711,17 @@ A file MAY contain unknown chunks:
|
|||||||
|
|
||||||
* At the end of the file as described in [Extended WebP file
|
* At the end of the file as described in [Extended WebP file
|
||||||
header](#extended_header) section.
|
header](#extended_header) section.
|
||||||
* At the end of FRGM and ANMF chunks as described in [Fragments](#fragments)
|
* At the end of ANMF chunks as described in the
|
||||||
and [Animation](#animation) sections.
|
[Animation](#animation) section.
|
||||||
|
|
||||||
Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their
|
Readers SHOULD ignore these chunks. Writers SHOULD preserve them in their
|
||||||
original order (unless they specifically intend to modify these chunks).
|
original order (unless they specifically intend to modify these chunks).
|
||||||
|
|
||||||
### Assembling the Canvas from fragments/frames
|
### Assembling the Canvas from frames
|
||||||
|
|
||||||
Here we provide an overview of how a reader should assemble a canvas in case
|
Here we provide an overview of how a reader should assemble a canvas in the
|
||||||
of a fragmented-image and in case of an animated image. The notation
|
case of an animated image. The notation _VP8X.field_ means the field in the
|
||||||
_VP8X.field_ means the field in the 'VP8X' chunk with the same description.
|
'VP8X' chunk with the same description.
|
||||||
|
|
||||||
Displaying a _fragmented image_ canvas MUST be equivalent to the following
|
|
||||||
pseudocode: _\[status: experimental\]_
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
assert VP8X.flags.hasFragments
|
|
||||||
canvas ← new black image of size VP8X.canvasWidth x VP8X.canvasHeight.
|
|
||||||
frgm_params ← nil
|
|
||||||
for chunk in image_data:
|
|
||||||
assert chunk.tag is "FRGM"
|
|
||||||
frgm_params.fragmentX = Fragment X
|
|
||||||
frgm_params.fragmentY = Fragment Y
|
|
||||||
for subchunk in 'Fragment Data':
|
|
||||||
if subchunk.tag == "ALPH":
|
|
||||||
assert alpha subchunks not found in 'Fragment Data' earlier
|
|
||||||
frgm_params.alpha = alpha_data
|
|
||||||
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
|
|
||||||
assert bitstream subchunks not found in 'Fragment Data' earlier
|
|
||||||
frgm_params.bitstream = bitstream_data
|
|
||||||
frgm_params.fragmentWidth = Width extracted from bitstream subchunk
|
|
||||||
frgm_params.fragmentHeight = Height extracted from bitstream subchunk
|
|
||||||
assert VP8X.canvasWidth >=
|
|
||||||
frgm_params.fragmentX + frgm_params.fragmentWidth
|
|
||||||
assert VP8X.canvasHeight >=
|
|
||||||
frgm_params.fragmentY + frgm_params.fragmentHeight
|
|
||||||
assert fragment has the properties mentioned in "Image Fragments" section.
|
|
||||||
render fragment with frame_params.alpha and frame_params.bitstream on canvas
|
|
||||||
with top-left corner in (frgm_params.fragmentX, frgm_params.fragmentY).
|
|
||||||
canvas contains the decoded canvas.
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Displaying an _animated image_ canvas MUST be equivalent to the following
|
Displaying an _animated image_ canvas MUST be equivalent to the following
|
||||||
pseudocode:
|
pseudocode:
|
||||||
@ -810,28 +729,25 @@ pseudocode:
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
assert VP8X.flags.hasAnimation
|
assert VP8X.flags.hasAnimation
|
||||||
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
|
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
|
||||||
background color ANIM.background_color.
|
background color ANIM.background_color.
|
||||||
loop_count ← ANIM.loopCount
|
loop_count ← ANIM.loopCount
|
||||||
dispose_method ← ANIM.disposeMethod
|
dispose_method ← ANIM.disposeMethod
|
||||||
if loop_count == 0:
|
if loop_count == 0:
|
||||||
loop_count = ∞
|
loop_count = ∞
|
||||||
frame_params ← nil
|
frame_params ← nil
|
||||||
for loop = 0, ..., loop_count - 1
|
assert next chunk in image_data is ANMF
|
||||||
assert next chunk in image_data is ANMF
|
for loop = 0..loop_count - 1
|
||||||
|
clear canvas to ANIM.background_color or application defined color
|
||||||
|
until eof or non-ANMF chunk
|
||||||
frame_params.frameX = Frame X
|
frame_params.frameX = Frame X
|
||||||
frame_params.frameY = Frame Y
|
frame_params.frameY = Frame Y
|
||||||
frame_params.frameWidth = Frame Width Minus One + 1
|
frame_params.frameWidth = Frame Width Minus One + 1
|
||||||
frame_params.frameHeight = Frame Height Minus One + 1
|
frame_params.frameHeight = Frame Height Minus One + 1
|
||||||
frame_params.frameDuration = Frame Duration
|
frame_params.frameDuration = Frame Duration
|
||||||
assert VP8X.canvasWidth >= frame_params.frameX + frame_params.frameWidth
|
frame_right = frame_params.frameX + frame_params.frameWidth
|
||||||
assert VP8X.canvasHeight >= frame_params.frameY + frame_params.frameHeight
|
frame_bottom = frame_params.frameY + frame_params.frameHeight
|
||||||
if VP8X.flags.hasFragments and first subchunk in 'Frame Data' is FRGM
|
assert VP8X.canvasWidth >= frame_right
|
||||||
// Fragmented frame.
|
assert VP8X.canvasHeight >= frame_bottom
|
||||||
frame_params.{bitstream,alpha} = canvas decoded from subchunks in
|
|
||||||
'Frame Data' as per the pseudocode for
|
|
||||||
_fragmented image_ above.
|
|
||||||
else
|
|
||||||
// Non-fragmented frame.
|
|
||||||
for subchunk in 'Frame Data':
|
for subchunk in 'Frame Data':
|
||||||
if subchunk.tag == "ALPH":
|
if subchunk.tag == "ALPH":
|
||||||
assert alpha subchunks not found in 'Frame Data' earlier
|
assert alpha subchunks not found in 'Frame Data' earlier
|
||||||
@ -839,14 +755,15 @@ for loop = 0, ..., loop_count - 1
|
|||||||
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
|
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
|
||||||
assert bitstream subchunks not found in 'Frame Data' earlier
|
assert bitstream subchunks not found in 'Frame Data' earlier
|
||||||
frame_params.bitstream = bitstream_data
|
frame_params.bitstream = bitstream_data
|
||||||
render frame with frame_params.alpha and frame_params.bitstream on canvas
|
render frame with frame_params.alpha and frame_params.bitstream on
|
||||||
with top-left corner in (frame_params.frameX, frame_params.frameY), using
|
canvas with top-left corner at (frame_params.frameX,
|
||||||
dispose method dispose_method.
|
frame_params.frameY), using dispose method dispose_method.
|
||||||
Show the contents of the image for frame_params.frameDuration * 1ms.
|
canvas contains the decoded image.
|
||||||
canvas contains the decoded canvas.
|
Show the contents of the canvas for frame_params.frameDuration * 1ms.
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Example file layouts
|
|
||||||
|
Example File Layouts
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
A lossy encoded image with alpha may look as follows:
|
A lossy encoded image with alpha may look as follows:
|
||||||
@ -878,17 +795,6 @@ RIFF/WEBP
|
|||||||
+- XMP (metadata)
|
+- XMP (metadata)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
A fragmented image may look as follows:
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
RIFF/WEBP
|
|
||||||
+- VP8X (descriptions of features used)
|
|
||||||
+- FRGM (fragment1 parameters + data)
|
|
||||||
+- FRGM (fragment2 parameters + data)
|
|
||||||
+- FRGM (fragment3 parameters + data)
|
|
||||||
+- FRGM (fragment4 parameters + data)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
An animated image with EXIF metadata may look as follows:
|
An animated image with EXIF metadata may look as follows:
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -906,4 +812,5 @@ RIFF/WEBP
|
|||||||
[webpllspec]: https://gerrit.chromium.org/gerrit/gitweb?p=webm/libwebp.git;a=blob;f=doc/webp-lossless-bitstream-spec.txt;hb=master
|
[webpllspec]: https://gerrit.chromium.org/gerrit/gitweb?p=webm/libwebp.git;a=blob;f=doc/webp-lossless-bitstream-spec.txt;hb=master
|
||||||
[iccspec]: http://www.color.org/icc_specs2.xalter
|
[iccspec]: http://www.color.org/icc_specs2.xalter
|
||||||
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
|
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
|
||||||
|
[rfc 1166]: http://tools.ietf.org/html/rfc1166
|
||||||
[rfc 2119]: http://tools.ietf.org/html/rfc2119
|
[rfc 2119]: http://tools.ietf.org/html/rfc2119
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# libexample_util
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
@ -12,6 +15,9 @@ LOCAL_MODULE := example_util
|
|||||||
|
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# cwebp
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
# Note: to enable jpeg/png encoding the sources from AOSP can be used with
|
# Note: to enable jpeg/png encoding the sources from AOSP can be used with
|
||||||
@ -32,6 +38,9 @@ LOCAL_MODULE := cwebp
|
|||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# dwebp
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
@ -44,3 +53,19 @@ LOCAL_STATIC_LIBRARIES := example_util webp
|
|||||||
LOCAL_MODULE := dwebp
|
LOCAL_MODULE := dwebp
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# webpmux
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
webpmux.c \
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
|
||||||
|
LOCAL_STATIC_LIBRARIES := example_util webpmux webp
|
||||||
|
|
||||||
|
LOCAL_MODULE := webpmux_example
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#ifdef WEBP_HAVE_PNG
|
#ifdef WEBP_HAVE_PNG
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
|
#include <setjmp.h> // note: this must be included *after* png.h
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
@ -192,8 +193,8 @@ static int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|||||||
uint8_t* const rgb = buffer->u.RGBA.rgba;
|
uint8_t* const rgb = buffer->u.RGBA.rgba;
|
||||||
const int stride = buffer->u.RGBA.stride;
|
const int stride = buffer->u.RGBA.stride;
|
||||||
const int has_alpha = (buffer->colorspace == MODE_RGBA);
|
const int has_alpha = (buffer->colorspace == MODE_RGBA);
|
||||||
png_structp png;
|
volatile png_structp png;
|
||||||
png_infop info;
|
volatile png_infop info;
|
||||||
png_uint_32 y;
|
png_uint_32 y;
|
||||||
|
|
||||||
png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||||
@ -203,11 +204,11 @@ static int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|||||||
}
|
}
|
||||||
info = png_create_info_struct(png);
|
info = png_create_info_struct(png);
|
||||||
if (info == NULL) {
|
if (info == NULL) {
|
||||||
png_destroy_write_struct(&png, NULL);
|
png_destroy_write_struct((png_structpp)&png, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (setjmp(png_jmpbuf(png))) {
|
if (setjmp(png_jmpbuf(png))) {
|
||||||
png_destroy_write_struct(&png, &info);
|
png_destroy_write_struct((png_structpp)&png, (png_infopp)&info);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
png_init_io(png, out_file);
|
png_init_io(png, out_file);
|
||||||
@ -221,7 +222,7 @@ static int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|||||||
png_write_rows(png, &row, 1);
|
png_write_rows(png, &row, 1);
|
||||||
}
|
}
|
||||||
png_write_end(png, info);
|
png_write_end(png, info);
|
||||||
png_destroy_write_struct(&png, &info);
|
png_destroy_write_struct((png_structpp)&png, (png_infopp)&info);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#else // !HAVE_WINCODEC_H && !WEBP_HAVE_PNG
|
#else // !HAVE_WINCODEC_H && !WEBP_HAVE_PNG
|
||||||
@ -244,10 +245,10 @@ static int WritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha) {
|
|||||||
uint32_t y;
|
uint32_t y;
|
||||||
|
|
||||||
if (alpha) {
|
if (alpha) {
|
||||||
fprintf(fout, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n"
|
fprintf(fout, "P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n"
|
||||||
"TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
|
"TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
|
||||||
} else {
|
} else {
|
||||||
fprintf(fout, "P6\n%d %d\n255\n", width, height);
|
fprintf(fout, "P6\n%u %u\n255\n", width, height);
|
||||||
}
|
}
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) {
|
if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) {
|
||||||
@ -404,7 +405,7 @@ static int WriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
|
|||||||
const int a_stride = buffer->u.YUVA.a_stride;
|
const int a_stride = buffer->u.YUVA.a_stride;
|
||||||
uint32_t y;
|
uint32_t y;
|
||||||
assert(a != NULL);
|
assert(a != NULL);
|
||||||
fprintf(fout, "P5\n%d %d\n255\n", width, height);
|
fprintf(fout, "P5\n%u %u\n255\n", width, height);
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
if (fwrite(a + y * a_stride, width, 1, fout) != 1) {
|
if (fwrite(a + y * a_stride, width, 1, fout) != 1) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -46,18 +46,7 @@
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static int transparent_index; // Index of transparent color in the map.
|
static int transparent_index = -1; // Opaque frame by default.
|
||||||
|
|
||||||
static void ResetFrameInfo(WebPMuxFrameInfo* const info) {
|
|
||||||
WebPDataInit(&info->bitstream);
|
|
||||||
info->x_offset = 0;
|
|
||||||
info->y_offset = 0;
|
|
||||||
info->duration = 0;
|
|
||||||
info->id = WEBP_CHUNK_ANMF;
|
|
||||||
info->dispose_method = WEBP_MUX_DISPOSE_NONE;
|
|
||||||
info->blend_method = WEBP_MUX_BLEND;
|
|
||||||
transparent_index = -1; // Opaque frame by default.
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SanitizeKeyFrameIntervals(size_t* const kmin_ptr,
|
static void SanitizeKeyFrameIntervals(size_t* const kmin_ptr,
|
||||||
size_t* const kmax_ptr) {
|
size_t* const kmax_ptr) {
|
||||||
@ -270,7 +259,8 @@ int main(int argc, const char *argv[]) {
|
|||||||
GifFileType* gif = NULL;
|
GifFileType* gif = NULL;
|
||||||
WebPConfig config;
|
WebPConfig config;
|
||||||
WebPPicture frame;
|
WebPPicture frame;
|
||||||
WebPMuxFrameInfo info;
|
int duration = 0;
|
||||||
|
FrameDisposeMethod orig_dispose = FRAME_DISPOSE_NONE;
|
||||||
WebPMuxAnimParams anim = { WHITE_COLOR, 0 };
|
WebPMuxAnimParams anim = { WHITE_COLOR, 0 };
|
||||||
WebPFrameCache* cache = NULL;
|
WebPFrameCache* cache = NULL;
|
||||||
|
|
||||||
@ -290,14 +280,11 @@ int main(int argc, const char *argv[]) {
|
|||||||
size_t kmax = 0;
|
size_t kmax = 0;
|
||||||
int allow_mixed = 0; // If true, each frame can be lossy or lossless.
|
int allow_mixed = 0; // If true, each frame can be lossy or lossless.
|
||||||
|
|
||||||
ResetFrameInfo(&info);
|
|
||||||
|
|
||||||
if (!WebPConfigInit(&config) || !WebPPictureInit(&frame)) {
|
if (!WebPConfigInit(&config) || !WebPPictureInit(&frame)) {
|
||||||
fprintf(stderr, "Error! Version mismatch!\n");
|
fprintf(stderr, "Error! Version mismatch!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
config.lossless = 1; // Use lossless compression by default.
|
config.lossless = 1; // Use lossless compression by default.
|
||||||
config.image_hint = WEBP_HINT_GRAPH; // always low-color
|
|
||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
Help();
|
Help();
|
||||||
@ -499,7 +486,8 @@ int main(int argc, const char *argv[]) {
|
|||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WebPFrameCacheAddFrame(cache, &config, &gif_rect, &frame, &info)) {
|
if (!WebPFrameCacheAddFrame(cache, &config, &gif_rect, orig_dispose,
|
||||||
|
duration, &frame)) {
|
||||||
fprintf(stderr, "Error! Cannot encode frame as WebP\n");
|
fprintf(stderr, "Error! Cannot encode frame as WebP\n");
|
||||||
fprintf(stderr, "Error code: %d\n", frame.error_code);
|
fprintf(stderr, "Error code: %d\n", frame.error_code);
|
||||||
}
|
}
|
||||||
@ -515,7 +503,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
// In GIF, graphic control extensions are optional for a frame, so we
|
// In GIF, graphic control extensions are optional for a frame, so we
|
||||||
// may not get one before reading the next frame. To handle this case,
|
// may not get one before reading the next frame. To handle this case,
|
||||||
// we reset frame properties to reasonable defaults for the next frame.
|
// we reset frame properties to reasonable defaults for the next frame.
|
||||||
ResetFrameInfo(&info);
|
orig_dispose = FRAME_DISPOSE_NONE;
|
||||||
|
duration = 0;
|
||||||
|
transparent_index = -1; // Opaque frame by default.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EXTENSION_RECORD_TYPE: {
|
case EXTENSION_RECORD_TYPE: {
|
||||||
@ -533,20 +523,19 @@ int main(int argc, const char *argv[]) {
|
|||||||
const int dispose = (flags >> GIF_DISPOSE_SHIFT) & GIF_DISPOSE_MASK;
|
const int dispose = (flags >> GIF_DISPOSE_SHIFT) & GIF_DISPOSE_MASK;
|
||||||
const int delay = data[2] | (data[3] << 8); // In 10 ms units.
|
const int delay = data[2] | (data[3] << 8); // In 10 ms units.
|
||||||
if (data[0] != 4) goto End;
|
if (data[0] != 4) goto End;
|
||||||
info.duration = delay * 10; // Duration is in 1 ms units for WebP.
|
duration = delay * 10; // Duration is in 1 ms units for WebP.
|
||||||
if (dispose == 3) {
|
switch (dispose) {
|
||||||
static int warning_printed = 0;
|
case 3:
|
||||||
if (!warning_printed) {
|
orig_dispose = FRAME_DISPOSE_RESTORE_PREVIOUS;
|
||||||
fprintf(stderr, "WARNING: GIF_DISPOSE_RESTORE unsupported.\n");
|
break;
|
||||||
warning_printed = 1;
|
case 2:
|
||||||
}
|
orig_dispose = FRAME_DISPOSE_BACKGROUND;
|
||||||
// failsafe. TODO(urvang): emulate the correct behaviour by
|
break;
|
||||||
// recoding the whole frame.
|
case 1:
|
||||||
info.dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;
|
case 0:
|
||||||
} else {
|
default:
|
||||||
info.dispose_method =
|
orig_dispose = FRAME_DISPOSE_NONE;
|
||||||
(dispose == 2) ? WEBP_MUX_DISPOSE_BACKGROUND
|
break;
|
||||||
: WEBP_MUX_DISPOSE_NONE;
|
|
||||||
}
|
}
|
||||||
transparent_index = (flags & GIF_TRANSPARENT_MASK) ? data[4] : -1;
|
transparent_index = (flags & GIF_TRANSPARENT_MASK) ? data[4] : -1;
|
||||||
break;
|
break;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,13 @@ extern "C" {
|
|||||||
|
|
||||||
struct WebPPicture;
|
struct WebPPicture;
|
||||||
|
|
||||||
|
// Includes all disposal methods, even the ones not supported by WebP bitstream.
|
||||||
|
typedef enum FrameDisposeMethod {
|
||||||
|
FRAME_DISPOSE_NONE,
|
||||||
|
FRAME_DISPOSE_BACKGROUND,
|
||||||
|
FRAME_DISPOSE_RESTORE_PREVIOUS
|
||||||
|
} FrameDisposeMethod;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int x_offset, y_offset, width, height;
|
int x_offset, y_offset, width, height;
|
||||||
} WebPFrameRect;
|
} WebPFrameRect;
|
||||||
@ -53,15 +60,15 @@ WebPFrameCache* WebPFrameCacheNew(int width, int height,
|
|||||||
// Release all the frame data from 'cache' and free 'cache'.
|
// Release all the frame data from 'cache' and free 'cache'.
|
||||||
void WebPFrameCacheDelete(WebPFrameCache* const cache);
|
void WebPFrameCacheDelete(WebPFrameCache* const cache);
|
||||||
|
|
||||||
// Given an image described by 'frame', 'info' and 'orig_rect', optimize it for
|
// Given an image described by 'frame', 'rect', 'dispose_method' and 'duration',
|
||||||
// WebP, encode it and add it to 'cache'. 'orig_rect' can be NULL.
|
// optimize it for WebP, encode it and add it to 'cache'. 'rect' can be NULL.
|
||||||
// This takes care of frame disposal too, according to 'info->dispose_method'.
|
// This takes care of frame disposal too, according to 'dispose_method'.
|
||||||
// Returns false in case of error (and sets frame->error_code accordingly).
|
// Returns false in case of error (and sets frame->error_code accordingly).
|
||||||
int WebPFrameCacheAddFrame(WebPFrameCache* const cache,
|
int WebPFrameCacheAddFrame(WebPFrameCache* const cache,
|
||||||
const WebPConfig* const config,
|
const WebPConfig* const config,
|
||||||
const WebPFrameRect* const orig_rect,
|
const WebPFrameRect* const rect,
|
||||||
WebPPicture* const frame,
|
FrameDisposeMethod dispose_method, int duration,
|
||||||
WebPMuxFrameInfo* const info);
|
WebPPicture* const frame);
|
||||||
|
|
||||||
// Flush the *ready* frames from cache and add them to 'mux'. If 'verbose' is
|
// Flush the *ready* frames from cache and add them to 'mux'. If 'verbose' is
|
||||||
// true, prints the information about these frames.
|
// true, prints the information about these frames.
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#ifndef WEBP_EXAMPLES_STOPWATCH_H_
|
#ifndef WEBP_EXAMPLES_STOPWATCH_H_
|
||||||
#define WEBP_EXAMPLES_STOPWATCH_H_
|
#define WEBP_EXAMPLES_STOPWATCH_H_
|
||||||
|
|
||||||
|
#include "webp/types.h"
|
||||||
|
|
||||||
#if defined _WIN32 && !defined __GNUC__
|
#if defined _WIN32 && !defined __GNUC__
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
@ -37,6 +39,7 @@ static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
|
|||||||
|
|
||||||
|
|
||||||
#else /* !_WIN32 */
|
#else /* !_WIN32 */
|
||||||
|
#include <string.h> // memcpy
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
typedef struct timeval Stopwatch;
|
typedef struct timeval Stopwatch;
|
||||||
|
@ -42,8 +42,6 @@
|
|||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void Help(void);
|
|
||||||
|
|
||||||
// Unfortunate global variables. Gathered into a struct for comfort.
|
// Unfortunate global variables. Gathered into a struct for comfort.
|
||||||
static struct {
|
static struct {
|
||||||
int has_animation;
|
int has_animation;
|
||||||
@ -82,6 +80,16 @@ static void ClearParams(void) {
|
|||||||
kParams.dmux = NULL;
|
kParams.dmux = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the previous frame to the dimensions of the canvas and has it dispose
|
||||||
|
// to background to cause the canvas to be cleared.
|
||||||
|
static void ClearPreviousFrame(void) {
|
||||||
|
WebPIterator* const prev = &kParams.prev_frame;
|
||||||
|
prev->width = kParams.canvas_width;
|
||||||
|
prev->height = kParams.canvas_height;
|
||||||
|
prev->x_offset = prev->y_offset = 0;
|
||||||
|
prev->dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Color profile handling
|
// Color profile handling
|
||||||
static int ApplyColorProfile(const WebPData* const profile,
|
static int ApplyColorProfile(const WebPData* const profile,
|
||||||
@ -181,6 +189,8 @@ static void decode_callback(int what) {
|
|||||||
if (WebPDemuxGetFrame(kParams.dmux, 1, curr)) {
|
if (WebPDemuxGetFrame(kParams.dmux, 1, curr)) {
|
||||||
--kParams.loop_count;
|
--kParams.loop_count;
|
||||||
kParams.done = (kParams.loop_count == 0);
|
kParams.done = (kParams.loop_count == 0);
|
||||||
|
if (kParams.done) return;
|
||||||
|
ClearPreviousFrame();
|
||||||
} else {
|
} else {
|
||||||
kParams.decoding_error = 1;
|
kParams.decoding_error = 1;
|
||||||
kParams.done = 1;
|
kParams.done = 1;
|
||||||
@ -395,7 +405,6 @@ int main(int argc, char *argv[]) {
|
|||||||
int c;
|
int c;
|
||||||
WebPDecoderConfig* const config = &kParams.config;
|
WebPDecoderConfig* const config = &kParams.config;
|
||||||
WebPIterator* const curr = &kParams.curr_frame;
|
WebPIterator* const curr = &kParams.curr_frame;
|
||||||
WebPIterator* const prev = &kParams.prev_frame;
|
|
||||||
|
|
||||||
if (!WebPInitDecoderConfig(config)) {
|
if (!WebPInitDecoderConfig(config)) {
|
||||||
fprintf(stderr, "Library version mismatch!\n");
|
fprintf(stderr, "Library version mismatch!\n");
|
||||||
@ -486,10 +495,7 @@ int main(int argc, char *argv[]) {
|
|||||||
printf("Canvas: %d x %d\n", kParams.canvas_width, kParams.canvas_height);
|
printf("Canvas: %d x %d\n", kParams.canvas_width, kParams.canvas_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev->width = kParams.canvas_width;
|
ClearPreviousFrame();
|
||||||
prev->height = kParams.canvas_height;
|
|
||||||
prev->x_offset = prev->y_offset = 0;
|
|
||||||
prev->dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;
|
|
||||||
|
|
||||||
memset(&kParams.iccp, 0, sizeof(kParams.iccp));
|
memset(&kParams.iccp, 0, sizeof(kParams.iccp));
|
||||||
kParams.has_color_profile =
|
kParams.has_color_profile =
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "webp/config.h"
|
#include "webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
@ -109,6 +110,7 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
|
|||||||
IFS(IWICBitmapFrameDecode_GetColorContexts(frame,
|
IFS(IWICBitmapFrameDecode_GetColorContexts(frame,
|
||||||
count, color_contexts,
|
count, color_contexts,
|
||||||
&num_color_contexts));
|
&num_color_contexts));
|
||||||
|
assert(FAILED(hr) || num_color_contexts <= count);
|
||||||
for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) {
|
for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) {
|
||||||
WICColorContextType type;
|
WICColorContextType type;
|
||||||
IFS(IWICColorContext_GetType(color_contexts[i], &type));
|
IFS(IWICColorContext_GetType(color_contexts[i], &type));
|
||||||
@ -116,7 +118,7 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
|
|||||||
UINT size;
|
UINT size;
|
||||||
IFS(IWICColorContext_GetProfileBytes(color_contexts[i],
|
IFS(IWICColorContext_GetProfileBytes(color_contexts[i],
|
||||||
0, NULL, &size));
|
0, NULL, &size));
|
||||||
if (size > 0) {
|
if (SUCCEEDED(hr) && size > 0) {
|
||||||
iccp->bytes = (uint8_t*)malloc(size);
|
iccp->bytes = (uint8_t*)malloc(size);
|
||||||
if (iccp->bytes == NULL) {
|
if (iccp->bytes == NULL) {
|
||||||
hr = E_OUTOFMEMORY;
|
hr = E_OUTOFMEMORY;
|
||||||
@ -261,7 +263,7 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format));
|
IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format));
|
||||||
IFS(IWICBitmapDecoder_GetContainerFormat(decoder, &src_container_format));
|
IFS(IWICBitmapDecoder_GetContainerFormat(decoder, &src_container_format));
|
||||||
|
|
||||||
if (keep_alpha) {
|
if (SUCCEEDED(hr) && keep_alpha) {
|
||||||
const GUID** guid;
|
const GUID** guid;
|
||||||
for (guid = kAlphaContainers; *guid != NULL; ++guid) {
|
for (guid = kAlphaContainers; *guid != NULL; ++guid) {
|
||||||
if (IsEqualGUID(MAKE_REFGUID(src_container_format),
|
if (IsEqualGUID(MAKE_REFGUID(src_container_format),
|
||||||
|
@ -26,7 +26,9 @@ readonly OLDPATH=${PATH}
|
|||||||
|
|
||||||
# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support.
|
# Add iPhoneOS-V6 to the list of platforms below if you need armv6 support.
|
||||||
# Note that iPhoneOS-V6 support is not available with the iOS6 SDK.
|
# Note that iPhoneOS-V6 support is not available with the iOS6 SDK.
|
||||||
readonly PLATFORMS="iPhoneSimulator iPhoneOS-V7 iPhoneOS-V7s iPhoneOS-V7-arm64"
|
PLATFORMS="iPhoneSimulator iPhoneSimulator64"
|
||||||
|
PLATFORMS+=" iPhoneOS-V7 iPhoneOS-V7s iPhoneOS-V7-arm64"
|
||||||
|
readonly PLATFORMS
|
||||||
readonly SRCDIR=$(dirname $0)
|
readonly SRCDIR=$(dirname $0)
|
||||||
readonly TOPDIR=$(pwd)
|
readonly TOPDIR=$(pwd)
|
||||||
readonly BUILDDIR="${TOPDIR}/iosbuild"
|
readonly BUILDDIR="${TOPDIR}/iosbuild"
|
||||||
@ -78,6 +80,9 @@ for PLATFORM in ${PLATFORMS}; do
|
|||||||
elif [[ "${PLATFORM}" == "iPhoneOS-V6" ]]; then
|
elif [[ "${PLATFORM}" == "iPhoneOS-V6" ]]; then
|
||||||
PLATFORM="iPhoneOS"
|
PLATFORM="iPhoneOS"
|
||||||
ARCH="armv6"
|
ARCH="armv6"
|
||||||
|
elif [[ "${PLATFORM}" == "iPhoneSimulator64" ]]; then
|
||||||
|
PLATFORM="iPhoneSimulator"
|
||||||
|
ARCH="x86_64"
|
||||||
else
|
else
|
||||||
ARCH="i386"
|
ARCH="i386"
|
||||||
fi
|
fi
|
||||||
|
@ -67,6 +67,8 @@ EXTRA_FLAGS += -Wmissing-prototypes
|
|||||||
EXTRA_FLAGS += -Wmissing-declarations
|
EXTRA_FLAGS += -Wmissing-declarations
|
||||||
EXTRA_FLAGS += -Wdeclaration-after-statement
|
EXTRA_FLAGS += -Wdeclaration-after-statement
|
||||||
EXTRA_FLAGS += -Wshadow
|
EXTRA_FLAGS += -Wshadow
|
||||||
|
EXTRA_FLAGS += -Wformat-security -Wformat-nonliteral
|
||||||
|
|
||||||
# EXTRA_FLAGS += -Wvla
|
# EXTRA_FLAGS += -Wvla
|
||||||
|
|
||||||
# AVX2-specific flags:
|
# AVX2-specific flags:
|
||||||
|
@ -35,7 +35,7 @@ libwebp_la_LIBADD += utils/libwebputils.la
|
|||||||
# other than the ones listed on the command line, i.e., after linking, it will
|
# other than the ones listed on the command line, i.e., after linking, it will
|
||||||
# not have unresolved symbols. Some platforms (Windows among them) require all
|
# not have unresolved symbols. Some platforms (Windows among them) require all
|
||||||
# symbols in shared libraries to be resolved at library creation.
|
# symbols in shared libraries to be resolved at library creation.
|
||||||
libwebp_la_LDFLAGS = -no-undefined -version-info 5:2:0
|
libwebp_la_LDFLAGS = -no-undefined -version-info 5:3:0
|
||||||
libwebpincludedir = $(includedir)/webp
|
libwebpincludedir = $(includedir)/webp
|
||||||
pkgconfig_DATA = libwebp.pc
|
pkgconfig_DATA = libwebp.pc
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ if BUILD_LIBWEBPDECODER
|
|||||||
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
|
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
|
||||||
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
||||||
|
|
||||||
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 1:2:0
|
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 1:3:0
|
||||||
pkgconfig_DATA += libwebpdecoder.pc
|
pkgconfig_DATA += libwebpdecoder.pc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -357,30 +357,33 @@ static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Partition #0
|
// Partition #0
|
||||||
static int CopyParts0Data(WebPIDecoder* const idec) {
|
static VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) {
|
||||||
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
|
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
|
||||||
VP8BitReader* const br = &dec->br_;
|
VP8BitReader* const br = &dec->br_;
|
||||||
const size_t psize = br->buf_end_ - br->buf_;
|
const size_t part_size = br->buf_end_ - br->buf_;
|
||||||
MemBuffer* const mem = &idec->mem_;
|
MemBuffer* const mem = &idec->mem_;
|
||||||
assert(!idec->is_lossless_);
|
assert(!idec->is_lossless_);
|
||||||
assert(mem->part0_buf_ == NULL);
|
assert(mem->part0_buf_ == NULL);
|
||||||
assert(psize > 0);
|
// the following is a format limitation, no need for runtime check:
|
||||||
assert(psize <= mem->part0_size_); // Format limit: no need for runtime check
|
assert(part_size <= mem->part0_size_);
|
||||||
|
if (part_size == 0) { // can't have zero-size partition #0
|
||||||
|
return VP8_STATUS_BITSTREAM_ERROR;
|
||||||
|
}
|
||||||
if (mem->mode_ == MEM_MODE_APPEND) {
|
if (mem->mode_ == MEM_MODE_APPEND) {
|
||||||
// We copy and grab ownership of the partition #0 data.
|
// We copy and grab ownership of the partition #0 data.
|
||||||
uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, psize);
|
uint8_t* const part0_buf = (uint8_t*)WebPSafeMalloc(1ULL, part_size);
|
||||||
if (part0_buf == NULL) {
|
if (part0_buf == NULL) {
|
||||||
return 0;
|
return VP8_STATUS_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
memcpy(part0_buf, br->buf_, psize);
|
memcpy(part0_buf, br->buf_, part_size);
|
||||||
mem->part0_buf_ = part0_buf;
|
mem->part0_buf_ = part0_buf;
|
||||||
br->buf_ = part0_buf;
|
br->buf_ = part0_buf;
|
||||||
br->buf_end_ = part0_buf + psize;
|
br->buf_end_ = part0_buf + part_size;
|
||||||
} else {
|
} else {
|
||||||
// Else: just keep pointers to the partition #0's data in dec_->br_.
|
// Else: just keep pointers to the partition #0's data in dec_->br_.
|
||||||
}
|
}
|
||||||
mem->start_ += psize;
|
mem->start_ += part_size;
|
||||||
return 1;
|
return VP8_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) {
|
static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) {
|
||||||
@ -414,8 +417,10 @@ static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) {
|
|||||||
dec->mt_method_ = VP8GetThreadMethod(params->options, NULL,
|
dec->mt_method_ = VP8GetThreadMethod(params->options, NULL,
|
||||||
io->width, io->height);
|
io->width, io->height);
|
||||||
VP8InitDithering(params->options, dec);
|
VP8InitDithering(params->options, dec);
|
||||||
if (!CopyParts0Data(idec)) {
|
|
||||||
return IDecError(idec, VP8_STATUS_OUT_OF_MEMORY);
|
dec->status_ = CopyParts0Data(idec);
|
||||||
|
if (dec->status_ != VP8_STATUS_OK) {
|
||||||
|
return IDecError(idec, dec->status_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish setting up the decoding parameters. Will call io->setup().
|
// Finish setting up the decoding parameters. Will call io->setup().
|
||||||
|
@ -562,6 +562,7 @@ int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {
|
|||||||
}
|
}
|
||||||
block->non_zero_y_ = 0;
|
block->non_zero_y_ = 0;
|
||||||
block->non_zero_uv_ = 0;
|
block->non_zero_uv_ = 0;
|
||||||
|
block->dither_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dec->filter_type_ > 0) { // store filter info
|
if (dec->filter_type_ > 0) { // store filter info
|
||||||
|
@ -31,7 +31,7 @@ extern "C" {
|
|||||||
// version numbers
|
// version numbers
|
||||||
#define DEC_MAJ_VERSION 0
|
#define DEC_MAJ_VERSION 0
|
||||||
#define DEC_MIN_VERSION 4
|
#define DEC_MIN_VERSION 4
|
||||||
#define DEC_REV_VERSION 2
|
#define DEC_REV_VERSION 3
|
||||||
|
|
||||||
// intra prediction modes
|
// intra prediction modes
|
||||||
enum { B_DC_PRED = 0, // 4x4 modes
|
enum { B_DC_PRED = 0, // 4x4 modes
|
||||||
|
@ -900,7 +900,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
|
|||||||
process_func(dec, row);
|
process_func(dec, row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (src < src_last) {
|
if (src < src_end) {
|
||||||
if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
|
if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
|
||||||
if (color_cache != NULL) {
|
if (color_cache != NULL) {
|
||||||
while (last_cached < src) {
|
while (last_cached < src) {
|
||||||
|
@ -311,7 +311,12 @@ int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
|
|||||||
|
|
||||||
extern void WebPInitAlphaProcessingSSE2(void);
|
extern void WebPInitAlphaProcessingSSE2(void);
|
||||||
|
|
||||||
|
static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used =
|
||||||
|
(VP8CPUInfo)&alpha_processing_last_cpuinfo_used;
|
||||||
|
|
||||||
void WebPInitAlphaProcessing(void) {
|
void WebPInitAlphaProcessing(void) {
|
||||||
|
if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return;
|
||||||
|
|
||||||
WebPMultARGBRow = MultARGBRow;
|
WebPMultARGBRow = MultARGBRow;
|
||||||
WebPMultRow = MultRow;
|
WebPMultRow = MultRow;
|
||||||
WebPApplyAlphaMultiply = ApplyAlphaMultiply;
|
WebPApplyAlphaMultiply = ApplyAlphaMultiply;
|
||||||
@ -326,4 +331,5 @@ void WebPInitAlphaProcessing(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
alpha_processing_last_cpuinfo_used = VP8GetCPUInfo;
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,18 @@ static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
|
|||||||
"cpuid\n"
|
"cpuid\n"
|
||||||
"xchg %%edi, %%ebx\n"
|
"xchg %%edi, %%ebx\n"
|
||||||
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
||||||
: "a"(info_type));
|
: "a"(info_type), "c"(0));
|
||||||
}
|
}
|
||||||
#elif defined(__i386__) || defined(__x86_64__)
|
#elif defined(__i386__) || defined(__x86_64__)
|
||||||
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
|
static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
|
||||||
__asm__ volatile (
|
__asm__ volatile (
|
||||||
"cpuid\n"
|
"cpuid\n"
|
||||||
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
||||||
: "a"(info_type));
|
: "a"(info_type), "c"(0));
|
||||||
}
|
}
|
||||||
#elif 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 GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0
|
||||||
#elif defined(WEBP_MSC_SSE2)
|
#elif defined(WEBP_MSC_SSE2)
|
||||||
#define GetCPUInfo __cpuid
|
#define GetCPUInfo __cpuid
|
||||||
@ -55,7 +57,9 @@ static WEBP_INLINE uint64_t xgetbv(void) {
|
|||||||
: "=a"(eax), "=d"(edx) : "c" (ecx));
|
: "=a"(eax), "=d"(edx) : "c" (ecx));
|
||||||
return ((uint64_t)edx << 32) | eax;
|
return ((uint64_t)edx << 32) | eax;
|
||||||
}
|
}
|
||||||
#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
|
#elif (defined(_M_X64) || defined(_M_IX86)) && \
|
||||||
|
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
|
||||||
|
#include <immintrin.h>
|
||||||
#define xgetbv() _xgetbv(0)
|
#define xgetbv() _xgetbv(0)
|
||||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||||
static WEBP_INLINE uint64_t xgetbv(void) {
|
static WEBP_INLINE uint64_t xgetbv(void) {
|
||||||
|
@ -688,7 +688,12 @@ extern void VP8DspInitSSE2(void);
|
|||||||
extern void VP8DspInitNEON(void);
|
extern void VP8DspInitNEON(void);
|
||||||
extern void VP8DspInitMIPS32(void);
|
extern void VP8DspInitMIPS32(void);
|
||||||
|
|
||||||
|
static volatile VP8CPUInfo dec_last_cpuinfo_used =
|
||||||
|
(VP8CPUInfo)&dec_last_cpuinfo_used;
|
||||||
|
|
||||||
void VP8DspInit(void) {
|
void VP8DspInit(void) {
|
||||||
|
if (dec_last_cpuinfo_used == VP8GetCPUInfo) return;
|
||||||
|
|
||||||
VP8InitClipTables();
|
VP8InitClipTables();
|
||||||
|
|
||||||
VP8TransformWHT = TransformWHT;
|
VP8TransformWHT = TransformWHT;
|
||||||
@ -727,5 +732,5 @@ void VP8DspInit(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
dec_last_cpuinfo_used = VP8GetCPUInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,10 @@ extern "C" {
|
|||||||
#define WEBP_ANDROID_NEON // Android targets that might support NEON
|
#define WEBP_ANDROID_NEON // Android targets that might support NEON
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || defined(__aarch64__)
|
// 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(WEBP_ANDROID_NEON) || \
|
||||||
|
defined(__aarch64__)) && !defined(__native_client__)
|
||||||
#define WEBP_USE_NEON
|
#define WEBP_USE_NEON
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -692,7 +692,12 @@ extern void VP8EncDspInitAVX2(void);
|
|||||||
extern void VP8EncDspInitNEON(void);
|
extern void VP8EncDspInitNEON(void);
|
||||||
extern void VP8EncDspInitMIPS32(void);
|
extern void VP8EncDspInitMIPS32(void);
|
||||||
|
|
||||||
|
static volatile VP8CPUInfo enc_last_cpuinfo_used =
|
||||||
|
(VP8CPUInfo)&enc_last_cpuinfo_used;
|
||||||
|
|
||||||
void VP8EncDspInit(void) {
|
void VP8EncDspInit(void) {
|
||||||
|
if (enc_last_cpuinfo_used == VP8GetCPUInfo) return;
|
||||||
|
|
||||||
VP8DspInit(); // common inverse transforms
|
VP8DspInit(); // common inverse transforms
|
||||||
InitTables();
|
InitTables();
|
||||||
|
|
||||||
@ -737,5 +742,6 @@ void VP8EncDspInit(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
enc_last_cpuinfo_used = VP8GetCPUInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
#include "../enc/vp8enci.h"
|
#include "../enc/vp8enci.h"
|
||||||
#include "../enc/cost.h"
|
#include "../enc/cost.h"
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && defined(__ANDROID__) && LOCAL_GCC_VERSION == 0x409
|
||||||
|
#define WORK_AROUND_GCC
|
||||||
|
#endif
|
||||||
|
|
||||||
static const int kC1 = 20091 + (1 << 16);
|
static const int kC1 = 20091 + (1 << 16);
|
||||||
static const int kC2 = 35468;
|
static const int kC2 = 35468;
|
||||||
|
|
||||||
@ -641,6 +645,7 @@ int VP8GetResidualCostMIPS32(int ctx0, const VP8Residual* const res) {
|
|||||||
GET_SSE_INNER(C, C + 1, C + 2, C + 3) \
|
GET_SSE_INNER(C, C + 1, C + 2, C + 3) \
|
||||||
GET_SSE_INNER(D, D + 1, D + 2, D + 3)
|
GET_SSE_INNER(D, D + 1, D + 2, D + 3)
|
||||||
|
|
||||||
|
#if !defined(WORK_AROUND_GCC)
|
||||||
static int SSE16x16(const uint8_t* a, const uint8_t* b) {
|
static int SSE16x16(const uint8_t* a, const uint8_t* b) {
|
||||||
int count;
|
int count;
|
||||||
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
|
int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
|
||||||
@ -742,6 +747,8 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // WORK_AROUND_GCC
|
||||||
|
|
||||||
#undef GET_SSE_MIPS32
|
#undef GET_SSE_MIPS32
|
||||||
#undef GET_SSE_MIPS32_INNER
|
#undef GET_SSE_MIPS32_INNER
|
||||||
|
|
||||||
@ -759,9 +766,11 @@ void VP8EncDspInitMIPS32(void) {
|
|||||||
VP8TDisto4x4 = Disto4x4;
|
VP8TDisto4x4 = Disto4x4;
|
||||||
VP8TDisto16x16 = Disto16x16;
|
VP8TDisto16x16 = Disto16x16;
|
||||||
VP8FTransform = FTransform;
|
VP8FTransform = FTransform;
|
||||||
|
#if !defined(WORK_AROUND_GCC)
|
||||||
VP8SSE16x16 = SSE16x16;
|
VP8SSE16x16 = SSE16x16;
|
||||||
VP8SSE8x8 = SSE8x8;
|
VP8SSE8x8 = SSE8x8;
|
||||||
VP8SSE16x8 = SSE16x8;
|
VP8SSE16x8 = SSE16x8;
|
||||||
VP8SSE4x4 = SSE4x4;
|
VP8SSE4x4 = SSE4x4;
|
||||||
|
#endif
|
||||||
#endif // WEBP_USE_MIPS32
|
#endif // WEBP_USE_MIPS32
|
||||||
}
|
}
|
||||||
|
@ -1012,8 +1012,10 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16],
|
|||||||
const int16x8_t out0 = Quantize(in, mtx, 0);
|
const int16x8_t out0 = Quantize(in, mtx, 0);
|
||||||
const int16x8_t out1 = Quantize(in, mtx, 8);
|
const int16x8_t out1 = Quantize(in, mtx, 8);
|
||||||
uint8x8x4_t shuffles;
|
uint8x8x4_t shuffles;
|
||||||
// vtbl4_u8 is marked unavailable for iOS arm64, use wider versions there.
|
// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
|
||||||
#if defined(__APPLE__) && defined(__aarch64__)
|
// non-standard versions there.
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__) && \
|
||||||
|
defined(__apple_build_version__) && (__apple_build_version__< 6020037)
|
||||||
uint8x16x2_t all_out;
|
uint8x16x2_t all_out;
|
||||||
INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1));
|
INIT_VECTOR2(all_out, vreinterpretq_u8_s16(out0), vreinterpretq_u8_s16(out1));
|
||||||
INIT_VECTOR4(shuffles,
|
INIT_VECTOR4(shuffles,
|
||||||
|
@ -1590,7 +1590,12 @@ extern void VP8LDspInitSSE2(void);
|
|||||||
extern void VP8LDspInitNEON(void);
|
extern void VP8LDspInitNEON(void);
|
||||||
extern void VP8LDspInitMIPS32(void);
|
extern void VP8LDspInitMIPS32(void);
|
||||||
|
|
||||||
|
static volatile VP8CPUInfo lossless_last_cpuinfo_used =
|
||||||
|
(VP8CPUInfo)&lossless_last_cpuinfo_used;
|
||||||
|
|
||||||
void VP8LDspInit(void) {
|
void VP8LDspInit(void) {
|
||||||
|
if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return;
|
||||||
|
|
||||||
memcpy(VP8LPredictors, kPredictorsC, sizeof(VP8LPredictors));
|
memcpy(VP8LPredictors, kPredictorsC, sizeof(VP8LPredictors));
|
||||||
|
|
||||||
VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C;
|
VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C;
|
||||||
@ -1634,6 +1639,7 @@ void VP8LDspInit(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
lossless_last_cpuinfo_used = VP8GetCPUInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -259,20 +259,45 @@ static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Subtract-Green Transform
|
// Subtract-Green Transform
|
||||||
|
|
||||||
// vtbl? are unavailable in iOS/arm64 builds.
|
// vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use
|
||||||
#if !defined(__aarch64__)
|
// non-standard versions there.
|
||||||
|
#if defined(__APPLE__) && defined(__aarch64__) && \
|
||||||
|
defined(__apple_build_version__) && (__apple_build_version__< 6020037)
|
||||||
|
#define USE_VTBLQ
|
||||||
|
#endif
|
||||||
|
|
||||||
// 255 = byte will be zero'd
|
#ifdef USE_VTBLQ
|
||||||
|
// 255 = byte will be zeroed
|
||||||
|
static const uint8_t kGreenShuffle[16] = {
|
||||||
|
1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255
|
||||||
|
};
|
||||||
|
|
||||||
|
static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
|
||||||
|
const uint8x16_t shuffle) {
|
||||||
|
return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)),
|
||||||
|
vtbl1q_u8(argb, vget_high_u8(shuffle)));
|
||||||
|
}
|
||||||
|
#else // !USE_VTBLQ
|
||||||
|
// 255 = byte will be zeroed
|
||||||
static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 };
|
static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 };
|
||||||
|
|
||||||
|
static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
|
||||||
|
const uint8x8_t shuffle) {
|
||||||
|
return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle),
|
||||||
|
vtbl1_u8(vget_high_u8(argb), shuffle));
|
||||||
|
}
|
||||||
|
#endif // USE_VTBLQ
|
||||||
|
|
||||||
static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
|
static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
|
||||||
const uint32_t* const end = argb_data + (num_pixels & ~3);
|
const uint32_t* const end = argb_data + (num_pixels & ~3);
|
||||||
|
#ifdef USE_VTBLQ
|
||||||
|
const uint8x16_t shuffle = vld1q_u8(kGreenShuffle);
|
||||||
|
#else
|
||||||
const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
|
const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
|
||||||
|
#endif
|
||||||
for (; argb_data < end; argb_data += 4) {
|
for (; argb_data < end; argb_data += 4) {
|
||||||
const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
|
const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
|
||||||
const uint8x16_t greens =
|
const uint8x16_t greens = DoGreenShuffle(argb, shuffle);
|
||||||
vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle),
|
|
||||||
vtbl1_u8(vget_high_u8(argb), shuffle));
|
|
||||||
vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens));
|
vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens));
|
||||||
}
|
}
|
||||||
// fallthrough and finish off with plain-C
|
// fallthrough and finish off with plain-C
|
||||||
@ -281,19 +306,21 @@ static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
|
|||||||
|
|
||||||
static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
|
static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
|
||||||
const uint32_t* const end = argb_data + (num_pixels & ~3);
|
const uint32_t* const end = argb_data + (num_pixels & ~3);
|
||||||
|
#ifdef USE_VTBLQ
|
||||||
|
const uint8x16_t shuffle = vld1q_u8(kGreenShuffle);
|
||||||
|
#else
|
||||||
const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
|
const uint8x8_t shuffle = vld1_u8(kGreenShuffle);
|
||||||
|
#endif
|
||||||
for (; argb_data < end; argb_data += 4) {
|
for (; argb_data < end; argb_data += 4) {
|
||||||
const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
|
const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data);
|
||||||
const uint8x16_t greens =
|
const uint8x16_t greens = DoGreenShuffle(argb, shuffle);
|
||||||
vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle),
|
|
||||||
vtbl1_u8(vget_high_u8(argb), shuffle));
|
|
||||||
vst1q_u8((uint8_t*)argb_data, vaddq_u8(argb, greens));
|
vst1q_u8((uint8_t*)argb_data, vaddq_u8(argb, greens));
|
||||||
}
|
}
|
||||||
// fallthrough and finish off with plain-C
|
// fallthrough and finish off with plain-C
|
||||||
VP8LAddGreenToBlueAndRed_C(argb_data, num_pixels & 3);
|
VP8LAddGreenToBlueAndRed_C(argb_data, num_pixels & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !__aarch64__
|
#undef USE_VTBLQ
|
||||||
|
|
||||||
#endif // USE_INTRINSICS
|
#endif // USE_INTRINSICS
|
||||||
|
|
||||||
@ -320,11 +347,9 @@ void VP8LDspInitNEON(void) {
|
|||||||
VP8LPredictors[12] = Predictor12;
|
VP8LPredictors[12] = Predictor12;
|
||||||
VP8LPredictors[13] = Predictor13;
|
VP8LPredictors[13] = Predictor13;
|
||||||
|
|
||||||
#if !defined(__aarch64__)
|
|
||||||
VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
|
VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
|
||||||
VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
|
VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // WEBP_USE_NEON
|
#endif // WEBP_USE_NEON
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,12 @@ const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = {
|
|||||||
extern void WebPInitUpsamplersSSE2(void);
|
extern void WebPInitUpsamplersSSE2(void);
|
||||||
extern void WebPInitUpsamplersNEON(void);
|
extern void WebPInitUpsamplersNEON(void);
|
||||||
|
|
||||||
|
static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 =
|
||||||
|
(VP8CPUInfo)&upsampling_last_cpuinfo_used2;
|
||||||
|
|
||||||
void WebPInitUpsamplers(void) {
|
void WebPInitUpsamplers(void) {
|
||||||
|
if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return;
|
||||||
|
|
||||||
#ifdef FANCY_UPSAMPLING
|
#ifdef FANCY_UPSAMPLING
|
||||||
WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
|
WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
|
||||||
WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
|
WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
|
||||||
@ -217,6 +222,7 @@ void WebPInitUpsamplers(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif // FANCY_UPSAMPLING
|
#endif // FANCY_UPSAMPLING
|
||||||
|
upsampling_last_cpuinfo_used2 = VP8GetCPUInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -123,7 +123,12 @@ WebPSamplerRowFunc WebPSamplers[MODE_LAST];
|
|||||||
extern void WebPInitSamplersSSE2(void);
|
extern void WebPInitSamplersSSE2(void);
|
||||||
extern void WebPInitSamplersMIPS32(void);
|
extern void WebPInitSamplersMIPS32(void);
|
||||||
|
|
||||||
|
static volatile VP8CPUInfo yuv_last_cpuinfo_used =
|
||||||
|
(VP8CPUInfo)&yuv_last_cpuinfo_used;
|
||||||
|
|
||||||
void WebPInitSamplers(void) {
|
void WebPInitSamplers(void) {
|
||||||
|
if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
|
||||||
|
|
||||||
WebPSamplers[MODE_RGB] = YuvToRgbRow;
|
WebPSamplers[MODE_RGB] = YuvToRgbRow;
|
||||||
WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
|
WebPSamplers[MODE_RGBA] = YuvToRgbaRow;
|
||||||
WebPSamplers[MODE_BGR] = YuvToBgrRow;
|
WebPSamplers[MODE_BGR] = YuvToBgrRow;
|
||||||
@ -149,6 +154,7 @@ void WebPInitSamplers(void) {
|
|||||||
}
|
}
|
||||||
#endif // WEBP_USE_MIPS32
|
#endif // WEBP_USE_MIPS32
|
||||||
}
|
}
|
||||||
|
yuv_last_cpuinfo_used = VP8GetCPUInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -30,7 +30,7 @@ extern "C" {
|
|||||||
// version numbers
|
// version numbers
|
||||||
#define ENC_MAJ_VERSION 0
|
#define ENC_MAJ_VERSION 0
|
||||||
#define ENC_MIN_VERSION 4
|
#define ENC_MIN_VERSION 4
|
||||||
#define ENC_REV_VERSION 2
|
#define ENC_REV_VERSION 3
|
||||||
|
|
||||||
// intra prediction modes
|
// intra prediction modes
|
||||||
enum { B_DC_PRED = 0, // 4x4 modes
|
enum { B_DC_PRED = 0, // 4x4 modes
|
||||||
|
@ -1081,6 +1081,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
|
|||||||
int y;
|
int y;
|
||||||
err = AllocateTransformBuffer(enc, width, height);
|
err = AllocateTransformBuffer(enc, width, height);
|
||||||
if (err != VP8_ENC_OK) goto Error;
|
if (err != VP8_ENC_OK) goto Error;
|
||||||
|
assert(enc->argb_ != NULL);
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
memcpy(enc->argb_ + y * width,
|
memcpy(enc->argb_ + y * width,
|
||||||
picture->argb + y * picture->argb_stride,
|
picture->argb + y * picture->argb_stride,
|
||||||
|
@ -326,7 +326,7 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
|
|||||||
|
|
||||||
if (!config->lossless) {
|
if (!config->lossless) {
|
||||||
VP8Encoder* enc = NULL;
|
VP8Encoder* enc = NULL;
|
||||||
if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
|
if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) {
|
||||||
// Make sure we have YUVA samples.
|
// Make sure we have YUVA samples.
|
||||||
if (config->preprocessing & 4) {
|
if (config->preprocessing & 4) {
|
||||||
#if WEBP_ENCODER_ABI_VERSION > 0x0204
|
#if WEBP_ENCODER_ABI_VERSION > 0x0204
|
||||||
|
@ -156,7 +156,7 @@ static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Advances the read buffer by 4 bytes to make room for reading next 32 bits.
|
// Advances the read buffer by 4 bytes to make room for reading next 32 bits.
|
||||||
// Speed critical, but infrequent part of the code can be non-inligned.
|
// Speed critical, but infrequent part of the code can be non-inlined.
|
||||||
extern void VP8LDoFillBitWindow(VP8LBitReader* const br);
|
extern void VP8LDoFillBitWindow(VP8LBitReader* const br);
|
||||||
static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {
|
static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {
|
||||||
if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br);
|
if (br->bit_pos_ >= VP8L_WBITS) VP8LDoFillBitWindow(br);
|
||||||
|
@ -419,7 +419,9 @@ WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src,
|
|||||||
WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture);
|
WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture);
|
||||||
|
|
||||||
// Rescale a picture to new dimension width x height.
|
// Rescale a picture to new dimension width x height.
|
||||||
// Now gamma correction is applied.
|
// If either 'width' or 'height' (but not both) is 0 the corresponding
|
||||||
|
// dimension will be calculated preserving the aspect ratio.
|
||||||
|
// No gamma correction is applied.
|
||||||
// Returns false in case of error (invalid parameter or insufficient memory).
|
// Returns false in case of error (invalid parameter or insufficient memory).
|
||||||
WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height);
|
WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height);
|
||||||
|
|
||||||
|
@ -18,10 +18,11 @@
|
|||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#ifdef __STRICT_ANSI__
|
#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \
|
||||||
#define WEBP_INLINE
|
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
|
||||||
#else /* __STRICT_ANSI__ */
|
|
||||||
#define WEBP_INLINE inline
|
#define WEBP_INLINE inline
|
||||||
|
#else
|
||||||
|
#define WEBP_INLINE
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
typedef signed char int8_t;
|
typedef signed char int8_t;
|
||||||
|
Reference in New Issue
Block a user