mirror of
https://github.com/webmproject/libwebp.git
synced 2025-04-12 11:56:47 +02:00
Merge branch '0.3.0'
* 0.3.0: (65 commits) Update ChangeLog Cosmetic fixes misc style fix add missing YUVA->ARGB automatic conversion in WebPEncode() Container spec: Clarify frame disposal container doc: add a note about the 'ANMF' payload Container spec: clarify the background color field container doc: move RIFF description to own section libwebp/mux: fix double free use WebPDataCopy() instead of re-coding it. demux: keep a frame tail pointer; used in AddFrame add doc precision about WebPParseHeaders() return codes gif2webp: Bgcolor fix for a special case fix bad saturation order in QuantizeBlock vwebp/animation: fix background dispose Makefile.vc: fix dynamic builds update ChangeLog examples: don't use C99 %zu update ChangeLog update NEWS ... Conflicts: src/webp/format_constants.h Change-Id: Ie659644d3ea5592cde64ec3af90a00cd17838247
This commit is contained in:
commit
df4a406d8d
4
.mailmap
4
.mailmap
@ -1,2 +1,6 @@
|
|||||||
|
<johann.koenig@duck.com> <johannkoenig@google.com>
|
||||||
Mikołaj Zalewski <mikolajz@google.com>
|
Mikołaj Zalewski <mikolajz@google.com>
|
||||||
Pascal Massimino <pascal.massimino@gmail.com>
|
Pascal Massimino <pascal.massimino@gmail.com>
|
||||||
|
Vikas Arora <vikasa@google.com>
|
||||||
|
<vikasa@google.com> <vikasa@gmail.com>
|
||||||
|
<vikasa@google.com> <vikaas.arora@gmail.com>
|
||||||
|
3
AUTHORS
3
AUTHORS
@ -1,9 +1,10 @@
|
|||||||
Contributors:
|
Contributors:
|
||||||
- James Zern (jzern at google dot com)
|
- James Zern (jzern at google dot com)
|
||||||
- Jan Engelhardt (jengelh at medozas dot de)
|
- Jan Engelhardt (jengelh at medozas dot de)
|
||||||
- Johann (johannkoenig at google dot com)
|
- Johann (johann dot koenig at duck dot com)
|
||||||
- Jyrki Alakuijala (jyrki at google dot com)
|
- Jyrki Alakuijala (jyrki at google dot com)
|
||||||
- Lou Quillio (louquillio at google dot com)
|
- Lou Quillio (louquillio at google dot com)
|
||||||
|
- Mans Rullgard (mans at mansr dot com)
|
||||||
- Martin Olsson (mnemo at minimum dot se)
|
- Martin Olsson (mnemo at minimum dot se)
|
||||||
- Mikołaj Zalewski (mikolajz at google dot com)
|
- Mikołaj Zalewski (mikolajz at google dot com)
|
||||||
- Noel Chromium (noel at chromium dot org)
|
- Noel Chromium (noel at chromium dot org)
|
||||||
|
383
ChangeLog
383
ChangeLog
@ -1,3 +1,333 @@
|
|||||||
|
d52b405 Cosmetic fixes
|
||||||
|
6cb4a61 misc style fix
|
||||||
|
68111ab add missing YUVA->ARGB automatic conversion in WebPEncode()
|
||||||
|
403bfe8 Container spec: Clarify frame disposal
|
||||||
|
3e7a13a Merge "Container spec: clarify the background color field" into 0.3.0
|
||||||
|
14af774 container doc: add a note about the 'ANMF' payload
|
||||||
|
cc635ef Container spec: clarify the background color field
|
||||||
|
e3e3394 container doc: move RIFF description to own section
|
||||||
|
4299f39 libwebp/mux: fix double free
|
||||||
|
33f9a69 Merge "demux: keep a frame tail pointer; used in AddFrame" into 0.3.0
|
||||||
|
a2a7b95 use WebPDataCopy() instead of re-coding it.
|
||||||
|
6f18f12 demux: keep a frame tail pointer; used in AddFrame
|
||||||
|
e5af49e add doc precision about WebPParseHeaders() return codes
|
||||||
|
db46daa Merge "Makefile.vc: fix dynamic builds" into 0.3.0
|
||||||
|
53c77af Merge "gif2webp: Bgcolor fix for a special case" into 0.3.0
|
||||||
|
a5ebd14 gif2webp: Bgcolor fix for a special case
|
||||||
|
6378f23 Merge "vwebp/animation: fix background dispose" into 0.3.0
|
||||||
|
3c8eb9a fix bad saturation order in QuantizeBlock
|
||||||
|
04c7a2e vwebp/animation: fix background dispose
|
||||||
|
81a5069 Makefile.vc: fix dynamic builds
|
||||||
|
5f25c39 update ChangeLog
|
||||||
|
14d42af examples: don't use C99 %zu
|
||||||
|
5ccf1fe update ChangeLog
|
||||||
|
2560c24 update NEWS
|
||||||
|
f43bafc Merge changes Iecccb09c,If5ee9fd2,I3e181ce4 into 0.3.0
|
||||||
|
a788644 dwebp: warn when decoding animated webp's
|
||||||
|
302efcd Decode: return more meaningful error for animation
|
||||||
|
ad45273 WebPBitstreamFeatures: add has_animation field
|
||||||
|
783dfa4 disable FRGM decoding for good in libwebpmux
|
||||||
|
4b956be Update ChangeLog
|
||||||
|
ad8b86d update NEWS
|
||||||
|
3e084f6 Merge "demux cosmetics: comments/rename internal function" into 0.3.0
|
||||||
|
d3f8c62 Merge "move WebPFeatureFlags declaration" into 0.3.0
|
||||||
|
7386fe5 Merge "libwebp{demux,mux}: install mux_types.h" into 0.3.0
|
||||||
|
d6cd4e9 Merge "bump decode abi" into 0.3.0
|
||||||
|
17f8da5 bump decode abi
|
||||||
|
97684ae Merge "add doc precision about WebPDemuxPartial()" into 0.3.0
|
||||||
|
f933fd2 move WebPFeatureFlags declaration
|
||||||
|
289bc47 libwebp{demux,mux}: install mux_types.h
|
||||||
|
224e8d4 add doc precision about WebPDemuxPartial()
|
||||||
|
4c18e80 demux cosmetics: comments/rename internal function
|
||||||
|
7cfd1bf update AUTHORS
|
||||||
|
401f7b8 Merge "speed-up lossless (~3%) with ad-hoc histogram cost evaluation" into 0.3.0
|
||||||
|
1fc8ffc Merge "makefile.unix: dist related changes" into 0.3.0
|
||||||
|
8a89c6e Merge changes I466c377f,Ib761ebd3,I694857fc into 0.3.0
|
||||||
|
f4ffb2d speed-up lossless (~3%) with ad-hoc histogram cost evaluation
|
||||||
|
723847d gif2webp: only write error messages to stderr
|
||||||
|
701b9e2 makefile.unix: dist related changes
|
||||||
|
bb85b43 Merge "update NEWS" into 0.3.0
|
||||||
|
59423a2 gif2webp: fix crash on open failure with libgif5
|
||||||
|
9acb17d gif2webp: silence a unused param warning
|
||||||
|
7d9fdc2 Merge "README updates" into 0.3.0
|
||||||
|
5621934 Merge "build: fix install race on shared headers" into 0.3.0
|
||||||
|
70809d8 Merge "bump version to 0.3.0" into 0.3.0
|
||||||
|
d851cd1 demux: make the parse a bit more strict
|
||||||
|
28bb410 update NEWS
|
||||||
|
cef9388 bump version to 0.3.0
|
||||||
|
9048494 build: fix install race on shared headers
|
||||||
|
1e67e8e README updates
|
||||||
|
42b611a Merge "configure: drop experimental from mux/demux" into 0.3.0
|
||||||
|
096a8e3 Merge "vwebp: add color profile support" into 0.3.0
|
||||||
|
ddfee5d vwebp: add color profile support
|
||||||
|
0d6927d Merge "Mark fragment options as experimental in webpmux" into 0.3.0
|
||||||
|
5dbd403 Mark fragment options as experimental in webpmux
|
||||||
|
a0a6648 configure: drop experimental from mux/demux
|
||||||
|
ee65bad Merge "add support for BITS > 32" into 0.3.0
|
||||||
|
744930d add support for BITS > 32
|
||||||
|
7dd288f cwebp: fix build
|
||||||
|
19a8dd0 Merge "Makefile.vc: add vwebp.exe target" into 0.3.0
|
||||||
|
50eedda Merge "examples: normalize icc related program arguments" into 0.3.0
|
||||||
|
757f637 Merge "Makefile.vc: add libwebpdecoder target" into 0.3.0
|
||||||
|
b65c4b7 Makefile.vc: add libwebpdecoder target
|
||||||
|
f8db7b4 Merge "vwebp: replace doubles w/floats where appropriate" into 0.3.0
|
||||||
|
d99aa56 Makefile.vc: add vwebp.exe target
|
||||||
|
013023e vwebp: replace doubles w/floats where appropriate
|
||||||
|
9b3db89 README.mux: add version reference
|
||||||
|
7b6a26c Merge "cwebp: output metadata statistics" into 0.3.0
|
||||||
|
d8dc72a examples: normalize icc related program arguments
|
||||||
|
7bfc905 Merge "make alpha unfilter work in-place" into 0.3.0
|
||||||
|
0037b2d Merge "add LUT-free reference code for YUV->RGB conversion." into 0.3.0
|
||||||
|
166bf74 Merge "demux: disable fragment parsing" into 0.3.0
|
||||||
|
126974b add LUT-free reference code for YUV->RGB conversion.
|
||||||
|
0aef3eb make alpha unfilter work in-place
|
||||||
|
14ef500 Merge "Remove 'status: experimental' from container spec" into 0.3.0
|
||||||
|
d40c98e Merge "webpmux binary: tiny style fix" into 0.3.0
|
||||||
|
0bc4268 cwebp: output metadata statistics
|
||||||
|
bc03980 Merge "autoconf: normalize experimental define" into 0.3.0
|
||||||
|
d1e21b1 Remove 'status: experimental' from container spec
|
||||||
|
7681bb9 webpmux binary: tiny style fix
|
||||||
|
a3dd3d0 avoid installing example_util.h
|
||||||
|
252320e demux: disable fragment parsing
|
||||||
|
537bde0 autoconf: normalize experimental define
|
||||||
|
5e338e0 Merge changes I33e8a613,I8e8a7b44 into 0.3.0
|
||||||
|
d9d0ea1 Merge changes If21e3ec7,I991fc30b into 0.3.0
|
||||||
|
627f5ca automake: add reference to libwebp for mux/demux
|
||||||
|
eef73d0 don't consolidate proba stats too often
|
||||||
|
05ec4cc libwebp{,decoder}.pc: add pthread flags
|
||||||
|
1bfcf5b add libwebpmux.pc
|
||||||
|
26ca843 add libwebpdemux.pc
|
||||||
|
69e2590 Merge "Tune Lossless compression for lower qualities."
|
||||||
|
0478b5d Tune Lossless compression for lower qualities.
|
||||||
|
39f7586 add a mention of parallel alpha encoding in the NEWS
|
||||||
|
5a21d96 Merge "1.5x-2x faster encoding for method 3 and up"
|
||||||
|
9bfbdd1 1.5x-2x faster encoding for method 3 and up
|
||||||
|
27dc741 Correct frame options order in README.mux
|
||||||
|
be2fd17 Mux: fix a scenario with bad ANMF/FRGM size
|
||||||
|
19eb012 Merge "Demux: Add option to get frame count using GetI()"
|
||||||
|
7368b8c Merge "WebPGetFeatures() out of if condition for clarity."
|
||||||
|
f604c9a Merge "fix windows build"
|
||||||
|
153f94e fix windows build
|
||||||
|
847b492 Merge "vwebp: use magenta for 'i'nfo display"
|
||||||
|
25ea46b Merge "vwebp: add keyboard shortcuts to help output"
|
||||||
|
bea7cca vwebp: use magenta for 'i'nfo display
|
||||||
|
8fab161 webpmux: correct -frame param order in help output
|
||||||
|
03cc23d vwebp: add keyboard shortcuts to help output
|
||||||
|
068eba8 Demux: Add option to get frame count using GetI()
|
||||||
|
988b8f5 WebPGetFeatures() out of if condition for clarity.
|
||||||
|
6933d91 Merge "gif2webp: Be lenient about background color index."
|
||||||
|
4d0f7c5 Merge "WebPGetFeatures() behavior change:"
|
||||||
|
fdeeb01 gif2webp: Be lenient about background color index.
|
||||||
|
ad25032 Merge "multi-threaded alpha encoding for lossy"
|
||||||
|
4e32d3e Merge "fix compilation of token.c"
|
||||||
|
f817930 multi-threaded alpha encoding for lossy
|
||||||
|
8805035 fix compilation of token.c
|
||||||
|
fc81621 code using the actual values for num_parts_, not the ones from config
|
||||||
|
7265535 Merge "move the config check from .c to .h"
|
||||||
|
dd9e76f move the config check from .c to .h
|
||||||
|
956b217 WebPGetFeatures() behavior change:
|
||||||
|
df02e4c WebPDemuxGetI behavior change:
|
||||||
|
633c004 Merge "rebalance method tools (-m) for methods [0..4]"
|
||||||
|
58ca6f6 rebalance method tools (-m) for methods [0..4]
|
||||||
|
7648c3c Merge "describe rd-opt levels introduce VP8RDLevel enum"
|
||||||
|
67fb100 Merge "autoconf: enable silent-rules by default"
|
||||||
|
a5042a3 GetVersion() methods for mux and demux
|
||||||
|
5189957 describe rd-opt levels introduce VP8RDLevel enum
|
||||||
|
4e094ac autoconf: enable silent-rules by default
|
||||||
|
b7eaa85 inline VP8LFastLog2() and VP8LFastSLog2 for small values
|
||||||
|
5cf7792 split quant_levels.c into decoder and encoder version
|
||||||
|
e5d3ffe Merge "Update code example in README.mux"
|
||||||
|
ac5a915 Update code example in README.mux
|
||||||
|
38a91e9 Add example code snippet for demux API
|
||||||
|
5f557f3 README.mux: add info about Demux API and vwebp
|
||||||
|
c0ba090 backward_references: avoid signed integer overflow
|
||||||
|
943386d disable SSE2 for now
|
||||||
|
9479fb7 lossless encoding speedup
|
||||||
|
ec2030a merge two lines together
|
||||||
|
b67956c Merge "Remove ReadOneBit() and ReadSymbolUnsafe()"
|
||||||
|
1667bde Remove ReadOneBit() and ReadSymbolUnsafe()
|
||||||
|
3151669 wicdec + dwebp cosmetics: normalize formatting
|
||||||
|
92668da change default filtering parameters: * type is now 'strong' * strength is now '60'
|
||||||
|
b7490f8 introduce WEBP_REFERENCE_IMPLEMENTATION compile option
|
||||||
|
3383885 faster decoding (3%-6%)
|
||||||
|
5c3e381 Merge "add a -jpeg_like option"
|
||||||
|
c231104 remove unused declaration of VP8Zigzag
|
||||||
|
3615295 Merge "wicdec: add alpha support for paletted formats"
|
||||||
|
c9f1649 wicdec: add alpha support for paletted formats
|
||||||
|
1262f81 Merge "wicdec: silence some warnings"
|
||||||
|
e7ea61e wicdec: silence some warnings
|
||||||
|
23c0f35 fix missing intptr_t->int cast for MSVC
|
||||||
|
e895059 add a -jpeg_like option
|
||||||
|
1f803f6 Merge "Tune alpha quality mapping to more reasonable values."
|
||||||
|
1267d49 Tune alpha quality mapping to more reasonable values.
|
||||||
|
043076e Merge "speed-up lossless in BackwardTrace"
|
||||||
|
f3a44dc remove one malloc from TraceBackwards()
|
||||||
|
0fc1a3a speed-up lossless in BackwardTrace
|
||||||
|
7c732e5 cwebp: centralize WebPCleanupTransparentArea()
|
||||||
|
7381254 Merge "wicdec: add ICC profile extraction"
|
||||||
|
e83ff7d wicdec: add ICC profile extraction
|
||||||
|
146c6e3 Merge "cosmetics: pngdec: normalize default label location"
|
||||||
|
a8f549d Merge "manpages: italicize option parameters"
|
||||||
|
e118db8 Merge "encode.h: note the need to free() WebPMemoryWriter"
|
||||||
|
1dfee6d cosmetics: pngdec: normalize default label location
|
||||||
|
14c3820 manpages: italicize option parameters
|
||||||
|
7defbfa encode.h: note the need to free() WebPMemoryWriter
|
||||||
|
88d382a cwebp: cleanup after memory_writer
|
||||||
|
12d6cec fix extra space in dwebp.1 man
|
||||||
|
b01681a Fix for demuxer frame iteration:
|
||||||
|
56c12aa Demuxer creation fix:
|
||||||
|
66c810b add a -yuv option to dwebp (very similar to -pgm)
|
||||||
|
841a3ba Merge "Remove -Wshadow warnings."
|
||||||
|
8fd0252 Merge "upsampling_neon.c: fix build"
|
||||||
|
6efed26 Remove -Wshadow warnings.
|
||||||
|
60904aa Merge "allow WebPINewRGB/YUVA to be passed a NULL output buffer."
|
||||||
|
b7adf37 allow WebPINewRGB/YUVA to be passed a NULL output buffer.
|
||||||
|
27f8f74 upsampling_neon.c: fix build
|
||||||
|
06b9cdf gitignore: add IOS related directories
|
||||||
|
f112221 Merge "Fix more comments for iobuild.sh"
|
||||||
|
fe4d25d Fix more comments for iobuild.sh
|
||||||
|
1de3e25 Merge "NEON optimised yuv to rgb conversion"
|
||||||
|
090b708 NEON optimised yuv to rgb conversion
|
||||||
|
daa0647 Merge "Add ios build script for building iOS library."
|
||||||
|
79fe39e Add ios build script for building iOS library.
|
||||||
|
126c035 remove some more -Wshadow warnings
|
||||||
|
522e9d6 Merge "cwebp: enable '-metadata'"
|
||||||
|
76ec5fa cwebp: enable '-metadata'
|
||||||
|
aeb91a9 Merge "cosmetics: break a few long lines"
|
||||||
|
be7c96b cosmetics: break a few long lines
|
||||||
|
cff8ddb Merge "add libwebpdecoder.pc"
|
||||||
|
93148ab Merge "libwebp.pc.in: detab"
|
||||||
|
6477f95 Merge "Makefile.vc: normalize path separator"
|
||||||
|
bed1ed7 add libwebpdecoder.pc
|
||||||
|
46168b2 libwebp.pc.in: detab
|
||||||
|
a941a34 Fixed few nits in the build files.
|
||||||
|
dd7a49b Makefile.vc: normalize path separator
|
||||||
|
9161be8 Merge "cwebp: extract WIC decoding to its own module"
|
||||||
|
08e7c58 Merge "Provide an option to build decoder library."
|
||||||
|
0aeba52 Provide an option to build decoder library.
|
||||||
|
757ebcb catch malloc(0)/calloc(0) with an assert
|
||||||
|
152ec3d Merge "handle malloc(0) and calloc(0) uniformly on all platforms"
|
||||||
|
a452a55 cwebp: extract WIC decoding to its own module
|
||||||
|
2b252a5 Merge "Provide option to swap bytes for 16 bit colormodes"
|
||||||
|
94a48b4 Provide option to swap bytes for 16 bit colormodes
|
||||||
|
42f8f93 handle malloc(0) and calloc(0) uniformly on all platforms
|
||||||
|
8b2152c Merge "add an extra assert to check memory bounds"
|
||||||
|
0d19fbf remove some -Wshadow warnings
|
||||||
|
cd22f65 add an extra assert to check memory bounds
|
||||||
|
8189fed Merge "Add details and reference about the YUV->RGB conversion"
|
||||||
|
1d2702b Merge "Formatting fixes in lossless bitstream spec"
|
||||||
|
8425aae Formatting fixes in lossless bitstream spec
|
||||||
|
a556cb1 Add details and reference about the YUV->RGB conversion
|
||||||
|
d8f21e0 add link to SSIM description on Wikipedia
|
||||||
|
18e9167 Merge "WebP-lossless spec clarifications:"
|
||||||
|
98e25b9 Merge "cwebp: add -metadata option"
|
||||||
|
f01c2a5 WebP-lossless spec clarifications:
|
||||||
|
f4a9797 Merge "Disto4x4 and Disto16x16 in NEON"
|
||||||
|
47b7b0b Disto4x4 and Disto16x16 in NEON
|
||||||
|
7eaee9f cwebp: add -metadata option
|
||||||
|
36c52c2 tiffdec: use toff_t for exif ifd offset
|
||||||
|
7c8111e Merge "cwebp/tiffdec: add TIFF metadata extraction"
|
||||||
|
e6409ad Remove redundant include from dsp/lossless code.
|
||||||
|
1ab5b3a Merge "configure: fix --with-gifincludedir"
|
||||||
|
03c749e configure: fix --with-gifincludedir
|
||||||
|
8b65063 multiple libgif versions support for gif2webp
|
||||||
|
476e293 gif2webp: Use DGifOpenFileName()
|
||||||
|
b50f277 tiffdec: correct format string
|
||||||
|
2b9048e Merge "tiffdec: check error returns for width/height"
|
||||||
|
a1b5a9a Merge "cwebp/tiff: use the first image directory"
|
||||||
|
079423f tiffdec: check error returns for width/height
|
||||||
|
d62824a Merge "cwebp/jpegdec: add JPEG metadata extraction"
|
||||||
|
03afaca Merge "cwebp: add PNG metadata extraction"
|
||||||
|
2c72496 cwebp/jpegdec: add JPEG metadata extraction
|
||||||
|
dba64d9 cwebp: add PNG metadata extraction
|
||||||
|
1f075f8 Lossless spec corrections/rewording/clarifications
|
||||||
|
2914ecf cwebp/tiffdec: add TIFF metadata extraction
|
||||||
|
d82a3e3 More corrections/clarifications in lossless spec:
|
||||||
|
bd00255 cwebp/tiff: use the first image directory
|
||||||
|
df7aa07 Merge "Cleanup around jpegdec"
|
||||||
|
0f57dcc decoding speed-up (~1%)
|
||||||
|
bcec339 Lossless bitstream clarification:
|
||||||
|
6bf2087 add examples/metadata.c
|
||||||
|
207f89c Merge "configure: add libwebpdemux status to summary"
|
||||||
|
1bd287a Cleanup around jpegdec
|
||||||
|
9145567 Merge "cosmetics: use '== 0' in size checks"
|
||||||
|
d6b88b7 cosmetics: use '== 0' in size checks
|
||||||
|
d3dace2 cosmetics: jpegdec
|
||||||
|
2f69af7 configure: add libwebpdemux status to summary
|
||||||
|
1c1c564 cwebp: extract tiff decoding to its own module
|
||||||
|
6a871d6 cwebp: extract jpeg decoding to its own module
|
||||||
|
2ee228f cwebp: extract png decoding to its own module
|
||||||
|
4679db0 Merge "cwebp: add metadata framework"
|
||||||
|
63aba3a cwebp: add metadata framework
|
||||||
|
931bd51 lossless bitstream: block size bits correction
|
||||||
|
e4fc4c1 lossless bitstream: block size bits correction
|
||||||
|
d65ec67 fix build, move token.c to src/enc/
|
||||||
|
657f5c9 move token buffer to its own file (token.c)
|
||||||
|
c34a375 introduce GetLargeValue() to slim-fast GetCoeffs().
|
||||||
|
d5838cd faster non-transposing SSE2 4x4 FTransform
|
||||||
|
f76191f speed up GetResidualCost()
|
||||||
|
ba2aa0f Add support for BITS=24 case
|
||||||
|
2e7f6e8 makefile.unix: Dependency on libraries
|
||||||
|
dca8421 Merge "Separate out mux and demux code and libraries:"
|
||||||
|
23782f9 Separate out mux and demux code and libraries:
|
||||||
|
bd56a01 configure: add summary output
|
||||||
|
90e5e31 dwebp manual: point to webpmux, gif2webp.
|
||||||
|
540790c gif2webp.c: add a note about prerequisites
|
||||||
|
d1edf69 cwebp man page: meaning of '-q' for lossy/lossless
|
||||||
|
79efa1d Add man page for gif2webp utility
|
||||||
|
2243e40 Merge "gif2webp build support with autoconf tools"
|
||||||
|
c40efca gif2webp build support with autoconf tools
|
||||||
|
6523e2d WebP Container:
|
||||||
|
4da788d Merge "simplify the fwd transform"
|
||||||
|
42c3b55 simplify the fwd transform
|
||||||
|
41a6ced user GLfloat instead of float
|
||||||
|
b542611 fix indentation
|
||||||
|
68f282f * handle offset in anim viewer 'vwebp' * fix gif2webp to handle disposal method and odd offset correctly
|
||||||
|
118cb31 Merge "add SSE2 version of Sum of Square error for 16x16, 16x8 and 8x8 case"
|
||||||
|
8a7c3cc Merge "Change the order of -frame argument to be more natural"
|
||||||
|
99e0a70 Merge "Simplify the texture evaluation Disto4x4()"
|
||||||
|
0f923c3 make the bundling work in a tmp buffer
|
||||||
|
e5c3b3f Simplify the texture evaluation Disto4x4()
|
||||||
|
4860008 Change the order of -frame argument to be more natural
|
||||||
|
35bfd4c add SSE2 version of Sum of Square error for 16x16, 16x8 and 8x8 case
|
||||||
|
a7305c2 Clarification for unknown chunks
|
||||||
|
4c4398e Refine WebP Container Spec wrt unknown chunks.
|
||||||
|
2ca642e Rectify WebPMuxGetFeatures:
|
||||||
|
7caab1d Some cosmetic/comment fixes.
|
||||||
|
60b2651 Merge "Write a GIF to WebP converter based on libgif."
|
||||||
|
c7127a4 Merge "Add NEON version of FTransformWHT"
|
||||||
|
11b2721 Write a GIF to WebP converter based on libgif.
|
||||||
|
e9a15a3 ExUtilWriteFile() to write memory segment to file
|
||||||
|
74356eb Add a simple cleanup step in mux assembly:
|
||||||
|
51bb1e5 mux.h: correct WebPDemuxSelectFragment() prototype
|
||||||
|
22a0fd9 Add NEON version of FTransformWHT
|
||||||
|
fa30c86 Update mux code to match the spec wrt animation
|
||||||
|
d9c5fbe by-pass Analysis pass in case segments=1
|
||||||
|
d2ad445 Merge changes Ibeccffc3,Id1585b16
|
||||||
|
5c8be25 Merge "Chunk fourCCs for XMP/EXIF"
|
||||||
|
a00a3da Use 'frgm' instead of 'tile' in webpmux parameters
|
||||||
|
81b8a74 Design change in ANMF and FRGM chunks:
|
||||||
|
f903cba Chunk fourCCs for XMP/EXIF
|
||||||
|
812933d Tune performance of HistogramCombine
|
||||||
|
52ad197 Animation specification in container spec
|
||||||
|
001b930 Image fragment specification in container spec
|
||||||
|
391f9db Ordering of description of bits in container spec
|
||||||
|
d573577 Metadata specification in container spec
|
||||||
|
1c4609b Merge commit 'v0.2.1'
|
||||||
|
0ca584c Merge "Color profile specification in container spec"
|
||||||
|
e8b41ad add NEON asm version for WHT inverse transform
|
||||||
|
af6f0db Color profile specification in container spec
|
||||||
|
a61a824 Merge "Add NULL check in chunk APIs"
|
||||||
|
0e8b7ee fix WebPPictureView() unassigned strides
|
||||||
|
75e5f17 ARM/NEON: 30% encoding speed-up
|
||||||
|
02b4356 Add NULL check in chunk APIs
|
||||||
|
a077072 mux struct naming
|
||||||
|
6c66dde Merge "Tune Lossless encoder"
|
||||||
|
ab5ea21 Tune Lossless encoder
|
||||||
|
74fefc8 Update ChangeLog (v0.2.1, origin/0.2.0)
|
||||||
|
92f8059 Rename some chunks:
|
||||||
|
3bb4bbe Merge "Mux API change:"
|
||||||
|
d0c79f0 Mux API change:
|
||||||
abc0604 Merge "update NEWS" into 0.2.0
|
abc0604 Merge "update NEWS" into 0.2.0
|
||||||
57cf313 update NEWS
|
57cf313 update NEWS
|
||||||
25f585c bump version to 0.2.1
|
25f585c bump version to 0.2.1
|
||||||
@ -15,6 +345,55 @@ b30add2 EncodeImageInternal: fix uninitialized free
|
|||||||
e5970bd Make *InitSSE2() functions be empty on non-SSE2 platform
|
e5970bd Make *InitSSE2() functions be empty on non-SSE2 platform
|
||||||
ef5cc47 make *InitSSE2() functions be empty on non-SSE2 platform
|
ef5cc47 make *InitSSE2() functions be empty on non-SSE2 platform
|
||||||
c4ea259 make VP8DspInitNEON() public
|
c4ea259 make VP8DspInitNEON() public
|
||||||
|
8344ead Merge "libwebp: validate chunk size in ParseOptionalChunks"
|
||||||
|
4828bb9 Merge "cwebp (windows): fix alpha image import on XP"
|
||||||
|
3076333 libwebp: validate chunk size in ParseOptionalChunks
|
||||||
|
7048189 AccumulateLSIM: fix double -> float warnings
|
||||||
|
eda8ee4 cwebp (windows): fix alpha image import on XP
|
||||||
|
c6e9865 Merge "add EXPERIMENTAL code for YUV-JPEG colorspace"
|
||||||
|
f0360b4 add EXPERIMENTAL code for YUV-JPEG colorspace
|
||||||
|
f86e6ab add LSIM metric to WebPPictureDistortion()
|
||||||
|
c3aa215 Speed up HistogramCombine for lower qualities.
|
||||||
|
1765cb1 Merge "autoconf/libwebp: enable dll builds for mingw"
|
||||||
|
a13562e autoconf/libwebp: enable dll builds for mingw
|
||||||
|
9f469b5 typo: no_fancy -> no_fancy_upsampling
|
||||||
|
1a27f2f Merge "fix double to float conversion warning"
|
||||||
|
cf1e90d Merge "cwebp: fix jpg encodes on XP"
|
||||||
|
f2b5d19 [cd]webp: always output windows errors
|
||||||
|
e855208 fix double to float conversion warning
|
||||||
|
ecd66f7 cwebp: fix jpg encodes on XP
|
||||||
|
7b3eb37 Tune lossless compression to get better gains.
|
||||||
|
ce8bff4 Merge "VP8LAllocateHistogramSet: fix overflow in size calculation"
|
||||||
|
ab5b67a Merge "EncodeImageInternal: fix uninitialized free"
|
||||||
|
7fee5d1 Merge "GetHistoBits: fix integer overflow"
|
||||||
|
a6ae04d VP8LAllocateHistogramSet: fix overflow in size calculation
|
||||||
|
80237c4 GetHistoBits: fix integer overflow
|
||||||
|
8a99723 EncodeImageInternal: fix uninitialized free
|
||||||
|
0b9e682 minor cosmetics
|
||||||
|
a792b91 fix the -g/O3 discrepancy for 32bit compile
|
||||||
|
73ba435 Merge "detect and merge similar segments"
|
||||||
|
fee6627 detect and merge similar segments
|
||||||
|
0c44f41 src/webp/*.h: don't forward declare enums in C++
|
||||||
|
d7a5ac8 vwebp: use demux interface
|
||||||
|
931e0ea Merge "replace 'typedef struct {} X;" by "typedef struct X X; struct X {};""
|
||||||
|
8f216f7 remove cases of equal comparison for qsort()
|
||||||
|
28d25c8 replace 'typedef struct {} X;" by "typedef struct X X; struct X {};"
|
||||||
|
2afee60 speed up for ARM using 8bit for boolean decoder
|
||||||
|
5725cab new segmentation algorithm
|
||||||
|
2cf1f81 Merge "fix the BITS=8 case"
|
||||||
|
12f78ae fix the BITS=8 case
|
||||||
|
6920c71 fix MSVC warnings regarding implicit uint64 to uint32 conversions
|
||||||
|
f6c096a webpmux binary: Rename 'xmp' option to 'meta'
|
||||||
|
ddfe871 webpmux help correction
|
||||||
|
b7c5544 Merge "Make *InitSSE2() functions be empty on non-SSE2 platform"
|
||||||
|
1c04a0d Common APIs for chunks metadata and color profile.
|
||||||
|
2a3117a Merge "Create WebPMuxFrameInfo struct for Mux APIs"
|
||||||
|
5c3a723 Make *InitSSE2() functions be empty on non-SSE2 platform
|
||||||
|
7c6e60f make *InitSSE2() functions be empty on non-SSE2 platform
|
||||||
|
c7eb457 make VP8DspInitNEON() public
|
||||||
|
ab3234a Create WebPMuxFrameInfo struct for Mux APIs
|
||||||
|
e3990fd Alignment fixes
|
||||||
|
e55fbd6 Merge branch '0.2.0'
|
||||||
4238bc0 Update ChangeLog (v0.2.0)
|
4238bc0 Update ChangeLog (v0.2.0)
|
||||||
c655380 dec/io.c: cosmetics
|
c655380 dec/io.c: cosmetics
|
||||||
fe1958f RGBA4444: harmonize lossless/lossy alpha values
|
fe1958f RGBA4444: harmonize lossless/lossy alpha values
|
||||||
@ -135,7 +514,7 @@ f0b5def bump versions
|
|||||||
05108f6 Merge "More spec/code matching in mux:"
|
05108f6 Merge "More spec/code matching in mux:"
|
||||||
6808e69 More spec/code matching in mux:
|
6808e69 More spec/code matching in mux:
|
||||||
bd2b46f Merge "doc/webp-container-spec: light cosmetics"
|
bd2b46f Merge "doc/webp-container-spec: light cosmetics"
|
||||||
20ead32 doc/webp-container-spec: light cosmetics (full)
|
20ead32 doc/webp-container-spec: light cosmetics
|
||||||
1d40a8b configure: add pthread detection
|
1d40a8b configure: add pthread detection
|
||||||
b5e9067 fix some int <-> size_t mix for buffer sizes
|
b5e9067 fix some int <-> size_t mix for buffer sizes
|
||||||
e41a759 build: remove libwebpmux from default targets/config
|
e41a759 build: remove libwebpmux from default targets/config
|
||||||
@ -258,7 +637,7 @@ f8f9408 libwebp: add WebPDemux stub functions
|
|||||||
fb47bb5 Merge "NumNamedElements() should take an enum param."
|
fb47bb5 Merge "NumNamedElements() should take an enum param."
|
||||||
7c68980 Fix asserts in Palette and BackwardReference code.
|
7c68980 Fix asserts in Palette and BackwardReference code.
|
||||||
fbdcb7e NumNamedElements() should take an enum param.
|
fbdcb7e NumNamedElements() should take an enum param.
|
||||||
fb4943b modify WebPParseHeaders to allow reuse by GetFeatures (old-decode-alph-3)
|
fb4943b modify WebPParseHeaders to allow reuse by GetFeatures
|
||||||
3697b5c write an ad-hoc EncodeImageInternal variant
|
3697b5c write an ad-hoc EncodeImageInternal variant
|
||||||
eaee9e7 Bug-Fix: Decode small (less than 32 bytes) images.
|
eaee9e7 Bug-Fix: Decode small (less than 32 bytes) images.
|
||||||
0bceae4 Merge "cwebp: fix alpha reporting in stats output"
|
0bceae4 Merge "cwebp: fix alpha reporting in stats output"
|
||||||
|
45
Makefile.vc
45
Makefile.vc
@ -1,6 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Stem for static libs and DLLs
|
# Stem for static libs and DLLs
|
||||||
#
|
#
|
||||||
|
LIBWEBPDECODER_BASENAME = libwebpdecoder
|
||||||
LIBWEBP_BASENAME = libwebp
|
LIBWEBP_BASENAME = libwebp
|
||||||
LIBWEBPMUX_BASENAME = libwebpmux
|
LIBWEBPMUX_BASENAME = libwebpmux
|
||||||
LIBWEBPDEMUX_BASENAME = libwebpdemux
|
LIBWEBPDEMUX_BASENAME = libwebpdemux
|
||||||
@ -75,6 +76,7 @@ STATICLIBBUILD = TRUE
|
|||||||
CC = $(CCDEBUG)
|
CC = $(CCDEBUG)
|
||||||
RTLIB = $(RTLIBD)
|
RTLIB = $(RTLIBD)
|
||||||
STATICLIBBUILD = TRUE
|
STATICLIBBUILD = TRUE
|
||||||
|
LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
|
||||||
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
|
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
|
||||||
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
|
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
|
||||||
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
||||||
@ -85,6 +87,7 @@ DLLBUILD = TRUE
|
|||||||
CC = $(CCDEBUG)
|
CC = $(CCDEBUG)
|
||||||
RTLIB = $(RTLIBD)
|
RTLIB = $(RTLIBD)
|
||||||
DLLBUILD = TRUE
|
DLLBUILD = TRUE
|
||||||
|
LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
|
||||||
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
|
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
|
||||||
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
|
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
|
||||||
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
||||||
@ -93,17 +96,19 @@ LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
|||||||
!IF "$(STATICLIBBUILD)" == "TRUE"
|
!IF "$(STATICLIBBUILD)" == "TRUE"
|
||||||
CC = $(CC) $(RTLIB)
|
CC = $(CC) $(RTLIB)
|
||||||
CFGSET = TRUE
|
CFGSET = TRUE
|
||||||
|
LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME).lib
|
||||||
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib
|
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib
|
||||||
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME).lib
|
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME).lib
|
||||||
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib
|
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib
|
||||||
!ELSE IF "$(DLLBUILD)" == "TRUE"
|
!ELSE IF "$(DLLBUILD)" == "TRUE"
|
||||||
DLLC = webp_dll.c
|
DLLC = webp_dll.c
|
||||||
DLLINC = webp_dll.h
|
DLLINC = webp_dll.h
|
||||||
|
DLL_OBJS = $(DIROBJ)\$(DLLC:.c=.obj)
|
||||||
CC = $(CC) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL
|
CC = $(CC) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL
|
||||||
|
LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib
|
||||||
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib
|
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib
|
||||||
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib
|
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib
|
||||||
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPMDEMUX_BASENAME)_dll.lib
|
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPMDEMUX_BASENAME)_dll.lib
|
||||||
LIBWEBP_OBJS = $(DIROBJ)\$(DLLC:.c=.obj)
|
|
||||||
LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
|
LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
|
||||||
CFGSET = TRUE
|
CFGSET = TRUE
|
||||||
!ENDIF
|
!ENDIF
|
||||||
@ -160,17 +165,22 @@ DEC_OBJS = \
|
|||||||
DEMUX_OBJS = \
|
DEMUX_OBJS = \
|
||||||
$(DIROBJ)\demux\demux.obj \
|
$(DIROBJ)\demux\demux.obj \
|
||||||
|
|
||||||
DSP_OBJS = \
|
DSP_DEC_OBJS = \
|
||||||
$(DIROBJ)\dsp\cpu.obj \
|
$(DIROBJ)\dsp\cpu.obj \
|
||||||
$(DIROBJ)\dsp\dec.obj \
|
$(DIROBJ)\dsp\dec.obj \
|
||||||
|
$(DIROBJ)\dsp\dec_neon.obj \
|
||||||
$(DIROBJ)\dsp\dec_sse2.obj \
|
$(DIROBJ)\dsp\dec_sse2.obj \
|
||||||
$(DIROBJ)\dsp\enc.obj \
|
|
||||||
$(DIROBJ)\dsp\enc_sse2.obj \
|
|
||||||
$(DIROBJ)\dsp\lossless.obj \
|
$(DIROBJ)\dsp\lossless.obj \
|
||||||
$(DIROBJ)\dsp\upsampling.obj \
|
$(DIROBJ)\dsp\upsampling.obj \
|
||||||
|
$(DIROBJ)\dsp\upsampling_neon.obj \
|
||||||
$(DIROBJ)\dsp\upsampling_sse2.obj \
|
$(DIROBJ)\dsp\upsampling_sse2.obj \
|
||||||
$(DIROBJ)\dsp\yuv.obj \
|
$(DIROBJ)\dsp\yuv.obj \
|
||||||
|
|
||||||
|
DSP_ENC_OBJS = \
|
||||||
|
$(DIROBJ)\dsp\enc.obj \
|
||||||
|
$(DIROBJ)\dsp\enc_neon.obj \
|
||||||
|
$(DIROBJ)\dsp\enc_sse2.obj \
|
||||||
|
|
||||||
EX_FORMAT_DEC_OBJS = \
|
EX_FORMAT_DEC_OBJS = \
|
||||||
$(DIROBJ)\examples\jpegdec.obj \
|
$(DIROBJ)\examples\jpegdec.obj \
|
||||||
$(DIROBJ)\examples\metadata.obj \
|
$(DIROBJ)\examples\metadata.obj \
|
||||||
@ -205,29 +215,35 @@ MUX_OBJS = \
|
|||||||
$(DIROBJ)\mux\muxinternal.obj \
|
$(DIROBJ)\mux\muxinternal.obj \
|
||||||
$(DIROBJ)\mux\muxread.obj \
|
$(DIROBJ)\mux\muxread.obj \
|
||||||
|
|
||||||
UTILS_OBJS = \
|
UTILS_DEC_OBJS = \
|
||||||
$(DIROBJ)\utils\bit_reader.obj \
|
$(DIROBJ)\utils\bit_reader.obj \
|
||||||
$(DIROBJ)\utils\bit_writer.obj \
|
|
||||||
$(DIROBJ)\utils\color_cache.obj \
|
$(DIROBJ)\utils\color_cache.obj \
|
||||||
$(DIROBJ)\utils\filters.obj \
|
$(DIROBJ)\utils\filters.obj \
|
||||||
$(DIROBJ)\utils\huffman.obj \
|
$(DIROBJ)\utils\huffman.obj \
|
||||||
$(DIROBJ)\utils\huffman_encode.obj \
|
|
||||||
$(DIROBJ)\utils\quant_levels.obj \
|
|
||||||
$(DIROBJ)\utils\quant_levels_dec.obj \
|
$(DIROBJ)\utils\quant_levels_dec.obj \
|
||||||
$(DIROBJ)\utils\rescaler.obj \
|
$(DIROBJ)\utils\rescaler.obj \
|
||||||
$(DIROBJ)\utils\thread.obj \
|
$(DIROBJ)\utils\thread.obj \
|
||||||
$(DIROBJ)\utils\utils.obj \
|
$(DIROBJ)\utils\utils.obj \
|
||||||
|
|
||||||
LIBWEBP_OBJS = $(DEC_OBJS) $(DSP_OBJS) $(ENC_OBJS) $(UTILS_OBJS) $(LIBWEBP_OBJS)
|
UTILS_ENC_OBJS = \
|
||||||
|
$(DIROBJ)\utils\bit_writer.obj \
|
||||||
|
$(DIROBJ)\utils\huffman_encode.obj \
|
||||||
|
$(DIROBJ)\utils\quant_levels.obj \
|
||||||
|
|
||||||
|
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
|
||||||
|
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
|
||||||
|
$(UTILS_ENC_OBJS) $(DLL_OBJS)
|
||||||
LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS)
|
LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS)
|
||||||
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) $(LIBWEBPDEMUX_OBJS)
|
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) $(LIBWEBPDEMUX_OBJS)
|
||||||
|
|
||||||
OUT_LIBS = $(LIBWEBP)
|
OUT_LIBS = $(LIBWEBPDECODER) $(LIBWEBP)
|
||||||
OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe
|
OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe
|
||||||
|
|
||||||
all: $(OUT_LIBS) $(OUT_EXAMPLES)
|
all: $(OUT_LIBS) $(OUT_EXAMPLES)
|
||||||
$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(EX_FORMAT_DEC_OBJS)
|
$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(EX_FORMAT_DEC_OBJS)
|
||||||
$(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj
|
$(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj
|
||||||
|
$(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj
|
||||||
|
$(DIRBIN)\vwebp.exe: $(EX_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
|
||||||
$(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX)
|
$(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX)
|
||||||
$(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(LIBWEBP)
|
$(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(LIBWEBP)
|
||||||
$(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP)
|
$(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP)
|
||||||
@ -237,6 +253,7 @@ experimental:
|
|||||||
CFG=$(CFG) \
|
CFG=$(CFG) \
|
||||||
CFLAGS="$(CFLAGS) /DWEBP_EXPERIMENTAL_FEATURES" /$(MAKEFLAGS)
|
CFLAGS="$(CFLAGS) /DWEBP_EXPERIMENTAL_FEATURES" /$(MAKEFLAGS)
|
||||||
|
|
||||||
|
$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS)
|
||||||
$(LIBWEBP): $(LIBWEBP_OBJS)
|
$(LIBWEBP): $(LIBWEBP_OBJS)
|
||||||
$(LIBWEBPMUX): $(LIBWEBPMUX_OBJS)
|
$(LIBWEBPMUX): $(LIBWEBPMUX_OBJS)
|
||||||
$(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS)
|
$(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS)
|
||||||
@ -244,8 +261,8 @@ $(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS)
|
|||||||
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): $(OUTPUT_DIRS)
|
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): $(OUTPUT_DIRS)
|
||||||
|
|
||||||
!IF "$(DLLBUILD)" == "TRUE"
|
!IF "$(DLLBUILD)" == "TRUE"
|
||||||
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS):
|
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): \
|
||||||
$(DIROBJ)\$(DLLINC) $(DIROBJ)\$(DLLC)
|
$(DIROBJ)\$(DLLINC) $(DIROBJ)\$(DLLC)
|
||||||
|
|
||||||
{$(DIROBJ)}.c{$(DIROBJ)}.obj:
|
{$(DIROBJ)}.c{$(DIROBJ)}.obj:
|
||||||
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
|
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
|
||||||
@ -253,14 +270,14 @@ $(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS):
|
|||||||
$(LIBWEBPMUX): $(LIBWEBP)
|
$(LIBWEBPMUX): $(LIBWEBP)
|
||||||
$(LIBWEBPDEMUX): $(LIBWEBP)
|
$(LIBWEBPDEMUX): $(LIBWEBP)
|
||||||
|
|
||||||
$(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
||||||
$(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $**
|
$(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $**
|
||||||
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
|
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
|
||||||
|
|
||||||
clean::
|
clean::
|
||||||
@-erase /s $(DIROBJ)\$(DLLC) $(DIROBJ)\$(DLLINC) 2> NUL
|
@-erase /s $(DIROBJ)\$(DLLC) $(DIROBJ)\$(DLLINC) 2> NUL
|
||||||
!ELSE
|
!ELSE
|
||||||
$(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
||||||
$(LNKLIB) /out:$@ $(LFLAGS) $**
|
$(LNKLIB) /out:$@ $(LFLAGS) $**
|
||||||
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
|
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
10
NEWS
10
NEWS
@ -1,9 +1,17 @@
|
|||||||
- next version:
|
- 3/20/13: version 0.3.0
|
||||||
|
This is a binary compatible release.
|
||||||
* WebPINewRGB/WebPINewYUVA accept being passed a NULL output buffer
|
* WebPINewRGB/WebPINewYUVA accept being passed a NULL output buffer
|
||||||
and will perform auto-allocation.
|
and will perform auto-allocation.
|
||||||
* default filter option is now '-strong -f 60'
|
* default filter option is now '-strong -f 60'
|
||||||
* encoding speed-up for lossy methods 3 to 6
|
* encoding speed-up for lossy methods 3 to 6
|
||||||
* alpha encoding can be done in parallel to lossy using 'cwebp -mt ...'
|
* alpha encoding can be done in parallel to lossy using 'cwebp -mt ...'
|
||||||
|
* color profile, metadata (XMP/EXIF) and animation support finalized in the
|
||||||
|
container.
|
||||||
|
* various NEON assembly additions
|
||||||
|
Tool updates / additions:
|
||||||
|
* gif2webp added
|
||||||
|
* vwebp given color profile & animation support
|
||||||
|
* cwebp can preserve color profile / metadata with '-metadata'
|
||||||
|
|
||||||
- 10/30/12: version 0.2.1
|
- 10/30/12: version 0.2.1
|
||||||
* Various security related fixes
|
* Various security related fixes
|
||||||
|
62
README
62
README
@ -4,7 +4,7 @@
|
|||||||
\__\__/\____/\_____/__/ ____ ___
|
\__\__/\____/\_____/__/ ____ ___
|
||||||
/ _/ / \ \ / _ \/ _/
|
/ _/ / \ \ / _ \/ _/
|
||||||
/ \_/ / / \ \ __/ \__
|
/ \_/ / / \ \ __/ \__
|
||||||
\____/____/\_____/_____/____/v0.2.1
|
\____/____/\_____/_____/____/v0.3.0
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
============
|
============
|
||||||
@ -49,7 +49,7 @@ will build the binaries examples/cwebp and examples/dwebp, along
|
|||||||
with the static library src/libwebp.a. No system-wide installation
|
with the static library src/libwebp.a. No system-wide installation
|
||||||
is supplied, as this is a simple alternative to the full installation
|
is supplied, as this is a simple alternative to the full installation
|
||||||
system based on the autoconf tools (see below).
|
system based on the autoconf tools (see below).
|
||||||
Please refer to the makefile.unix for additional details and customizations.
|
Please refer to makefile.unix for additional details and customizations.
|
||||||
|
|
||||||
Using autoconf tools:
|
Using autoconf tools:
|
||||||
---------------------
|
---------------------
|
||||||
@ -71,10 +71,11 @@ should be all you need to have the following files
|
|||||||
|
|
||||||
installed.
|
installed.
|
||||||
|
|
||||||
Note: The encoding and decoding libraries are compiled separately
|
Note: A decode-only library, libwebpdecoder, is available using the
|
||||||
(as src/dec/libwebpdecode.* and src/dec/libwebpencode.*). They
|
'--enable-libwebpdecoder' flag. The encode library is built separately and can
|
||||||
can be installed independently using a minor modification in the
|
be installed independently using a minor modification in the corresponding
|
||||||
corresponding Makefile.am configure files (see comments there).
|
Makefile.am configure files (see comments there). See './configure --help' for
|
||||||
|
more options.
|
||||||
|
|
||||||
SWIG bindings:
|
SWIG bindings:
|
||||||
--------------
|
--------------
|
||||||
@ -176,7 +177,7 @@ options:
|
|||||||
|
|
||||||
-metadata <string> ..... comma separated list of metadata to
|
-metadata <string> ..... comma separated list of metadata to
|
||||||
copy from the input to the output if present.
|
copy from the input to the output if present.
|
||||||
Valid values: all, none (default), exif, iccp, xmp
|
Valid values: all, none (default), exif, icc, xmp
|
||||||
|
|
||||||
-short ................. condense printed message
|
-short ................. condense printed message
|
||||||
-quiet ................. don't print anything.
|
-quiet ................. don't print anything.
|
||||||
@ -263,12 +264,51 @@ Visualization tool:
|
|||||||
|
|
||||||
There's a little self-serve visualization tool called 'vwebp' under the
|
There's a little self-serve visualization tool called 'vwebp' under the
|
||||||
examples/ directory. It uses OpenGL to open a simple drawing window and show
|
examples/ directory. It uses OpenGL to open a simple drawing window and show
|
||||||
a decoded WebP file. It's not yet integrated in the automake or makefile.unix
|
a decoded WebP file. It's not yet integrated in the automake build system, but
|
||||||
build system, but you can try to manually compile it using the recommendations
|
you can try to manually compile it using the recommendations below.
|
||||||
at the top of the source file.
|
|
||||||
|
|
||||||
Usage: 'vwebp my_picture.webp'
|
Usage: vwebp in_file [options]
|
||||||
|
|
||||||
|
Decodes the WebP image file and visualize it using OpenGL
|
||||||
|
Options are:
|
||||||
|
-version .... print version number and exit.
|
||||||
|
-noicc ....... don't use the icc profile if present.
|
||||||
|
-nofancy ..... don't use the fancy YUV420 upscaler.
|
||||||
|
-nofilter .... disable in-loop filtering.
|
||||||
|
-mt .......... use multi-threading.
|
||||||
|
-info ........ print info.
|
||||||
|
-h ....... this help message.
|
||||||
|
|
||||||
|
Keyboard shortcuts:
|
||||||
|
'c' ................ toggle use of color profile.
|
||||||
|
'i' ................ overlay file information.
|
||||||
|
'q' / 'Q' / ESC .... quit.
|
||||||
|
|
||||||
|
Building:
|
||||||
|
---------
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
1) OpenGL & OpenGL Utility Toolkit (GLUT)
|
||||||
|
Linux:
|
||||||
|
$ sudo apt-get install freeglut3-dev mesa-common-dev
|
||||||
|
Mac + XCode:
|
||||||
|
- These libraries should be available in the OpenGL / GLUT frameworks.
|
||||||
|
Windows:
|
||||||
|
http://freeglut.sourceforge.net/index.php#download
|
||||||
|
|
||||||
|
2) (Optional) qcms (Quick Color Management System)
|
||||||
|
i. Download qcms from Mozilla / Chromium:
|
||||||
|
http://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms
|
||||||
|
http://src.chromium.org/viewvc/chrome/trunk/src/third_party/qcms
|
||||||
|
ii. Build and archive the source files as libqcms.a / qcms.lib
|
||||||
|
iii. Update makefile.unix / Makefile.vc
|
||||||
|
a) Define WEBP_HAVE_QCMS
|
||||||
|
b) Update include / library paths to reference the qcms directory.
|
||||||
|
|
||||||
|
Build using makefile.unix / Makefile.vc:
|
||||||
|
$ make -f makefile.unix examples/vwebp
|
||||||
|
> nmake /f Makefile.vc CFG=release-static \
|
||||||
|
../obj/x64/release-static/bin/vwebp.exe
|
||||||
|
|
||||||
Encoding API:
|
Encoding API:
|
||||||
=============
|
=============
|
||||||
|
47
README.mux
47
README.mux
@ -1,7 +1,7 @@
|
|||||||
__ __ ____ ____ ____ __ __ _ __ __
|
__ __ ____ ____ ____ __ __ _ __ __
|
||||||
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
|
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
|
||||||
\ / __/ _ \ __/ / / (_/ /__
|
\ / __/ _ \ __/ / / (_/ /__
|
||||||
\__\__/\_____/_____/__/ \__//_/\_____/__/___/
|
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.1.0
|
||||||
|
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
@ -9,9 +9,9 @@ Description:
|
|||||||
|
|
||||||
WebPMux: set of two libraries 'Mux' and 'Demux' for creation, extraction and
|
WebPMux: set of two libraries 'Mux' and 'Demux' for creation, extraction and
|
||||||
manipulation of an extended format WebP file, which can have features like
|
manipulation of an extended format WebP file, which can have features like
|
||||||
color profile, metadata, animation and fragmented images. Reference
|
color profile, metadata and animation. Reference command-line tools 'webpmux'
|
||||||
command-line tools 'webpmux' and 'vwebp' as well as the WebP container
|
and 'vwebp' as well as the WebP container specification
|
||||||
specification 'doc/webp-container-spec.txt' are also provided in this package.
|
'doc/webp-container-spec.txt' are also provided in this package.
|
||||||
|
|
||||||
WebP Mux tool:
|
WebP Mux tool:
|
||||||
==============
|
==============
|
||||||
@ -26,7 +26,6 @@ A list of options is available using the -help command line flag:
|
|||||||
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
|
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
|
||||||
webpmux -set SET_OPTIONS INPUT -o OUTPUT
|
webpmux -set SET_OPTIONS INPUT -o OUTPUT
|
||||||
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
|
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
|
||||||
webpmux -frgm FRAGMENT_OPTIONS [-frgm...] -o OUTPUT
|
|
||||||
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
|
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
|
||||||
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
|
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
|
||||||
webpmux -info INPUT
|
webpmux -info INPUT
|
||||||
@ -38,7 +37,6 @@ GET_OPTIONS:
|
|||||||
icc Get ICC profile.
|
icc Get ICC profile.
|
||||||
exif Get EXIF metadata.
|
exif Get EXIF metadata.
|
||||||
xmp Get XMP metadata.
|
xmp Get XMP metadata.
|
||||||
frgm n Get nth fragment.
|
|
||||||
frame n Get nth frame.
|
frame n Get nth frame.
|
||||||
|
|
||||||
SET_OPTIONS:
|
SET_OPTIONS:
|
||||||
@ -47,7 +45,7 @@ SET_OPTIONS:
|
|||||||
exif file.exif Set EXIF metadata.
|
exif file.exif Set EXIF metadata.
|
||||||
xmp file.xmp Set XMP metadata.
|
xmp file.xmp Set XMP metadata.
|
||||||
where: 'file.icc' contains the ICC profile to be set,
|
where: 'file.icc' contains the ICC profile to be set,
|
||||||
'file.exif' contains the EXIF metadata to be set and
|
'file.exif' contains the EXIF metadata to be set
|
||||||
'file.xmp' contains the XMP metadata to be set
|
'file.xmp' contains the XMP metadata to be set
|
||||||
|
|
||||||
STRIP_OPTIONS:
|
STRIP_OPTIONS:
|
||||||
@ -56,12 +54,6 @@ STRIP_OPTIONS:
|
|||||||
exif Strip EXIF metadata.
|
exif Strip EXIF metadata.
|
||||||
xmp Strip XMP metadata.
|
xmp Strip XMP metadata.
|
||||||
|
|
||||||
FRAGMENT_OPTIONS(i):
|
|
||||||
Create fragmented image.
|
|
||||||
file_i +xi+yi
|
|
||||||
where: 'file_i' is the i'th fragment (WebP format),
|
|
||||||
'xi','yi' specify the image offset for this fragment.
|
|
||||||
|
|
||||||
FRAME_OPTIONS(i):
|
FRAME_OPTIONS(i):
|
||||||
Create animation.
|
Create animation.
|
||||||
file_i +di+xi+yi+mi
|
file_i +di+xi+yi+mi
|
||||||
@ -86,29 +78,18 @@ INPUT & OUTPUT are in WebP format.
|
|||||||
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
|
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
|
||||||
valid.
|
valid.
|
||||||
|
|
||||||
WebP viewer tool:
|
Visualization tool:
|
||||||
================
|
===================
|
||||||
|
|
||||||
The examples/ directory also contains a tool (vwebp) for viewing WebP files.
|
The examples/ directory also contains a tool (vwebp) for viewing WebP files.
|
||||||
It decodes the image and visualizes it using OpenGL.
|
It decodes the image and visualizes it using OpenGL. See the libwebp README
|
||||||
|
for details on building and running this program.
|
||||||
A list of options is available using the -h command line flag:
|
|
||||||
|
|
||||||
> vwebp -h
|
|
||||||
Decodes the WebP image file and visualize it using OpenGL
|
|
||||||
Options are:
|
|
||||||
-version .... print version number and exit.
|
|
||||||
-nofancy ..... don't use the fancy YUV420 upscaler.
|
|
||||||
-nofilter .... disable in-loop filtering.
|
|
||||||
-mt .......... use multi-threading
|
|
||||||
-info ........ print info.
|
|
||||||
-h ....... this help message.
|
|
||||||
|
|
||||||
Mux API:
|
Mux API:
|
||||||
========
|
========
|
||||||
The Mux API contains methods for adding data to and reading data from WebP
|
The Mux API contains methods for adding data to and reading data from WebP
|
||||||
files. This API currently supports XMP/EXIF metadata, ICC profile, animation
|
files. This API currently supports XMP/EXIF metadata, ICC profile and animation.
|
||||||
and fragmented images. Other features may be added in subsequent releases.
|
Other features may be added in subsequent releases.
|
||||||
|
|
||||||
Example#1 (pseudo code): Creating a WebPMux object with image data, color
|
Example#1 (pseudo code): Creating a WebPMux object with image data, color
|
||||||
profile and XMP metadata.
|
profile and XMP metadata.
|
||||||
@ -145,11 +126,11 @@ For a detailed Mux API reference, please refer to the header file
|
|||||||
(src/webp/mux.h).
|
(src/webp/mux.h).
|
||||||
|
|
||||||
Demux API:
|
Demux API:
|
||||||
=========
|
==========
|
||||||
The Demux API enables extraction of images and extended format data from
|
The Demux API enables extraction of images and extended format data from
|
||||||
WebP files. This API currently supports reading of XMP/EXIF metadata, ICC
|
WebP files. This API currently supports reading of XMP/EXIF metadata, ICC
|
||||||
profile, animation and fragmented images. Other features may be added in
|
profile and animated images. Other features may be added in subsequent
|
||||||
subsequent releases.
|
releases.
|
||||||
|
|
||||||
Code Example: Demuxing WebP data to extract all the frames, ICC profile
|
Code Example: Demuxing WebP data to extract all the frames, ICC profile
|
||||||
and EXIF/XMP metadata.
|
and EXIF/XMP metadata.
|
||||||
|
33
configure.ac
33
configure.ac
@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libwebp], [0.2.1],
|
AC_INIT([libwebp], [0.3.0],
|
||||||
[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_TARGET
|
AC_CANONICAL_TARGET
|
||||||
@ -176,7 +176,7 @@ CPPFLAGS=$SAVED_CPPFLAGS
|
|||||||
LIBS=$SAVED_LIBS
|
LIBS=$SAVED_LIBS
|
||||||
|
|
||||||
if test "$gif_support" = "yes" -a \
|
if test "$gif_support" = "yes" -a \
|
||||||
"$enable_experimental_libwebpmux" = "yes"; then
|
"$enable_libwebpmux" = "yes"; then
|
||||||
build_gif2webp=yes
|
build_gif2webp=yes
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"])
|
AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"])
|
||||||
@ -244,27 +244,27 @@ AC_MSG_CHECKING(if --enable-experimental option is specified)
|
|||||||
AC_ARG_ENABLE([experimental], AS_HELP_STRING([--enable-experimental],
|
AC_ARG_ENABLE([experimental], AS_HELP_STRING([--enable-experimental],
|
||||||
[Activate experimental features]))
|
[Activate experimental features]))
|
||||||
if test "$enable_experimental" = "yes"; then
|
if test "$enable_experimental" = "yes"; then
|
||||||
AC_DEFINE(EXPERIMENTAL,,[Enable experimental code])
|
AC_DEFINE(WEBP_EXPERIMENTAL_FEATURES, [1], [Enable experimental code])
|
||||||
USE_EXPERIMENTAL_CODE="-DWEBP_EXPERIMENTAL_FEATURES"
|
USE_EXPERIMENTAL_CODE="-DWEBP_EXPERIMENTAL_FEATURES"
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT(${enable_experimental-no})
|
AC_MSG_RESULT(${enable_experimental-no})
|
||||||
AC_SUBST(USE_EXPERIMENTAL_CODE)
|
AC_SUBST(USE_EXPERIMENTAL_CODE)
|
||||||
|
|
||||||
dnl === Check whether libwebpmux should be built
|
dnl === Check whether libwebpmux should be built
|
||||||
AC_MSG_CHECKING(whether libwebpmux is to be built)
|
AC_MSG_CHECKING(whether libwebpmux is to be built)
|
||||||
AC_ARG_ENABLE([experimental-libwebpmux],
|
AC_ARG_ENABLE([libwebpmux],
|
||||||
AS_HELP_STRING([--enable-experimental-libwebpmux],
|
AS_HELP_STRING([--enable-libwebpmux],
|
||||||
[Build libwebpmux @<:@default=no@:>@]))
|
[Build libwebpmux @<:@default=no@:>@]))
|
||||||
AC_MSG_RESULT(${enable_experimental_libwebpmux-no})
|
AC_MSG_RESULT(${enable_libwebpmux-no})
|
||||||
AM_CONDITIONAL([WANT_MUX], [test "$enable_experimental_libwebpmux" = "yes"])
|
AM_CONDITIONAL([WANT_MUX], [test "$enable_libwebpmux" = "yes"])
|
||||||
|
|
||||||
dnl === Check whether libwebpdemux should be built
|
dnl === Check whether libwebpdemux should be built
|
||||||
AC_MSG_CHECKING(whether libwebpdemux is to be built)
|
AC_MSG_CHECKING(whether libwebpdemux is to be built)
|
||||||
AC_ARG_ENABLE([experimental-libwebpdemux],
|
AC_ARG_ENABLE([libwebpdemux],
|
||||||
AS_HELP_STRING([--enable-experimental-libwebpdemux],
|
AS_HELP_STRING([--enable-libwebpdemux],
|
||||||
[Build libwebpdemux @<:@default=no@:>@]))
|
[Build libwebpdemux @<:@default=no@:>@]))
|
||||||
AC_MSG_RESULT(${enable_experimental_libwebpdemux-no})
|
AC_MSG_RESULT(${enable_libwebpdemux-no})
|
||||||
AM_CONDITIONAL([WANT_DEMUX], [test "$enable_experimental_libwebpdemux" = "yes"])
|
AM_CONDITIONAL([WANT_DEMUX], [test "$enable_libwebpdemux" = "yes"])
|
||||||
|
|
||||||
dnl === Check whether decoder library should be built.
|
dnl === Check whether decoder library should be built.
|
||||||
AC_MSG_CHECKING(whether decoder library is to be built)
|
AC_MSG_CHECKING(whether decoder library is to be built)
|
||||||
@ -283,7 +283,8 @@ AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \
|
|||||||
src/enc/Makefile src/dsp/Makefile \
|
src/enc/Makefile src/dsp/Makefile \
|
||||||
src/demux/Makefile src/mux/Makefile \
|
src/demux/Makefile src/mux/Makefile \
|
||||||
src/utils/Makefile \
|
src/utils/Makefile \
|
||||||
src/libwebp.pc src/libwebpdecoder.pc])
|
src/libwebp.pc src/libwebpdecoder.pc \
|
||||||
|
src/demux/libwebpdemux.pc src/mux/libwebpmux.pc])
|
||||||
|
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
@ -297,8 +298,8 @@ Static libraries: ${enable_static}
|
|||||||
Threaded decode: ${enable_threading-no}
|
Threaded decode: ${enable_threading-no}
|
||||||
libwebp: yes
|
libwebp: yes
|
||||||
libwebpdecoder: ${enable_libwebpdecoder-no}
|
libwebpdecoder: ${enable_libwebpdecoder-no}
|
||||||
libwebpdemux: ${enable_experimental_libwebpdemux-no}
|
libwebpdemux: ${enable_libwebpdemux-no}
|
||||||
libwebpmux: ${enable_experimental_libwebpmux-no}
|
libwebpmux: ${enable_libwebpmux-no}
|
||||||
|
|
||||||
Tools:
|
Tools:
|
||||||
cwebp: yes
|
cwebp: yes
|
||||||
@ -314,5 +315,5 @@ dwebp: yes
|
|||||||
PNG : ${png_support-no}
|
PNG : ${png_support-no}
|
||||||
WIC : ${wic_support-no}
|
WIC : ${wic_support-no}
|
||||||
gif2webp: ${build_gif2webp-no}
|
gif2webp: ${build_gif2webp-no}
|
||||||
webpmux: ${enable_experimental_libwebpmux-no}
|
webpmux: ${enable_libwebpmux-no}
|
||||||
])
|
])
|
||||||
|
@ -60,9 +60,9 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
|||||||
document are to be interpreted as described in [RFC 2119][].
|
document are to be interpreted as described in [RFC 2119][].
|
||||||
|
|
||||||
**Note:** Out of the features mentioned above, lossy compression, lossless
|
**Note:** Out of the features mentioned above, lossy compression, lossless
|
||||||
compression and transparency are finalized and are to be considered stable.
|
compression, transparency, metadata, color profile and animation are finalized
|
||||||
On the other hand, metadata, color profile, animation and image fragmentation
|
and are to be considered stable. On the other hand, image fragmentation is
|
||||||
are experimental as of now, and are open to discussion, feedback and comments.
|
experimental as of now, and is open to discussion, feedback and comments.
|
||||||
The same is indicated using annotation "_status: experimental_" in the relevant
|
The same is indicated using annotation "_status: experimental_" in the relevant
|
||||||
sections of this document.
|
sections of this document.
|
||||||
|
|
||||||
@ -93,11 +93,21 @@ _uint32_
|
|||||||
|
|
||||||
: A 32-bit, little-endian, unsigned integer.
|
: A 32-bit, little-endian, unsigned integer.
|
||||||
|
|
||||||
|
_FourCC_
|
||||||
|
|
||||||
|
: A _FourCC_ (four-character code) is a _uint32_ created by concatenating four
|
||||||
|
ASCII characters in little-endian order.
|
||||||
|
|
||||||
_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
|
||||||
|
----------------
|
||||||
|
The WebP file format is based on the RIFF (resource interchange file format)
|
||||||
|
document format.
|
||||||
|
|
||||||
The basic element of a RIFF file is a _chunk_. It consists of:
|
The basic element of a RIFF file is a _chunk_. It consists of:
|
||||||
|
|
||||||
0 1 2 3
|
0 1 2 3
|
||||||
@ -112,12 +122,12 @@ The basic element of a RIFF file is a _chunk_. It consists of:
|
|||||||
|
|
||||||
Chunk FourCC: 32 bits
|
Chunk FourCC: 32 bits
|
||||||
|
|
||||||
: ASCII four character code or _chunk tag_ used for chunk identification.
|
: ASCII four-character code used for chunk identification.
|
||||||
|
|
||||||
Chunk Size: 32 bits (_uint32_)
|
Chunk Size: 32 bits (_uint32_)
|
||||||
|
|
||||||
: The size of the chunk (_ckSize_) not including this field, the chunk
|
: The size of the chunk not including this field, the chunk identifier or
|
||||||
identifier and padding.
|
padding.
|
||||||
|
|
||||||
Chunk Payload: _Chunk Size_ bytes
|
Chunk Payload: _Chunk Size_ bytes
|
||||||
|
|
||||||
@ -126,43 +136,13 @@ Chunk Payload: _Chunk Size_ bytes
|
|||||||
|
|
||||||
_ChunkHeader('ABCD')_
|
_ChunkHeader('ABCD')_
|
||||||
|
|
||||||
: This is used to describe the fourcc and size header of individual
|
: This is used to describe the _FourCC_ and _Chunk Size_ header of individual
|
||||||
chunks, where 'ABCD' is the fourcc for the chunk. This element's
|
chunks, where 'ABCD' is the FourCC for the chunk. This element's
|
||||||
size is 8 bytes.
|
size is 8 bytes.
|
||||||
|
|
||||||
: Note that, in this specification, all chunk tag characters are in
|
**Note:** RIFF has a convention that all-uppercase chunk FourCCs are standard
|
||||||
file order, not in byte order of a uint32 of any particular
|
chunks that apply to any RIFF file format, while FourCCs specific to a file
|
||||||
architecture.
|
format are all lowercase. WebP does not follow this convention.
|
||||||
|
|
||||||
_list of chunks_
|
|
||||||
|
|
||||||
: A concatenation of multiple chunks.
|
|
||||||
|
|
||||||
: We will refer to the first chunk as having _position_ 0, the second
|
|
||||||
as position 1, etc. By _chunk with index 0 among "ABCD"_ we mean
|
|
||||||
the first chunk among the chunks of type "ABCD" in the list, the
|
|
||||||
_chunk with index 1 among "ABCD"_ is the second such chunk, etc.
|
|
||||||
|
|
||||||
A WebP file MUST begin with a single chunk with a tag 'RIFF'. All
|
|
||||||
other defined chunks are contained within this chunk. The file SHOULD
|
|
||||||
NOT contain anything after it.
|
|
||||||
|
|
||||||
The maximum size of RIFF's _ckSize_ is 2^32 minus 10 bytes. The size
|
|
||||||
of the whole file is at most 4GiB minus 2 bytes.
|
|
||||||
|
|
||||||
**Note:** some RIFF libraries are said to have bugs when handling files
|
|
||||||
larger than 1GiB or 2GiB. If you are using an existing library, check
|
|
||||||
that it handles large files correctly.
|
|
||||||
|
|
||||||
The first four bytes of the RIFF chunk contents (i.e., bytes 8-11 of the file)
|
|
||||||
MUST be the ASCII string "WEBP". They are followed by a list of chunks. As the
|
|
||||||
size of any chunk is even, the size of the RIFF chunk is also even. The
|
|
||||||
contents of the chunks in that list will be described in the following sections.
|
|
||||||
|
|
||||||
**Note:** RIFF has a convention that all-uppercase chunks are standard
|
|
||||||
chunks that apply to any RIFF file format, while chunks specific to a
|
|
||||||
file format are all lowercase. WebP does not follow this convention.
|
|
||||||
|
|
||||||
|
|
||||||
WebP file header
|
WebP file header
|
||||||
----------------
|
----------------
|
||||||
@ -183,12 +163,20 @@ 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 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
|
||||||
|
most 4GiB minus 2 bytes.
|
||||||
|
|
||||||
'WEBP': 32 bits
|
'WEBP': 32 bits
|
||||||
|
|
||||||
: The ASCII characters 'W' 'E' 'B' 'P'.
|
: The ASCII characters 'W' 'E' 'B' 'P'.
|
||||||
|
|
||||||
|
A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size
|
||||||
|
in the header is the total size of the chunks that follow plus `4` bytes for
|
||||||
|
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
|
||||||
|
contents of individual chunks will be described in the following sections.
|
||||||
|
|
||||||
Simple file format (lossy)
|
Simple file format (lossy)
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
@ -274,15 +262,15 @@ An extended format file consists of:
|
|||||||
|
|
||||||
* A 'VP8X' chunk with information about features used in the file.
|
* A 'VP8X' chunk with information about features used in the file.
|
||||||
|
|
||||||
* An optional 'ICCP' chunk with color profile. _\[status: experimental\]_
|
* An optional 'ICCP' chunk with color profile.
|
||||||
|
|
||||||
* An optional 'ANIM' chunk with animation control data. _\[status: experimental\]_
|
* An optional 'ANIM' chunk with animation control data.
|
||||||
|
|
||||||
* Image data.
|
* Image data.
|
||||||
|
|
||||||
* An optional 'EXIF' chunk with EXIF metadata. _\[status: experimental\]_
|
* An optional 'EXIF' chunk with EXIF metadata.
|
||||||
|
|
||||||
* An optional 'XMP ' chunk with XMP metadata. _\[status: experimental\]_
|
* An optional 'XMP ' chunk with XMP metadata.
|
||||||
|
|
||||||
* An optional list of [unknown chunks](#unknown-chunks). _\[status: experimental\]_
|
* An optional list of [unknown chunks](#unknown-chunks). _\[status: experimental\]_
|
||||||
|
|
||||||
@ -325,7 +313,7 @@ Reserved (Rsv): 2 bits
|
|||||||
|
|
||||||
: SHOULD be `0`.
|
: SHOULD be `0`.
|
||||||
|
|
||||||
ICC profile (I): 1 bit _\[status: experimental\]_
|
ICC profile (I): 1 bit
|
||||||
|
|
||||||
: Set if the file contains an ICC profile.
|
: Set if the file contains an ICC profile.
|
||||||
|
|
||||||
@ -334,15 +322,15 @@ 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 _\[status: experimental\]_
|
EXIF metadata (E): 1 bit
|
||||||
|
|
||||||
: Set if the file contains EXIF metadata.
|
: Set if the file contains EXIF metadata.
|
||||||
|
|
||||||
XMP metadata (X): 1 bit _\[status: experimental\]_
|
XMP metadata (X): 1 bit
|
||||||
|
|
||||||
: Set if the file contains XMP metadata.
|
: Set if the file contains XMP metadata.
|
||||||
|
|
||||||
Animation (A): 1 bit _\[status: experimental\]_
|
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.
|
||||||
@ -371,11 +359,12 @@ Future specifications MAY add more fields.
|
|||||||
|
|
||||||
### Chunks
|
### Chunks
|
||||||
|
|
||||||
#### Animation _\[status: experimental\]_
|
#### Animation
|
||||||
|
|
||||||
An animation is controlled by ANIM and ANMF chunks.
|
An animation is controlled by ANIM and ANMF chunks.
|
||||||
|
|
||||||
ANIM Chunk:
|
ANIM Chunk:
|
||||||
|
{:#anim_chunk}
|
||||||
|
|
||||||
For an animated image, this chunk contains the _global parameters_ of the
|
For an animated image, this chunk contains the _global parameters_ of the
|
||||||
animation.
|
animation.
|
||||||
@ -392,10 +381,14 @@ animation.
|
|||||||
|
|
||||||
Background Color: 32 bits (_uint32_)
|
Background Color: 32 bits (_uint32_)
|
||||||
|
|
||||||
: The background color of the canvas in \[Blue, Green, Red, Alpha\] byte order.
|
: The default background color of the canvas in \[Blue, Green, Red, Alpha\]
|
||||||
The background color is the color used for those pixels of the canvas that are
|
byte order. This color is used to fill the unused space on the canvas around the
|
||||||
not covered by a frame. Background color is also used when disposal method is
|
frames, as well as the transparent pixels of the first frame. Background color
|
||||||
`1`.
|
is also used when disposal method is `1`.
|
||||||
|
|
||||||
|
**Note**: Viewers that have a preferred background against which to present the
|
||||||
|
images (web browsers, for example) should ignore this value and use their
|
||||||
|
preferred background color instead.
|
||||||
|
|
||||||
Loop Count: 16 bits (_uint16_)
|
Loop Count: 16 bits (_uint16_)
|
||||||
|
|
||||||
@ -457,14 +450,45 @@ Reserved: 7 bits
|
|||||||
|
|
||||||
Disposal method (D): 1 bit
|
Disposal method (D): 1 bit
|
||||||
|
|
||||||
: Indicates how the area used by this frame is to be treated before rendering
|
: Indicates how _the current frame_ is to be treated after it has been displayed
|
||||||
the next frame on canvas:
|
(before rendering the next frame) on the canvas:
|
||||||
|
|
||||||
* `0`: Do not dispose. Keep the area used by this frame as it is and render
|
* `0`: Do not dispose. Leave the canvas as is.
|
||||||
the next frame on top of it.
|
|
||||||
|
|
||||||
* `1`: Dispose to background color (also part of this chunk). Restore the
|
* `1`: Dispose to background color. Fill the _rectangle_ on the canvas covered
|
||||||
area used by this frame to background color before rendering the next frame.
|
by the _current frame_ with background color specified in the
|
||||||
|
[ANIM chunk](#anim_chunk).
|
||||||
|
|
||||||
|
After disposing the current frame, render the next frame on the canvas using
|
||||||
|
[alpha-blending](#alpha-blending). If the next frame does not have an alpha
|
||||||
|
channel, assume alpha value of 255, effectively replacing the rectangle.
|
||||||
|
|
||||||
|
**Notes**:
|
||||||
|
|
||||||
|
* The frame disposal only applies to the _frame rectangle_, that is, the
|
||||||
|
rectangle defined by _Frame X_, _Frame Y_, _frame width_ and _frame height_.
|
||||||
|
It may or may not cover the whole canvas.
|
||||||
|
|
||||||
|
{:#alpha-blending}
|
||||||
|
* **Alpha-blending**:
|
||||||
|
|
||||||
|
Given that each of the R, G, B and A channels is 8-bit, and the RGB
|
||||||
|
channels are _not premultiplied_ by alpha, the formula for blending
|
||||||
|
'dst' onto 'src' is:
|
||||||
|
|
||||||
|
~~~~~
|
||||||
|
blend.A = src.A + dst.A * (1 - src.A / 255)
|
||||||
|
if blend.A = 0 then
|
||||||
|
blend.RGB = 0
|
||||||
|
else
|
||||||
|
blend.RGB = (src.RGB * src.A +
|
||||||
|
dst.RGB * dst.A * (1 - src.A / 255)) / blend.A
|
||||||
|
~~~~~
|
||||||
|
|
||||||
|
* Alpha-blending SHOULD be done in linear color space, by taking into account
|
||||||
|
the [color profile](#color-profile) of the image. If the color profile is
|
||||||
|
not present, sRGB is to be assumed. (Note that sRGB also needs to be
|
||||||
|
linearized due to a gamma of ~2.2).
|
||||||
|
|
||||||
Frame Data: _Chunk Size_ - `16` bytes
|
Frame Data: _Chunk Size_ - `16` bytes
|
||||||
|
|
||||||
@ -478,6 +502,9 @@ Frame Data: _Chunk Size_ - `16` bytes
|
|||||||
|
|
||||||
* An optional list of [unknown chunks](#unknown-chunks).
|
* An optional list of [unknown chunks](#unknown-chunks).
|
||||||
|
|
||||||
|
**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
|
||||||
|
_padded_ chunks as described by the [RIFF file format](#riff-file-format).
|
||||||
|
|
||||||
#### Fragments _\[status: experimental\]_
|
#### Fragments _\[status: experimental\]_
|
||||||
|
|
||||||
For images that are represented by fragments, this chunk contains data for
|
For images that are represented by fragments, this chunk contains data for
|
||||||
@ -644,7 +671,7 @@ 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 _\[status: experimental\]_
|
#### Color profile
|
||||||
|
|
||||||
0 1 2 3
|
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
|
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
|
||||||
@ -666,7 +693,7 @@ See the [ICC Specification][iccspec] for details.
|
|||||||
|
|
||||||
If this chunk is not present, sRGB SHOULD be assumed.
|
If this chunk is not present, sRGB SHOULD be assumed.
|
||||||
|
|
||||||
#### Metadata _\[status: experimental\]_
|
#### Metadata
|
||||||
|
|
||||||
Metadata can be stored in 'EXIF' or 'XMP ' chunks.
|
Metadata can be stored in 'EXIF' or 'XMP ' chunks.
|
||||||
|
|
||||||
@ -727,14 +754,14 @@ A file MAY contain unknown chunks:
|
|||||||
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 _\[status: experimental\]_
|
### Assembling the Canvas from fragments/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 case
|
||||||
of a fragmented-image and in case of an animated image. The notation
|
of a fragmented-image and in case of an animated image. The notation
|
||||||
_VP8X.field_ means the field in the 'VP8X' chunk with the same description.
|
_VP8X.field_ means the field in the 'VP8X' chunk with the same description.
|
||||||
|
|
||||||
Displaying a _fragmented image_ canvas MUST be equivalent to the following
|
Displaying a _fragmented image_ canvas MUST be equivalent to the following
|
||||||
pseudocode:
|
pseudocode: _\[status: experimental\]_
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
assert VP8X.flags.hasFragments
|
assert VP8X.flags.hasFragments
|
||||||
|
@ -11,9 +11,7 @@ endif
|
|||||||
|
|
||||||
noinst_LTLIBRARIES = libexampleutil.la
|
noinst_LTLIBRARIES = libexampleutil.la
|
||||||
|
|
||||||
libexampleutil_la_SOURCES = example_util.c
|
libexampleutil_la_SOURCES = example_util.c example_util.h
|
||||||
libexampleutilinclude_HEADERS = example_util.h
|
|
||||||
libexampleutilincludedir =
|
|
||||||
|
|
||||||
dwebp_SOURCES = dwebp.c stopwatch.h
|
dwebp_SOURCES = dwebp.c stopwatch.h
|
||||||
dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
|
dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
|
||||||
|
@ -366,14 +366,30 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
METADATA_EXIF = (1 << 0),
|
METADATA_EXIF = (1 << 0),
|
||||||
METADATA_ICCP = (1 << 1),
|
METADATA_ICC = (1 << 1),
|
||||||
METADATA_XMP = (1 << 2),
|
METADATA_XMP = (1 << 2),
|
||||||
METADATA_ALL = METADATA_EXIF | METADATA_ICCP | METADATA_XMP
|
METADATA_ALL = METADATA_EXIF | METADATA_ICC | METADATA_XMP
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int kChunkHeaderSize = 8;
|
static const int kChunkHeaderSize = 8;
|
||||||
static const int kTagSize = 4;
|
static const int kTagSize = 4;
|
||||||
|
|
||||||
|
static void PrintMetadataInfo(const Metadata* const metadata,
|
||||||
|
int metadata_written) {
|
||||||
|
if (metadata == NULL || metadata_written == 0) return;
|
||||||
|
|
||||||
|
fprintf(stderr, "Metadata:\n");
|
||||||
|
if (metadata_written & METADATA_ICC) {
|
||||||
|
fprintf(stderr, " * ICC profile: %6d bytes\n", (int)metadata->iccp.size);
|
||||||
|
}
|
||||||
|
if (metadata_written & METADATA_EXIF) {
|
||||||
|
fprintf(stderr, " * EXIF data: %6d bytes\n", (int)metadata->exif.size);
|
||||||
|
}
|
||||||
|
if (metadata_written & METADATA_XMP) {
|
||||||
|
fprintf(stderr, " * XMP data: %6d bytes\n", (int)metadata->xmp.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Outputs, in little endian, 'num' bytes from 'val' to 'out'.
|
// Outputs, in little endian, 'num' bytes from 'val' to 'out'.
|
||||||
static int WriteLE(FILE* const out, uint32_t val, int num) {
|
static int WriteLE(FILE* const out, uint32_t val, int num) {
|
||||||
uint8_t buf[4];
|
uint8_t buf[4];
|
||||||
@ -424,7 +440,8 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
const WebPPicture* const picture,
|
const WebPPicture* const picture,
|
||||||
const WebPMemoryWriter* const memory_writer,
|
const WebPMemoryWriter* const memory_writer,
|
||||||
const Metadata* const metadata,
|
const Metadata* const metadata,
|
||||||
int keep_metadata) {
|
int keep_metadata,
|
||||||
|
int* const metadata_written) {
|
||||||
const char kVP8XHeader[] = "VP8X\x0a\x00\x00\x00";
|
const char kVP8XHeader[] = "VP8X\x0a\x00\x00\x00";
|
||||||
const int kAlphaFlag = 0x10;
|
const int kAlphaFlag = 0x10;
|
||||||
const int kEXIFFlag = 0x08;
|
const int kEXIFFlag = 0x08;
|
||||||
@ -439,13 +456,16 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
!!(keep_metadata & METADATA_EXIF),
|
!!(keep_metadata & METADATA_EXIF),
|
||||||
kEXIFFlag, &flags, &metadata_size);
|
kEXIFFlag, &flags, &metadata_size);
|
||||||
const int write_iccp = UpdateFlagsAndSize(&metadata->iccp,
|
const int write_iccp = UpdateFlagsAndSize(&metadata->iccp,
|
||||||
!!(keep_metadata & METADATA_ICCP),
|
!!(keep_metadata & METADATA_ICC),
|
||||||
kICCPFlag, &flags, &metadata_size);
|
kICCPFlag, &flags, &metadata_size);
|
||||||
const int write_xmp = UpdateFlagsAndSize(&metadata->xmp,
|
const int write_xmp = UpdateFlagsAndSize(&metadata->xmp,
|
||||||
!!(keep_metadata & METADATA_XMP),
|
!!(keep_metadata & METADATA_XMP),
|
||||||
kXMPFlag, &flags, &metadata_size);
|
kXMPFlag, &flags, &metadata_size);
|
||||||
uint8_t* webp = memory_writer->mem;
|
uint8_t* webp = memory_writer->mem;
|
||||||
size_t webp_size = memory_writer->size;
|
size_t webp_size = memory_writer->size;
|
||||||
|
|
||||||
|
*metadata_written = 0;
|
||||||
|
|
||||||
if (webp_size < kMinSize) return 0;
|
if (webp_size < kMinSize) return 0;
|
||||||
if (webp_size - kChunkHeaderSize + metadata_size > kMaxChunkPayload) {
|
if (webp_size - kChunkHeaderSize + metadata_size > kMaxChunkPayload) {
|
||||||
fprintf(stderr, "Error! Addition of metadata would exceed "
|
fprintf(stderr, "Error! Addition of metadata would exceed "
|
||||||
@ -482,11 +502,20 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
ok = ok && WriteLE24(out, picture->width - 1);
|
ok = ok && WriteLE24(out, picture->width - 1);
|
||||||
ok = ok && WriteLE24(out, picture->height - 1);
|
ok = ok && WriteLE24(out, picture->height - 1);
|
||||||
}
|
}
|
||||||
if (write_iccp) ok = ok && WriteMetadataChunk(out, "ICCP", &metadata->iccp);
|
if (write_iccp) {
|
||||||
|
ok = ok && WriteMetadataChunk(out, "ICCP", &metadata->iccp);
|
||||||
|
*metadata_written |= METADATA_ICC;
|
||||||
|
}
|
||||||
// Image
|
// Image
|
||||||
ok = ok && (fwrite(webp, webp_size, 1, out) == 1);
|
ok = ok && (fwrite(webp, webp_size, 1, out) == 1);
|
||||||
if (write_exif) ok = ok && WriteMetadataChunk(out, "EXIF", &metadata->exif);
|
if (write_exif) {
|
||||||
if (write_xmp) ok = ok && WriteMetadataChunk(out, "XMP ", &metadata->xmp);
|
ok = ok && WriteMetadataChunk(out, "EXIF", &metadata->exif);
|
||||||
|
*metadata_written |= METADATA_EXIF;
|
||||||
|
}
|
||||||
|
if (write_xmp) {
|
||||||
|
ok = ok && WriteMetadataChunk(out, "XMP ", &metadata->xmp);
|
||||||
|
*metadata_written |= METADATA_XMP;
|
||||||
|
}
|
||||||
return ok;
|
return ok;
|
||||||
} else {
|
} else {
|
||||||
// No metadata, just write the original image file.
|
// No metadata, just write the original image file.
|
||||||
@ -575,7 +604,7 @@ static void HelpLong(void) {
|
|||||||
printf(" ");
|
printf(" ");
|
||||||
printf("copy from the input to the output if present.\n");
|
printf("copy from the input to the output if present.\n");
|
||||||
printf(" "
|
printf(" "
|
||||||
"Valid values: all, none (default), exif, iccp, xmp\n");
|
"Valid values: all, none (default), exif, icc, xmp\n");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" -short ................. condense printed message\n");
|
printf(" -short ................. condense printed message\n");
|
||||||
@ -631,6 +660,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
int resize_w = 0, resize_h = 0;
|
int resize_w = 0, resize_h = 0;
|
||||||
int show_progress = 0;
|
int show_progress = 0;
|
||||||
int keep_metadata = 0;
|
int keep_metadata = 0;
|
||||||
|
int metadata_written = 0;
|
||||||
WebPPicture picture;
|
WebPPicture picture;
|
||||||
int print_distortion = -1; // -1=off, 0=PSNR, 1=SSIM, 2=LSIM
|
int print_distortion = -1; // -1=off, 0=PSNR, 1=SSIM, 2=LSIM
|
||||||
WebPPicture original_picture; // when PSNR or SSIM is requested
|
WebPPicture original_picture; // when PSNR or SSIM is requested
|
||||||
@ -812,7 +842,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
{ "all", METADATA_ALL },
|
{ "all", METADATA_ALL },
|
||||||
{ "none", 0 },
|
{ "none", 0 },
|
||||||
{ "exif", METADATA_EXIF },
|
{ "exif", METADATA_EXIF },
|
||||||
{ "iccp", METADATA_ICCP },
|
{ "icc", METADATA_ICC },
|
||||||
{ "xmp", METADATA_XMP },
|
{ "xmp", METADATA_XMP },
|
||||||
};
|
};
|
||||||
const size_t kNumTokens = sizeof(kTokens) / sizeof(kTokens[0]);
|
const size_t kNumTokens = sizeof(kTokens) / sizeof(kTokens[0]);
|
||||||
@ -844,7 +874,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
start = token + 1;
|
start = token + 1;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
if (keep_metadata != 0 && keep_metadata != METADATA_ICCP) {
|
if (keep_metadata != 0 && keep_metadata != METADATA_ICC) {
|
||||||
// TODO(jzern): remove when -metadata is supported on all platforms.
|
// TODO(jzern): remove when -metadata is supported on all platforms.
|
||||||
fprintf(stderr, "Warning: only ICC profile extraction is currently"
|
fprintf(stderr, "Warning: only ICC profile extraction is currently"
|
||||||
" supported on this platform!\n");
|
" supported on this platform!\n");
|
||||||
@ -978,7 +1008,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
if (keep_metadata != 0 && out != NULL) {
|
if (keep_metadata != 0 && out != NULL) {
|
||||||
if (!WriteWebPWithMetadata(out, &picture, &memory_writer,
|
if (!WriteWebPWithMetadata(out, &picture, &memory_writer,
|
||||||
&metadata, keep_metadata)) {
|
&metadata, keep_metadata, &metadata_written)) {
|
||||||
fprintf(stderr, "Error writing WebP file with metadata!\n");
|
fprintf(stderr, "Error writing WebP file with metadata!\n");
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
@ -990,6 +1020,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
PrintExtraInfoLossy(&picture, short_output, config.low_memory, in_file);
|
PrintExtraInfoLossy(&picture, short_output, config.low_memory, in_file);
|
||||||
}
|
}
|
||||||
|
if (!short_output) {
|
||||||
|
PrintMetadataInfo(&metadata, metadata_written);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!quiet && !short_output && print_distortion >= 0) { // print distortion
|
if (!quiet && !short_output && print_distortion >= 0) { // print distortion
|
||||||
static const char* distortion_names[] = { "PSNR", "SSIM", "LSIM" };
|
static const char* distortion_names[] = { "PSNR", "SSIM", "LSIM" };
|
||||||
|
@ -460,6 +460,13 @@ int main(int argc, const char *argv[]) {
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bitstream->has_animation) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error! Decoding of an animated WebP file is not supported.\n"
|
||||||
|
" Use webpmux to extract the individual frames or\n"
|
||||||
|
" vwebp to view this image.\n");
|
||||||
|
}
|
||||||
|
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case PNG:
|
case PNG:
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
|
@ -44,8 +44,8 @@ int ExUtilReadFile(const char* const file_name,
|
|||||||
fclose(in);
|
fclose(in);
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr, "Could not read %zu bytes of data from file %s\n",
|
fprintf(stderr, "Could not read %d bytes of data from file %s\n",
|
||||||
file_size, file_name);
|
(int)file_size, file_name);
|
||||||
free(file_data);
|
free(file_data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -117,36 +117,42 @@ static int ReadSubImage(GifFileType* gif, WebPPicture* pic, WebPPicture* view) {
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetColorFromIndex(const ColorMapObject* const color_map, GifWord idx,
|
static int GetBackgroundColor(const ColorMapObject* const color_map,
|
||||||
uint32_t* const argb) {
|
GifWord bgcolor_idx, uint32_t* const bgcolor) {
|
||||||
assert(color_map != NULL && color_map->Colors != NULL);
|
if (transparent_index != -1 && bgcolor_idx == transparent_index) {
|
||||||
if (idx >= color_map->ColorCount) {
|
*bgcolor = TRANSPARENT_COLOR; // Special case.
|
||||||
return 0; // Invalid index.
|
return 1;
|
||||||
|
} else if (color_map == NULL || color_map->Colors == NULL
|
||||||
|
|| bgcolor_idx >= color_map->ColorCount) {
|
||||||
|
return 0; // Invalid color map or index.
|
||||||
} else {
|
} else {
|
||||||
const GifColorType color = color_map->Colors[idx];
|
const GifColorType color = color_map->Colors[bgcolor_idx];
|
||||||
*argb = (0xff << 24)
|
*bgcolor = (0xff << 24)
|
||||||
| (color.Red << 16)
|
| (color.Red << 16)
|
||||||
| (color.Green << 8)
|
| (color.Green << 8)
|
||||||
| (color.Blue << 0);
|
| (color.Blue << 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DisplayGifError(const GifFileType* const gif) {
|
static void DisplayGifError(const GifFileType* const gif, int gif_error) {
|
||||||
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
||||||
// libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
|
// libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
|
||||||
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) && \
|
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) && \
|
||||||
((GIFLIB_MAJOR == 4 && GIFLIB_MINOR >= 2) || GIFLIB_MAJOR > 4)
|
((GIFLIB_MAJOR == 4 && GIFLIB_MINOR >= 2) || GIFLIB_MAJOR > 4)
|
||||||
#if GIFLIB_MAJOR >= 5
|
#if GIFLIB_MAJOR >= 5
|
||||||
// Static string actually, hence the const char* cast.
|
// Static string actually, hence the const char* cast.
|
||||||
const char* error_str = (const char*)GifErrorString(gif->Error);
|
const char* error_str = (const char*)GifErrorString(
|
||||||
|
(gif == NULL) ? gif_error : gif->Error);
|
||||||
#else
|
#else
|
||||||
const char* error_str = (const char*)GifErrorString();
|
const char* error_str = (const char*)GifErrorString();
|
||||||
|
(void)gif;
|
||||||
#endif
|
#endif
|
||||||
if (error_str == NULL) error_str = "Unknown error";
|
if (error_str == NULL) error_str = "Unknown error";
|
||||||
fprintf(stderr, "GIFLib Error: %s\n", error_str);
|
fprintf(stderr, "GIFLib Error %d: %s\n", gif_error, error_str);
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "GIFLib Error: ");
|
(void)gif;
|
||||||
|
fprintf(stderr, "GIFLib Error %d: ", gif_error);
|
||||||
PrintGifError();
|
PrintGifError();
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
#endif
|
#endif
|
||||||
@ -184,7 +190,7 @@ static void Help(void) {
|
|||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
int gif_error = -1;
|
int gif_error = GIF_ERROR;
|
||||||
WebPMuxError err = WEBP_MUX_OK;
|
WebPMuxError err = WEBP_MUX_OK;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
const char *in_file = NULL, *out_file = NULL;
|
const char *in_file = NULL, *out_file = NULL;
|
||||||
@ -196,6 +202,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
WebPMuxFrameInfo frame;
|
WebPMuxFrameInfo frame;
|
||||||
WebPMuxAnimParams anim = { WHITE_COLOR, 0 };
|
WebPMuxAnimParams anim = { WHITE_COLOR, 0 };
|
||||||
|
|
||||||
|
int is_first_frame = 1;
|
||||||
int done;
|
int done;
|
||||||
int c;
|
int c;
|
||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
@ -280,14 +287,6 @@ int main(int argc, const char *argv[]) {
|
|||||||
picture.custom_ptr = &memory;
|
picture.custom_ptr = &memory;
|
||||||
if (!WebPPictureAlloc(&picture)) goto End;
|
if (!WebPPictureAlloc(&picture)) goto End;
|
||||||
|
|
||||||
if (gif->SColorMap != NULL &&
|
|
||||||
!GetColorFromIndex(gif->SColorMap, gif->SBackGroundColor,
|
|
||||||
&anim.bgcolor)) {
|
|
||||||
fprintf(stderr, "GIF decode warning: invalid background color index. "
|
|
||||||
"Assuming white background.\n");
|
|
||||||
}
|
|
||||||
ClearPicture(&picture, anim.bgcolor);
|
|
||||||
|
|
||||||
mux = WebPMuxNew();
|
mux = WebPMuxNew();
|
||||||
if (mux == NULL) {
|
if (mux == NULL) {
|
||||||
fprintf(stderr, "ERROR: could not create a mux object.\n");
|
fprintf(stderr, "ERROR: could not create a mux object.\n");
|
||||||
@ -340,11 +339,11 @@ int main(int argc, const char *argv[]) {
|
|||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
fprintf(stderr, "Added frame %dx%d (offset:%d,%d duration:%d) ",
|
printf("Added frame %dx%d (offset:%d,%d duration:%d) ",
|
||||||
view.width, view.height, frame.x_offset, frame.y_offset,
|
view.width, view.height, frame.x_offset, frame.y_offset,
|
||||||
frame.duration);
|
frame.duration);
|
||||||
fprintf(stderr, "dispose:%d transparent index:%d\n",
|
printf("dispose:%d transparent index:%d\n",
|
||||||
frame.dispose_method, transparent_index);
|
frame.dispose_method, transparent_index);
|
||||||
}
|
}
|
||||||
WebPDataClear(&frame.bitstream);
|
WebPDataClear(&frame.bitstream);
|
||||||
break;
|
break;
|
||||||
@ -376,6 +375,15 @@ int main(int argc, const char *argv[]) {
|
|||||||
: WEBP_MUX_DISPOSE_NONE;
|
: WEBP_MUX_DISPOSE_NONE;
|
||||||
}
|
}
|
||||||
transparent_index = (flags & GIF_TRANSPARENT_MASK) ? data[4] : -1;
|
transparent_index = (flags & GIF_TRANSPARENT_MASK) ? data[4] : -1;
|
||||||
|
if (is_first_frame) {
|
||||||
|
if (!GetBackgroundColor(gif->SColorMap, gif->SBackGroundColor,
|
||||||
|
&anim.bgcolor)) {
|
||||||
|
fprintf(stderr, "GIF decode warning: invalid background color "
|
||||||
|
"index. Assuming white background.\n");
|
||||||
|
}
|
||||||
|
ClearPicture(&picture, anim.bgcolor);
|
||||||
|
is_first_frame = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PLAINTEXT_EXT_FUNC_CODE: {
|
case PLAINTEXT_EXT_FUNC_CODE: {
|
||||||
@ -389,7 +397,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (data == NULL) goto End; // Loop count sub-block missing.
|
if (data == NULL) goto End; // Loop count sub-block missing.
|
||||||
if (data[0] != 3 && data[1] != 1) break; // wrong size/marker
|
if (data[0] != 3 && data[1] != 1) break; // wrong size/marker
|
||||||
anim.loop_count = data[2] | (data[3] << 8);
|
anim.loop_count = data[2] | (data[3] << 8);
|
||||||
if (verbose) fprintf(stderr, "Loop count: %d\n", anim.loop_count);
|
if (verbose) printf("Loop count: %d\n", anim.loop_count);
|
||||||
} else if (!memcmp(data + 1, "XMP dataXMP", 11)) {
|
} else if (!memcmp(data + 1, "XMP dataXMP", 11)) {
|
||||||
// Read XMP metadata.
|
// Read XMP metadata.
|
||||||
WebPData xmp;
|
WebPData xmp;
|
||||||
@ -398,7 +406,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
xmp.bytes = (uint8_t*)data;
|
xmp.bytes = (uint8_t*)data;
|
||||||
xmp.size = data[0] + 1;
|
xmp.size = data[0] + 1;
|
||||||
WebPMuxSetChunk(mux, "XMP ", &xmp, 1);
|
WebPMuxSetChunk(mux, "XMP ", &xmp, 1);
|
||||||
if (verbose) fprintf(stderr, "XMP size: %zu\n", xmp.size);
|
if (verbose) printf("XMP size: %d\n", (int)xmp.size);
|
||||||
} else if (!memcmp(data + 1, "ICCRGBG1012", 11)) {
|
} else if (!memcmp(data + 1, "ICCRGBG1012", 11)) {
|
||||||
// Read ICC profile.
|
// Read ICC profile.
|
||||||
WebPData icc;
|
WebPData icc;
|
||||||
@ -407,7 +415,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
icc.bytes = (uint8_t*)data;
|
icc.bytes = (uint8_t*)data;
|
||||||
icc.size = data[0] + 1;
|
icc.size = data[0] + 1;
|
||||||
WebPMuxSetChunk(mux, "ICCP", &icc, 1);
|
WebPMuxSetChunk(mux, "ICCP", &icc, 1);
|
||||||
if (verbose) fprintf(stderr, "ICC size: %zu\n", icc.size);
|
if (verbose) printf("ICC size: %d\n", (int)icc.size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -451,12 +459,18 @@ int main(int argc, const char *argv[]) {
|
|||||||
fprintf(stderr, "Error writing output file: %s\n", out_file);
|
fprintf(stderr, "Error writing output file: %s\n", out_file);
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
if (!quiet) fprintf(stderr, "Saved output file: %s\n", out_file);
|
if (!quiet) {
|
||||||
|
printf("Saved output file: %s\n", out_file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!quiet) {
|
||||||
|
printf("Nothing written; use -o flag to save the result.\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// All OK.
|
// All OK.
|
||||||
ok = 1;
|
ok = 1;
|
||||||
gif_error = 0;
|
gif_error = GIF_OK;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
WebPDataClear(&webp_data);
|
WebPDataClear(&webp_data);
|
||||||
@ -464,8 +478,8 @@ int main(int argc, const char *argv[]) {
|
|||||||
WebPPictureFree(&picture);
|
WebPPictureFree(&picture);
|
||||||
if (out != NULL && out_file != NULL) fclose(out);
|
if (out != NULL && out_file != NULL) fclose(out);
|
||||||
|
|
||||||
if (gif_error != 0) {
|
if (gif_error != GIF_OK) {
|
||||||
DisplayGifError(gif);
|
DisplayGifError(gif, gif_error);
|
||||||
}
|
}
|
||||||
if (gif != NULL) {
|
if (gif != NULL) {
|
||||||
DGifCloseFile(gif);
|
DGifCloseFile(gif);
|
||||||
|
@ -79,9 +79,9 @@ static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
|||||||
ICCPSegment* segment;
|
ICCPSegment* segment;
|
||||||
|
|
||||||
if (segment_size == 0 || count == 0 || seq == 0) {
|
if (segment_size == 0 || count == 0 || seq == 0) {
|
||||||
fprintf(stderr, "[ICCP] size (%zu) / count (%d) / sequence number (%d)"
|
fprintf(stderr, "[ICCP] size (%d) / count (%d) / sequence number (%d)"
|
||||||
" cannot be 0!\n",
|
" cannot be 0!\n",
|
||||||
segment_size, seq, count);
|
(int)segment_size, seq, count);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
259
examples/vwebp.c
259
examples/vwebp.c
@ -8,7 +8,7 @@
|
|||||||
// Simple WebP file viewer.
|
// Simple WebP file viewer.
|
||||||
//
|
//
|
||||||
// Compiling on linux:
|
// Compiling on linux:
|
||||||
// sudo apt-get install libglut3-dev mesa-common-dev
|
// sudo apt-get install freeglut3-dev mesa-common-dev
|
||||||
// gcc -o vwebp vwebp.c -O3 -lwebp -lwebpmux -lglut -lGL -lpthread -lm
|
// gcc -o vwebp vwebp.c -O3 -lwebp -lwebpmux -lglut -lGL -lpthread -lm
|
||||||
// Compiling on Mac + XCode:
|
// Compiling on Mac + XCode:
|
||||||
// gcc -o vwebp vwebp.c -lwebp -lwebpmux -framework GLUT -framework OpenGL
|
// gcc -o vwebp vwebp.c -lwebp -lwebpmux -framework GLUT -framework OpenGL
|
||||||
@ -19,9 +19,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/decode.h"
|
|
||||||
#include "webp/demux.h"
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <GLUT/glut.h>
|
#include <GLUT/glut.h>
|
||||||
#else
|
#else
|
||||||
@ -31,6 +28,13 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WEBP_HAVE_QCMS
|
||||||
|
#include <qcms.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "webp/decode.h"
|
||||||
|
#include "webp/demux.h"
|
||||||
|
|
||||||
#include "./example_util.h"
|
#include "./example_util.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@ -42,9 +46,11 @@ 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;
|
||||||
|
int has_color_profile;
|
||||||
int done;
|
int done;
|
||||||
int decoding_error;
|
int decoding_error;
|
||||||
int print_info;
|
int print_info;
|
||||||
|
int use_color_profile;
|
||||||
|
|
||||||
int canvas_width, canvas_height;
|
int canvas_width, canvas_height;
|
||||||
int loop_count;
|
int loop_count;
|
||||||
@ -56,6 +62,12 @@ static struct {
|
|||||||
const WebPDecBuffer* pic;
|
const WebPDecBuffer* pic;
|
||||||
WebPDemuxer* dmux;
|
WebPDemuxer* dmux;
|
||||||
WebPIterator frameiter;
|
WebPIterator frameiter;
|
||||||
|
struct {
|
||||||
|
int width, height;
|
||||||
|
int x_offset, y_offset;
|
||||||
|
enum WebPMuxAnimDispose dispose_method;
|
||||||
|
} prev_frame;
|
||||||
|
WebPChunkIterator iccp;
|
||||||
} kParams;
|
} kParams;
|
||||||
|
|
||||||
static void ClearPreviousPic(void) {
|
static void ClearPreviousPic(void) {
|
||||||
@ -67,10 +79,128 @@ static void ClearParams(void) {
|
|||||||
ClearPreviousPic();
|
ClearPreviousPic();
|
||||||
WebPDataClear(&kParams.data);
|
WebPDataClear(&kParams.data);
|
||||||
WebPDemuxReleaseIterator(&kParams.frameiter);
|
WebPDemuxReleaseIterator(&kParams.frameiter);
|
||||||
|
WebPDemuxReleaseChunkIterator(&kParams.iccp);
|
||||||
WebPDemuxDelete(kParams.dmux);
|
WebPDemuxDelete(kParams.dmux);
|
||||||
kParams.dmux = NULL;
|
kParams.dmux = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Color profile handling
|
||||||
|
static int ApplyColorProfile(const WebPData* const profile,
|
||||||
|
WebPDecBuffer* const rgba) {
|
||||||
|
#ifdef WEBP_HAVE_QCMS
|
||||||
|
int i, ok = 0;
|
||||||
|
uint8_t* line;
|
||||||
|
uint8_t major_revision;
|
||||||
|
qcms_profile* input_profile = NULL;
|
||||||
|
qcms_profile* output_profile = NULL;
|
||||||
|
qcms_transform* transform = NULL;
|
||||||
|
const qcms_data_type input_type = QCMS_DATA_RGBA_8;
|
||||||
|
const qcms_data_type output_type = QCMS_DATA_RGBA_8;
|
||||||
|
const qcms_intent intent = QCMS_INTENT_DEFAULT;
|
||||||
|
|
||||||
|
if (profile == NULL || rgba == NULL) return 0;
|
||||||
|
if (profile->bytes == NULL || profile->size < 10) return 1;
|
||||||
|
major_revision = profile->bytes[8];
|
||||||
|
|
||||||
|
qcms_enable_iccv4();
|
||||||
|
input_profile = qcms_profile_from_memory(profile->bytes, profile->size);
|
||||||
|
// qcms_profile_is_bogus() is broken with ICCv4.
|
||||||
|
if (input_profile == NULL ||
|
||||||
|
(major_revision < 4 && qcms_profile_is_bogus(input_profile))) {
|
||||||
|
fprintf(stderr, "Color profile is bogus!\n");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
output_profile = qcms_profile_sRGB();
|
||||||
|
if (output_profile == NULL) {
|
||||||
|
fprintf(stderr, "Error creating output color profile!\n");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
qcms_profile_precache_output_transform(output_profile);
|
||||||
|
transform = qcms_transform_create(input_profile, input_type,
|
||||||
|
output_profile, output_type,
|
||||||
|
intent);
|
||||||
|
if (transform == NULL) {
|
||||||
|
fprintf(stderr, "Error creating color transform!\n");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = rgba->u.RGBA.rgba;
|
||||||
|
for (i = 0; i < rgba->height; ++i, line += rgba->u.RGBA.stride) {
|
||||||
|
qcms_transform_data(transform, line, line, rgba->width);
|
||||||
|
}
|
||||||
|
ok = 1;
|
||||||
|
|
||||||
|
Error:
|
||||||
|
if (input_profile != NULL) qcms_profile_release(input_profile);
|
||||||
|
if (output_profile != NULL) qcms_profile_release(output_profile);
|
||||||
|
if (transform != NULL) qcms_transform_release(transform);
|
||||||
|
return ok;
|
||||||
|
#else
|
||||||
|
(void)profile;
|
||||||
|
(void)rgba;
|
||||||
|
return 1;
|
||||||
|
#endif // WEBP_HAVE_QCMS
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// File decoding
|
||||||
|
|
||||||
|
static int Decode(void) { // Fills kParams.frameiter
|
||||||
|
const WebPIterator* const iter = &kParams.frameiter;
|
||||||
|
WebPDecoderConfig* const config = kParams.config;
|
||||||
|
WebPDecBuffer* const output_buffer = &config->output;
|
||||||
|
int ok = 0;
|
||||||
|
|
||||||
|
ClearPreviousPic();
|
||||||
|
output_buffer->colorspace = MODE_RGBA;
|
||||||
|
ok = (WebPDecode(iter->fragment.bytes, iter->fragment.size,
|
||||||
|
config) == VP8_STATUS_OK);
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "Decoding of frame #%d failed!\n", iter->frame_num);
|
||||||
|
} else {
|
||||||
|
kParams.pic = output_buffer;
|
||||||
|
if (kParams.use_color_profile) {
|
||||||
|
ok = ApplyColorProfile(&kParams.iccp.chunk, output_buffer);
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "Applying color profile to frame #%d failed!\n",
|
||||||
|
iter->frame_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_callback(int what) {
|
||||||
|
if (what == 0 && !kParams.done) {
|
||||||
|
int duration = 0;
|
||||||
|
if (kParams.dmux != NULL) {
|
||||||
|
WebPIterator* const iter = &kParams.frameiter;
|
||||||
|
if (!WebPDemuxNextFrame(iter)) {
|
||||||
|
WebPDemuxReleaseIterator(iter);
|
||||||
|
if (WebPDemuxGetFrame(kParams.dmux, 1, iter)) {
|
||||||
|
--kParams.loop_count;
|
||||||
|
kParams.done = (kParams.loop_count == 0);
|
||||||
|
} else {
|
||||||
|
kParams.decoding_error = 1;
|
||||||
|
kParams.done = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
duration = iter->duration;
|
||||||
|
}
|
||||||
|
if (!Decode()) {
|
||||||
|
kParams.decoding_error = 1;
|
||||||
|
kParams.done = 1;
|
||||||
|
} else {
|
||||||
|
glutPostRedisplay();
|
||||||
|
glutTimerFunc(duration, decode_callback, what);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Callbacks
|
// Callbacks
|
||||||
|
|
||||||
@ -84,6 +214,24 @@ static void HandleKey(unsigned char key, int pos_x, int pos_y) {
|
|||||||
ClearParams();
|
ClearParams();
|
||||||
exit(0);
|
exit(0);
|
||||||
#endif
|
#endif
|
||||||
|
} else if (key == 'c') {
|
||||||
|
if (kParams.has_color_profile && !kParams.decoding_error) {
|
||||||
|
kParams.use_color_profile = 1 - kParams.use_color_profile;
|
||||||
|
|
||||||
|
if (kParams.has_animation) {
|
||||||
|
// Restart the completed animation to pickup the color profile change.
|
||||||
|
if (kParams.done && kParams.loop_count == 0) {
|
||||||
|
kParams.loop_count =
|
||||||
|
(int)WebPDemuxGetI(kParams.dmux, WEBP_FF_LOOP_COUNT) + 1;
|
||||||
|
kParams.done = 0;
|
||||||
|
// Start the decode loop immediately.
|
||||||
|
glutTimerFunc(0, decode_callback, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Decode();
|
||||||
|
glutPostRedisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (key == 'i') {
|
} else if (key == 'i') {
|
||||||
kParams.print_info = 1 - kParams.print_info;
|
kParams.print_info = 1 - kParams.print_info;
|
||||||
glutPostRedisplay();
|
glutPostRedisplay();
|
||||||
@ -141,24 +289,46 @@ static void HandleDisplay(void) {
|
|||||||
glPixelZoom(1, -1);
|
glPixelZoom(1, -1);
|
||||||
xoff = (GLfloat)(2. * iter->x_offset / kParams.canvas_width);
|
xoff = (GLfloat)(2. * iter->x_offset / kParams.canvas_width);
|
||||||
yoff = (GLfloat)(2. * iter->y_offset / kParams.canvas_height);
|
yoff = (GLfloat)(2. * iter->y_offset / kParams.canvas_height);
|
||||||
glRasterPos2f(-1. + xoff, 1. - yoff);
|
glRasterPos2f(-1.f + xoff, 1.f - yoff);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4);
|
||||||
if (iter->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
|
|
||||||
|
if (kParams.prev_frame.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
|
||||||
|
// TODO(later): these offsets and those above should factor in window size.
|
||||||
|
// they will be incorrect if the window is resized.
|
||||||
|
// glScissor() takes window coordinates (0,0 at bottom left).
|
||||||
|
const int window_x = kParams.prev_frame.x_offset;
|
||||||
|
const int window_y = kParams.canvas_height -
|
||||||
|
kParams.prev_frame.y_offset -
|
||||||
|
kParams.prev_frame.height;
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
// Only updated the requested area, not the whole canvas.
|
||||||
|
glScissor(window_x, window_y,
|
||||||
|
kParams.prev_frame.width, kParams.prev_frame.height);
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT); // use clear color
|
glClear(GL_COLOR_BUFFER_BIT); // use clear color
|
||||||
|
DrawCheckerBoard();
|
||||||
|
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
kParams.prev_frame.width = iter->width;
|
||||||
|
kParams.prev_frame.height = iter->height;
|
||||||
|
kParams.prev_frame.x_offset = iter->x_offset;
|
||||||
|
kParams.prev_frame.y_offset = iter->y_offset;
|
||||||
|
kParams.prev_frame.dispose_method = iter->dispose_method;
|
||||||
|
|
||||||
glDrawPixels(pic->width, pic->height,
|
glDrawPixels(pic->width, pic->height,
|
||||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
(GLvoid*)pic->u.RGBA.rgba);
|
(GLvoid*)pic->u.RGBA.rgba);
|
||||||
if (kParams.print_info) {
|
if (kParams.print_info) {
|
||||||
char tmp[32];
|
char tmp[32];
|
||||||
|
|
||||||
glColor4f(0.90, 0.0, 0.90, 1.0);
|
glColor4f(0.90f, 0.0f, 0.90f, 1.0f);
|
||||||
glRasterPos2f(-0.95f, 0.90f);
|
glRasterPos2f(-0.95f, 0.90f);
|
||||||
PrintString(kParams.file_name);
|
PrintString(kParams.file_name);
|
||||||
|
|
||||||
snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height);
|
snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height);
|
||||||
glColor4f(0.90, 0.0, 0.90, 1.0);
|
glColor4f(0.90f, 0.0f, 0.90f, 1.0f);
|
||||||
glRasterPos2f(-0.95f, 0.80f);
|
glRasterPos2f(-0.95f, 0.80f);
|
||||||
PrintString(tmp);
|
PrintString(tmp);
|
||||||
if (iter->x_offset != 0 || iter->y_offset != 0) {
|
if (iter->x_offset != 0 || iter->y_offset != 0) {
|
||||||
@ -192,55 +362,6 @@ static void StartDisplay(void) {
|
|||||||
DrawCheckerBoard();
|
DrawCheckerBoard();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// File decoding
|
|
||||||
|
|
||||||
static int Decode(void) { // Fills kParams.frameiter
|
|
||||||
const WebPIterator* const iter = &kParams.frameiter;
|
|
||||||
WebPDecoderConfig* const config = kParams.config;
|
|
||||||
WebPDecBuffer* const output_buffer = &config->output;
|
|
||||||
int ok = 0;
|
|
||||||
|
|
||||||
ClearPreviousPic();
|
|
||||||
output_buffer->colorspace = MODE_RGBA;
|
|
||||||
ok = (WebPDecode(iter->fragment.bytes, iter->fragment.size,
|
|
||||||
config) == VP8_STATUS_OK);
|
|
||||||
if (!ok) {
|
|
||||||
fprintf(stderr, "Decoding of frame #%d failed!\n", iter->frame_num);
|
|
||||||
} else {
|
|
||||||
kParams.pic = output_buffer;
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void decode_callback(int what) {
|
|
||||||
if (what == 0 && !kParams.done) {
|
|
||||||
int duration = 0;
|
|
||||||
if (kParams.dmux != NULL) {
|
|
||||||
WebPIterator* const iter = &kParams.frameiter;
|
|
||||||
if (!WebPDemuxNextFrame(iter)) {
|
|
||||||
WebPDemuxReleaseIterator(iter);
|
|
||||||
if (WebPDemuxGetFrame(kParams.dmux, 1, iter)) {
|
|
||||||
--kParams.loop_count;
|
|
||||||
kParams.done = (kParams.loop_count == 0);
|
|
||||||
} else {
|
|
||||||
kParams.decoding_error = 1;
|
|
||||||
kParams.done = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
duration = iter->duration;
|
|
||||||
}
|
|
||||||
if (!Decode()) {
|
|
||||||
kParams.decoding_error = 1;
|
|
||||||
kParams.done = 1;
|
|
||||||
} else {
|
|
||||||
glutPostRedisplay();
|
|
||||||
glutTimerFunc(duration, decode_callback, what);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Main
|
// Main
|
||||||
|
|
||||||
@ -249,6 +370,7 @@ static void Help(void) {
|
|||||||
"Decodes the WebP image file and visualize it using OpenGL\n"
|
"Decodes the WebP image file and visualize it using OpenGL\n"
|
||||||
"Options are:\n"
|
"Options are:\n"
|
||||||
" -version .... print version number and exit.\n"
|
" -version .... print version number and exit.\n"
|
||||||
|
" -noicc ....... don't use the icc profile if present.\n"
|
||||||
" -nofancy ..... don't use the fancy YUV420 upscaler.\n"
|
" -nofancy ..... don't use the fancy YUV420 upscaler.\n"
|
||||||
" -nofilter .... disable in-loop filtering.\n"
|
" -nofilter .... disable in-loop filtering.\n"
|
||||||
" -mt .......... use multi-threading.\n"
|
" -mt .......... use multi-threading.\n"
|
||||||
@ -256,6 +378,7 @@ static void Help(void) {
|
|||||||
" -h ....... this help message.\n"
|
" -h ....... this help message.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Keyboard shortcuts:\n"
|
"Keyboard shortcuts:\n"
|
||||||
|
" 'c' ................ toggle use of color profile.\n"
|
||||||
" 'i' ................ overlay file information.\n"
|
" 'i' ................ overlay file information.\n"
|
||||||
" 'q' / 'Q' / ESC .... quit.\n"
|
" 'q' / 'Q' / ESC .... quit.\n"
|
||||||
);
|
);
|
||||||
@ -270,11 +393,14 @@ int main(int argc, char *argv[]) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
kParams.config = &config;
|
kParams.config = &config;
|
||||||
|
kParams.use_color_profile = 1;
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
Help();
|
Help();
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (!strcmp(argv[c], "-noicc")) {
|
||||||
|
kParams.use_color_profile = 0;
|
||||||
} else if (!strcmp(argv[c], "-nofancy")) {
|
} else if (!strcmp(argv[c], "-nofancy")) {
|
||||||
config.options.no_fancy_upsampling = 1;
|
config.options.no_fancy_upsampling = 1;
|
||||||
} else if (!strcmp(argv[c], "-nofilter")) {
|
} else if (!strcmp(argv[c], "-nofilter")) {
|
||||||
@ -327,6 +453,25 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kParams.prev_frame.width = kParams.canvas_width;
|
||||||
|
kParams.prev_frame.height = kParams.canvas_height;
|
||||||
|
kParams.prev_frame.x_offset = kParams.prev_frame.y_offset = 0;
|
||||||
|
kParams.prev_frame.dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;
|
||||||
|
|
||||||
|
memset(&kParams.iccp, 0, sizeof(kParams.iccp));
|
||||||
|
kParams.has_color_profile =
|
||||||
|
!!(WebPDemuxGetI(kParams.dmux, WEBP_FF_FORMAT_FLAGS) & ICCP_FLAG);
|
||||||
|
if (kParams.has_color_profile) {
|
||||||
|
#ifdef WEBP_HAVE_QCMS
|
||||||
|
if (!WebPDemuxGetChunk(kParams.dmux, "ICCP", 1, &kParams.iccp)) goto Error;
|
||||||
|
printf("VP8X: Found color profile\n");
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "Warning: color profile present, but qcms is unavailable!\n"
|
||||||
|
"Build libqcms from Mozilla or Chromium and define WEBP_HAVE_QCMS "
|
||||||
|
"before building.\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (!WebPDemuxGetFrame(kParams.dmux, 1, &kParams.frameiter)) goto Error;
|
if (!WebPDemuxGetFrame(kParams.dmux, 1, &kParams.frameiter)) goto Error;
|
||||||
|
|
||||||
kParams.has_animation = (kParams.frameiter.num_frames > 1);
|
kParams.has_animation = (kParams.frameiter.num_frames > 1);
|
||||||
|
@ -17,12 +17,6 @@
|
|||||||
/* Usage examples:
|
/* Usage examples:
|
||||||
|
|
||||||
Create container WebP file:
|
Create container WebP file:
|
||||||
webpmux -frgm fragment_1.webp +0+0 \
|
|
||||||
-frgm fragment_2.webp +960+0 \
|
|
||||||
-frgm fragment_3.webp +0+576 \
|
|
||||||
-frgm fragment_4.webp +960+576 \
|
|
||||||
-o out_fragment_container.webp
|
|
||||||
|
|
||||||
webpmux -frame anim_1.webp +100+10+10 \
|
webpmux -frame anim_1.webp +100+10+10 \
|
||||||
-frame anim_2.webp +100+25+25+1 \
|
-frame anim_2.webp +100+25+25+1 \
|
||||||
-frame anim_3.webp +100+50+50+1 \
|
-frame anim_3.webp +100+50+50+1 \
|
||||||
@ -52,6 +46,10 @@
|
|||||||
webpmux -version
|
webpmux -version
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -185,6 +183,9 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
|||||||
uint32_t flag;
|
uint32_t flag;
|
||||||
|
|
||||||
WebPMuxError err = WebPMuxGetFeatures(mux, &flag);
|
WebPMuxError err = WebPMuxGetFeatures(mux, &flag);
|
||||||
|
#ifndef WEBP_EXPERIMENTAL_FEATURES
|
||||||
|
if (flag & FRAGMENTS_FLAG) err = WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
#endif
|
||||||
RETURN_IF_ERROR("Failed to retrieve features\n");
|
RETURN_IF_ERROR("Failed to retrieve features\n");
|
||||||
|
|
||||||
if (flag == 0) {
|
if (flag == 0) {
|
||||||
@ -196,7 +197,7 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
|||||||
printf("Features present:");
|
printf("Features present:");
|
||||||
if (flag & ANIMATION_FLAG) printf(" animation");
|
if (flag & ANIMATION_FLAG) printf(" animation");
|
||||||
if (flag & FRAGMENTS_FLAG) printf(" image fragments");
|
if (flag & FRAGMENTS_FLAG) printf(" image fragments");
|
||||||
if (flag & ICCP_FLAG) printf(" icc profile");
|
if (flag & ICCP_FLAG) printf(" ICC profile");
|
||||||
if (flag & EXIF_FLAG) printf(" EXIF metadata");
|
if (flag & EXIF_FLAG) printf(" EXIF metadata");
|
||||||
if (flag & XMP_FLAG) printf(" XMP metadata");
|
if (flag & XMP_FLAG) printf(" XMP metadata");
|
||||||
if (flag & ALPHA_FLAG) printf(" transparency");
|
if (flag & ALPHA_FLAG) printf(" transparency");
|
||||||
@ -231,7 +232,7 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
|||||||
RETURN_IF_ERROR3("Failed to retrieve %s#%d\n", type_str, i);
|
RETURN_IF_ERROR3("Failed to retrieve %s#%d\n", type_str, i);
|
||||||
printf("%3d: %8d %8d ", i, frame.x_offset, frame.y_offset);
|
printf("%3d: %8d %8d ", i, frame.x_offset, frame.y_offset);
|
||||||
if (is_anim) printf("%8d %7d ", frame.duration, frame.dispose_method);
|
if (is_anim) printf("%8d %7d ", frame.duration, frame.dispose_method);
|
||||||
printf("%10zu\n", frame.bitstream.size);
|
printf("%10d\n", (int)frame.bitstream.size);
|
||||||
WebPDataClear(&frame.bitstream);
|
WebPDataClear(&frame.bitstream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,28 +242,28 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
|||||||
WebPData icc_profile;
|
WebPData icc_profile;
|
||||||
err = WebPMuxGetChunk(mux, "ICCP", &icc_profile);
|
err = WebPMuxGetChunk(mux, "ICCP", &icc_profile);
|
||||||
RETURN_IF_ERROR("Failed to retrieve the ICC profile\n");
|
RETURN_IF_ERROR("Failed to retrieve the ICC profile\n");
|
||||||
printf("Size of the ICC profile data: %zu\n", icc_profile.size);
|
printf("Size of the ICC profile data: %d\n", (int)icc_profile.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag & EXIF_FLAG) {
|
if (flag & EXIF_FLAG) {
|
||||||
WebPData exif;
|
WebPData exif;
|
||||||
err = WebPMuxGetChunk(mux, "EXIF", &exif);
|
err = WebPMuxGetChunk(mux, "EXIF", &exif);
|
||||||
RETURN_IF_ERROR("Failed to retrieve the EXIF metadata\n");
|
RETURN_IF_ERROR("Failed to retrieve the EXIF metadata\n");
|
||||||
printf("Size of the EXIF metadata: %zu\n", exif.size);
|
printf("Size of the EXIF metadata: %d\n", (int)exif.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag & XMP_FLAG) {
|
if (flag & XMP_FLAG) {
|
||||||
WebPData xmp;
|
WebPData xmp;
|
||||||
err = WebPMuxGetChunk(mux, "XMP ", &xmp);
|
err = WebPMuxGetChunk(mux, "XMP ", &xmp);
|
||||||
RETURN_IF_ERROR("Failed to retrieve the XMP metadata\n");
|
RETURN_IF_ERROR("Failed to retrieve the XMP metadata\n");
|
||||||
printf("Size of the XMP metadata: %zu\n", xmp.size);
|
printf("Size of the XMP metadata: %d\n", (int)xmp.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flag & ALPHA_FLAG) && !(flag & (ANIMATION_FLAG | FRAGMENTS_FLAG))) {
|
if ((flag & ALPHA_FLAG) && !(flag & (ANIMATION_FLAG | FRAGMENTS_FLAG))) {
|
||||||
WebPMuxFrameInfo image;
|
WebPMuxFrameInfo image;
|
||||||
err = WebPMuxGetFrame(mux, 1, &image);
|
err = WebPMuxGetFrame(mux, 1, &image);
|
||||||
RETURN_IF_ERROR("Failed to retrieve the image\n");
|
RETURN_IF_ERROR("Failed to retrieve the image\n");
|
||||||
printf("Size of the image (with alpha): %zu\n", image.bitstream.size);
|
printf("Size of the image (with alpha): %d\n", (int)image.bitstream.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
@ -272,7 +273,9 @@ static void PrintHelp(void) {
|
|||||||
printf("Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT\n");
|
printf("Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT\n");
|
||||||
printf(" webpmux -set SET_OPTIONS INPUT -o OUTPUT\n");
|
printf(" webpmux -set SET_OPTIONS INPUT -o OUTPUT\n");
|
||||||
printf(" webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT\n");
|
printf(" webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT\n");
|
||||||
|
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||||
printf(" webpmux -frgm FRAGMENT_OPTIONS [-frgm...] -o OUTPUT\n");
|
printf(" webpmux -frgm FRAGMENT_OPTIONS [-frgm...] -o OUTPUT\n");
|
||||||
|
#endif
|
||||||
printf(" webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]"
|
printf(" webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]"
|
||||||
"\n");
|
"\n");
|
||||||
printf(" [-bgcolor BACKGROUND_COLOR] -o OUTPUT\n");
|
printf(" [-bgcolor BACKGROUND_COLOR] -o OUTPUT\n");
|
||||||
@ -286,7 +289,9 @@ static void PrintHelp(void) {
|
|||||||
printf(" icc Get ICC profile.\n");
|
printf(" icc Get ICC profile.\n");
|
||||||
printf(" exif Get EXIF metadata.\n");
|
printf(" exif Get EXIF metadata.\n");
|
||||||
printf(" xmp Get XMP metadata.\n");
|
printf(" xmp Get XMP metadata.\n");
|
||||||
|
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||||
printf(" frgm n Get nth fragment.\n");
|
printf(" frgm n Get nth fragment.\n");
|
||||||
|
#endif
|
||||||
printf(" frame n Get nth frame.\n");
|
printf(" frame n Get nth frame.\n");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@ -306,6 +311,7 @@ static void PrintHelp(void) {
|
|||||||
printf(" exif Strip EXIF metadata.\n");
|
printf(" exif Strip EXIF metadata.\n");
|
||||||
printf(" xmp Strip XMP metadata.\n");
|
printf(" xmp Strip XMP metadata.\n");
|
||||||
|
|
||||||
|
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("FRAGMENT_OPTIONS(i):\n");
|
printf("FRAGMENT_OPTIONS(i):\n");
|
||||||
printf(" Create fragmented image.\n");
|
printf(" Create fragmented image.\n");
|
||||||
@ -313,6 +319,7 @@ static void PrintHelp(void) {
|
|||||||
printf(" where: 'file_i' is the i'th fragment (WebP format),\n");
|
printf(" where: 'file_i' is the i'th fragment (WebP format),\n");
|
||||||
printf(" 'xi','yi' specify the image offset for this fragment."
|
printf(" 'xi','yi' specify the image offset for this fragment."
|
||||||
"\n");
|
"\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("FRAME_OPTIONS(i):\n");
|
printf("FRAME_OPTIONS(i):\n");
|
||||||
@ -375,7 +382,8 @@ static int WriteData(const char* filename, const WebPData* const webpdata) {
|
|||||||
if (fwrite(webpdata->bytes, webpdata->size, 1, fout) != 1) {
|
if (fwrite(webpdata->bytes, webpdata->size, 1, fout) != 1) {
|
||||||
fprintf(stderr, "Error writing file %s!\n", filename);
|
fprintf(stderr, "Error writing file %s!\n", filename);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Saved file %s (%zu bytes)\n", filename, webpdata->size);
|
fprintf(stderr, "Saved file %s (%d bytes)\n",
|
||||||
|
filename, (int)webpdata->size);
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
if (fout != stdout) fclose(fout);
|
if (fout != stdout) fclose(fout);
|
||||||
@ -596,6 +604,7 @@ static int ParseCommandLine(int argc, const char* argv[],
|
|||||||
arg->params_ = argv[i + 1];
|
arg->params_ = argv[i + 1];
|
||||||
++feature_arg_index;
|
++feature_arg_index;
|
||||||
i += 2;
|
i += 2;
|
||||||
|
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||||
} else if (!strcmp(argv[i], "-frgm")) {
|
} else if (!strcmp(argv[i], "-frgm")) {
|
||||||
CHECK_NUM_ARGS_LESS(3, ErrParse);
|
CHECK_NUM_ARGS_LESS(3, ErrParse);
|
||||||
if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) {
|
if (ACTION_IS_NIL || config->action_type_ == ACTION_SET) {
|
||||||
@ -612,6 +621,7 @@ static int ParseCommandLine(int argc, const char* argv[],
|
|||||||
arg->params_ = argv[i + 2];
|
arg->params_ = argv[i + 2];
|
||||||
++feature_arg_index;
|
++feature_arg_index;
|
||||||
i += 3;
|
i += 3;
|
||||||
|
#endif
|
||||||
} else if (!strcmp(argv[i], "-o")) {
|
} else if (!strcmp(argv[i], "-o")) {
|
||||||
CHECK_NUM_ARGS_LESS(2, ErrParse);
|
CHECK_NUM_ARGS_LESS(2, ErrParse);
|
||||||
config->output_ = argv[i + 1];
|
config->output_ = argv[i + 1];
|
||||||
@ -660,8 +670,12 @@ static int ParseCommandLine(int argc, const char* argv[],
|
|||||||
} else {
|
} else {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||||
} else if ((!strcmp(argv[i], "frame") ||
|
} else if ((!strcmp(argv[i], "frame") ||
|
||||||
!strcmp(argv[i], "frgm")) &&
|
!strcmp(argv[i], "frgm")) &&
|
||||||
|
#else
|
||||||
|
} else if (!strcmp(argv[i], "frame") &&
|
||||||
|
#endif
|
||||||
(config->action_type_ == ACTION_GET)) {
|
(config->action_type_ == ACTION_GET)) {
|
||||||
CHECK_NUM_ARGS_LESS(2, ErrParse);
|
CHECK_NUM_ARGS_LESS(2, ErrParse);
|
||||||
feature->type_ = (!strcmp(argv[i], "frame")) ? FEATURE_ANMF :
|
feature->type_ = (!strcmp(argv[i], "frame")) ? FEATURE_ANMF :
|
||||||
@ -763,12 +777,12 @@ static int InitializeConfig(int argc, const char* argv[],
|
|||||||
// Processing.
|
// Processing.
|
||||||
|
|
||||||
static int GetFrameFragment(const WebPMux* mux,
|
static int GetFrameFragment(const WebPMux* mux,
|
||||||
const WebPMuxConfig* config, int isFrame) {
|
const WebPMuxConfig* config, int is_frame) {
|
||||||
WebPMuxError err = WEBP_MUX_OK;
|
WebPMuxError err = WEBP_MUX_OK;
|
||||||
WebPMux* mux_single = NULL;
|
WebPMux* mux_single = NULL;
|
||||||
long num = 0;
|
long num = 0;
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
const WebPChunkId id = isFrame ? WEBP_CHUNK_ANMF : WEBP_CHUNK_FRGM;
|
const WebPChunkId id = is_frame ? WEBP_CHUNK_ANMF : WEBP_CHUNK_FRGM;
|
||||||
WebPMuxFrameInfo info;
|
WebPMuxFrameInfo info;
|
||||||
WebPDataInit(&info.bitstream);
|
WebPDataInit(&info.bitstream);
|
||||||
|
|
||||||
|
@ -168,7 +168,10 @@ LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS)
|
|||||||
|
|
||||||
HDRS_INSTALLED = \
|
HDRS_INSTALLED = \
|
||||||
src/webp/decode.h \
|
src/webp/decode.h \
|
||||||
|
src/webp/demux.h \
|
||||||
src/webp/encode.h \
|
src/webp/encode.h \
|
||||||
|
src/webp/mux.h \
|
||||||
|
src/webp/mux_types.h \
|
||||||
src/webp/types.h \
|
src/webp/types.h \
|
||||||
|
|
||||||
HDRS = \
|
HDRS = \
|
||||||
@ -191,22 +194,21 @@ HDRS = \
|
|||||||
src/utils/quant_levels_dec.h \
|
src/utils/quant_levels_dec.h \
|
||||||
src/utils/rescaler.h \
|
src/utils/rescaler.h \
|
||||||
src/utils/thread.h \
|
src/utils/thread.h \
|
||||||
src/webp/demux.h \
|
|
||||||
src/webp/format_constants.h \
|
src/webp/format_constants.h \
|
||||||
src/webp/mux.h \
|
|
||||||
src/webp/mux_types.h \
|
|
||||||
$(HDRS_INSTALLED) \
|
$(HDRS_INSTALLED) \
|
||||||
|
|
||||||
OUT_LIBS = examples/libexample_util.a src/libwebpdecoder.a src/libwebp.a
|
OUT_LIBS = examples/libexample_util.a src/libwebpdecoder.a src/libwebp.a
|
||||||
OUT_EXAMPLES = examples/cwebp examples/dwebp
|
OUT_EXAMPLES = examples/cwebp examples/dwebp
|
||||||
|
EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux
|
||||||
|
|
||||||
OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES)
|
OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES)
|
||||||
ifeq ($(MAKECMDGOALS),clean)
|
ifeq ($(MAKECMDGOALS),clean)
|
||||||
OUTPUT += examples/gif2webp examples/vwebp examples/webpmux
|
OUTPUT += $(EXTRA_EXAMPLES)
|
||||||
OUTPUT += src/demux/libwebpdemux.a src/mux/libwebpmux.a
|
OUTPUT += src/demux/libwebpdemux.a src/mux/libwebpmux.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: ex
|
ex: $(OUT_EXAMPLES)
|
||||||
|
all: ex $(EXTRA_EXAMPLES)
|
||||||
|
|
||||||
$(EX_FORMAT_DEC_OBJS): %.o: %.h
|
$(EX_FORMAT_DEC_OBJS): %.o: %.h
|
||||||
|
|
||||||
@ -222,8 +224,6 @@ src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS)
|
|||||||
%.a:
|
%.a:
|
||||||
$(AR) $(ARFLAGS) $@ $^
|
$(AR) $(ARFLAGS) $@ $^
|
||||||
|
|
||||||
ex: $(OUT_EXAMPLES)
|
|
||||||
|
|
||||||
examples/cwebp: examples/cwebp.o $(EX_FORMAT_DEC_OBJS)
|
examples/cwebp: examples/cwebp.o $(EX_FORMAT_DEC_OBJS)
|
||||||
examples/dwebp: examples/dwebp.o
|
examples/dwebp: examples/dwebp.o
|
||||||
examples/gif2webp: examples/gif2webp.o
|
examples/gif2webp: examples/gif2webp.o
|
||||||
@ -242,18 +242,21 @@ examples/vwebp: EXTRA_LIBS += $(GL_LIBS)
|
|||||||
examples/webpmux: examples/libexample_util.a src/mux/libwebpmux.a
|
examples/webpmux: examples/libexample_util.a src/mux/libwebpmux.a
|
||||||
examples/webpmux: src/libwebpdecoder.a
|
examples/webpmux: src/libwebpdecoder.a
|
||||||
|
|
||||||
$(OUT_EXAMPLES) examples/gif2webp examples/vwebp examples/webpmux:
|
$(OUT_EXAMPLES) $(EXTRA_EXAMPLES):
|
||||||
$(CC) -o $@ $^ $(LDFLAGS)
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
dist: DESTDIR := dist
|
dist: DESTDIR := dist
|
||||||
|
dist: OUT_EXAMPLES += $(EXTRA_EXAMPLES)
|
||||||
dist: all
|
dist: all
|
||||||
$(INSTALL) -m755 -d $(DESTDIR)/include/webp \
|
$(INSTALL) -m755 -d $(DESTDIR)/include/webp \
|
||||||
$(DESTDIR)/doc $(DESTDIR)/lib
|
$(DESTDIR)/doc $(DESTDIR)/lib
|
||||||
$(INSTALL) -m755 -s $(OUT_EXAMPLES) $(DESTDIR)
|
$(INSTALL) -m755 -s $(OUT_EXAMPLES) $(DESTDIR)
|
||||||
$(INSTALL) -m644 $(HDRS_INSTALLED) $(DESTDIR)/include/webp
|
$(INSTALL) -m644 $(HDRS_INSTALLED) $(DESTDIR)/include/webp
|
||||||
$(INSTALL) -m644 src/libwebp.a $(DESTDIR)/lib
|
$(INSTALL) -m644 src/libwebp.a $(DESTDIR)/lib
|
||||||
|
$(INSTALL) -m644 src/demux/libwebpdemux.a $(DESTDIR)/lib
|
||||||
|
$(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib
|
||||||
umask 022; \
|
umask 022; \
|
||||||
for m in man/[cd]webp.1; do \
|
for m in man/[cd]webp.1 man/gif2webp.1 man/webpmux.1; do \
|
||||||
basenam=$$(basename $$m .1); \
|
basenam=$$(basename $$m .1); \
|
||||||
$(GROFF) -t -e -man -T utf8 $$m \
|
$(GROFF) -t -e -man -T utf8 $$m \
|
||||||
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \
|
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH CWEBP 1 "March 8, 2013"
|
.TH CWEBP 1 "March 13, 2013"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
cwebp \- compress an image file to a WebP file
|
cwebp \- compress an image file to a WebP file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -200,7 +200,7 @@ Specify the hint about input image type. Possible values are:
|
|||||||
.BI \-metadata " string
|
.BI \-metadata " string
|
||||||
A comma separated list of metadata to copy from the input to the output if
|
A comma separated list of metadata to copy from the input to the output if
|
||||||
present.
|
present.
|
||||||
Valid values: \fBall\fP, \fBnone\fP, \fBexif\fP, \fBiccp\fP, \fBxmp\fP.
|
Valid values: \fBall\fP, \fBnone\fP, \fBexif\fP, \fBicc\fP, \fBxmp\fP.
|
||||||
The default is \fBnone\fP.
|
The default is \fBnone\fP.
|
||||||
|
|
||||||
Note: each input format may not support all combinations.
|
Note: each input format may not support all combinations.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH WEBPMUX 1 "February 26, 2013"
|
.TH WEBPMUX 1 "March 16, 2013"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
webpmux \- command line tool to create WebP Mux/container file.
|
webpmux \- command line tool to create WebP Mux/container file.
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -21,11 +21,6 @@ webpmux \- command line tool to create WebP Mux/container file.
|
|||||||
.B \-o
|
.B \-o
|
||||||
.I OUTPUT
|
.I OUTPUT
|
||||||
.br
|
.br
|
||||||
.B webpmux \-frgm
|
|
||||||
.I FRAGMENT_OPTIONS
|
|
||||||
.B [ \-frgm ... ] \-o
|
|
||||||
.I OUTPUT
|
|
||||||
.br
|
|
||||||
.B webpmux \-frame
|
.B webpmux \-frame
|
||||||
.I FRAME_OPTIONS
|
.I FRAME_OPTIONS
|
||||||
.B [ \-frame ... ] [ \-loop
|
.B [ \-frame ... ] [ \-loop
|
||||||
@ -64,9 +59,6 @@ Get EXIF metadata.
|
|||||||
.B xmp
|
.B xmp
|
||||||
Get XMP metadata.
|
Get XMP metadata.
|
||||||
.TP
|
.TP
|
||||||
.BI frgm " n
|
|
||||||
Get nth fragment.
|
|
||||||
.TP
|
|
||||||
.BI frame " n
|
.BI frame " n
|
||||||
Get nth frame.
|
Get nth frame.
|
||||||
|
|
||||||
@ -98,12 +90,6 @@ Strip EXIF metadata.
|
|||||||
.B xmp
|
.B xmp
|
||||||
Strip XMP metadata.
|
Strip XMP metadata.
|
||||||
|
|
||||||
.SS FRAGMENT_OPTIONS (\-frgm)
|
|
||||||
.TP
|
|
||||||
.I file_i +xi+yi
|
|
||||||
Where: 'file_i' is the i'th fragment (WebP format) and 'xi','yi' specify the
|
|
||||||
image offset for this fragment.
|
|
||||||
|
|
||||||
.SS FRAME_OPTIONS (\-frame)
|
.SS FRAME_OPTIONS (\-frame)
|
||||||
.TP
|
.TP
|
||||||
.I file_i +di[+xi+yi[+mi]]
|
.I file_i +di[+xi+yi[+mi]]
|
||||||
@ -163,18 +149,13 @@ webpmux \-get exif exif_container.webp \-o image_metadata.exif
|
|||||||
.br
|
.br
|
||||||
webpmux \-strip exif exif_container.webp \-o without_exif.webp
|
webpmux \-strip exif exif_container.webp \-o without_exif.webp
|
||||||
.br
|
.br
|
||||||
webpmux \-frame anim_1.webp +0+0+0 \-frame anim_2.webp +50+50+0 \-loop 10
|
webpmux \-frame anim_1.webp +100 \-frame anim_2.webp +100+50+50 \-loop 10
|
||||||
.br
|
.br
|
||||||
.RS 8
|
.RS 8
|
||||||
\-bgcolor 255,255,255,255 \-o anim_container.webp
|
\-bgcolor 255,255,255,255 \-o anim_container.webp
|
||||||
.RE
|
.RE
|
||||||
.br
|
.br
|
||||||
webpmux \-get frame 2 anim_container.webp \-o frame_2.webp
|
webpmux \-get frame 2 anim_container.webp \-o frame_2.webp
|
||||||
.br
|
|
||||||
webpmux \-tile tile_1.webp +0+0 \-tile tile_2.webp +960+0 \-tile tile_3.webp
|
|
||||||
+0+576 \-tile tile_4.webp +960+576 \-o tile_container.webp
|
|
||||||
.br
|
|
||||||
webpmux \-get tile 2 tile_container.webp \-o tile_2.webp
|
|
||||||
|
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
\fBwebpmux\fP is written by the WebP team.
|
\fBwebpmux\fP is written by the WebP team.
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
SUBDIRS = dec enc dsp utils
|
# The mux and demux libraries depend on libwebp, thus the '.' to force the
|
||||||
|
# build order so it's available to them.
|
||||||
|
SUBDIRS = dec enc dsp utils .
|
||||||
if WANT_MUX
|
if WANT_MUX
|
||||||
SUBDIRS += mux
|
SUBDIRS += mux
|
||||||
endif
|
endif
|
||||||
@ -13,11 +15,14 @@ if BUILD_LIBWEBPDECODER
|
|||||||
lib_LTLIBRARIES += libwebpdecoder.la
|
lib_LTLIBRARIES += libwebpdecoder.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
common_HEADERS =
|
||||||
|
common_HEADERS += webp/decode.h
|
||||||
|
common_HEADERS += webp/types.h
|
||||||
|
commondir = $(includedir)/webp
|
||||||
|
|
||||||
libwebp_la_SOURCES =
|
libwebp_la_SOURCES =
|
||||||
libwebpinclude_HEADERS =
|
libwebpinclude_HEADERS =
|
||||||
libwebpinclude_HEADERS += webp/decode.h
|
|
||||||
libwebpinclude_HEADERS += webp/encode.h
|
libwebpinclude_HEADERS += webp/encode.h
|
||||||
libwebpinclude_HEADERS += webp/types.h
|
|
||||||
noinst_HEADERS =
|
noinst_HEADERS =
|
||||||
noinst_HEADERS += webp/format_constants.h
|
noinst_HEADERS += webp/format_constants.h
|
||||||
|
|
||||||
@ -31,15 +36,12 @@ 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 4:1:0
|
libwebp_la_LDFLAGS = -no-undefined -version-info 4:2:0
|
||||||
libwebpincludedir = $(includedir)/webp
|
libwebpincludedir = $(includedir)/webp
|
||||||
pkgconfig_DATA = libwebp.pc
|
pkgconfig_DATA = libwebp.pc
|
||||||
|
|
||||||
if BUILD_LIBWEBPDECODER
|
if BUILD_LIBWEBPDECODER
|
||||||
libwebpdecoder_la_SOURCES =
|
libwebpdecoder_la_SOURCES =
|
||||||
libwebpdecoderinclude_HEADERS =
|
|
||||||
libwebpdecoderinclude_HEADERS += webp/decode.h
|
|
||||||
libwebpdecoderinclude_HEADERS += webp/types.h
|
|
||||||
|
|
||||||
libwebpdecoder_la_LIBADD =
|
libwebpdecoder_la_LIBADD =
|
||||||
libwebpdecoder_la_LIBADD += dec/libwebpdecode.la
|
libwebpdecoder_la_LIBADD += dec/libwebpdecode.la
|
||||||
@ -47,7 +49,6 @@ if BUILD_LIBWEBPDECODER
|
|||||||
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
||||||
|
|
||||||
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 0:0:0
|
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 0:0:0
|
||||||
libwebpdecoderincludedir = $(includedir)/webp
|
|
||||||
pkgconfig_DATA += libwebpdecoder.pc
|
pkgconfig_DATA += libwebpdecoder.pc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size,
|
|||||||
int width, int height, int stride, uint8_t* output) {
|
int width, int height, int stride, uint8_t* output) {
|
||||||
uint8_t* decoded_data = NULL;
|
uint8_t* decoded_data = NULL;
|
||||||
const size_t decoded_size = height * width;
|
const size_t decoded_size = height * width;
|
||||||
uint8_t* unfiltered_data = NULL;
|
|
||||||
WEBP_FILTER_TYPE filter;
|
WEBP_FILTER_TYPE filter;
|
||||||
int pre_processing;
|
int pre_processing;
|
||||||
int rsrv;
|
int rsrv;
|
||||||
@ -83,29 +82,19 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
WebPFilterFunc unfilter_func = WebPUnfilters[filter];
|
WebPUnfilterFunc unfilter_func = WebPUnfilters[filter];
|
||||||
if (unfilter_func != NULL) {
|
if (unfilter_func != NULL) {
|
||||||
unfiltered_data = (uint8_t*)malloc(decoded_size);
|
|
||||||
if (unfiltered_data == NULL) {
|
|
||||||
ok = 0;
|
|
||||||
goto Error;
|
|
||||||
}
|
|
||||||
// TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode
|
// TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode
|
||||||
// and apply filter per image-row.
|
// and apply filter per image-row.
|
||||||
unfilter_func(decoded_data, width, height, 1, width, unfiltered_data);
|
unfilter_func(width, height, width, decoded_data);
|
||||||
// Construct raw_data (height x stride) from alpha data (height x width).
|
|
||||||
CopyPlane(unfiltered_data, width, output, stride, width, height);
|
|
||||||
free(unfiltered_data);
|
|
||||||
} else {
|
|
||||||
// Construct raw_data (height x stride) from alpha data (height x width).
|
|
||||||
CopyPlane(decoded_data, width, output, stride, width, height);
|
|
||||||
}
|
}
|
||||||
|
// Construct raw_data (height x stride) from alpha data (height x width).
|
||||||
|
CopyPlane(decoded_data, width, output, stride, width, height);
|
||||||
if (pre_processing == ALPHA_PREPROCESSED_LEVELS) {
|
if (pre_processing == ALPHA_PREPROCESSED_LEVELS) {
|
||||||
ok = DequantizeLevels(decoded_data, width, height);
|
ok = DequantizeLevels(decoded_data, width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Error:
|
|
||||||
if (method != ALPHA_NO_COMPRESSION) {
|
if (method != ALPHA_NO_COMPRESSION) {
|
||||||
free(decoded_data);
|
free(decoded_data);
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@ extern "C" {
|
|||||||
|
|
||||||
// version numbers
|
// version numbers
|
||||||
#define DEC_MAJ_VERSION 0
|
#define DEC_MAJ_VERSION 0
|
||||||
#define DEC_MIN_VERSION 2
|
#define DEC_MIN_VERSION 3
|
||||||
#define DEC_REV_VERSION 1
|
#define DEC_REV_VERSION 0
|
||||||
|
|
||||||
#define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames
|
#define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include "./vp8i.h"
|
#include "./vp8i.h"
|
||||||
#include "./vp8li.h"
|
#include "./vp8li.h"
|
||||||
#include "./webpi.h"
|
#include "./webpi.h"
|
||||||
#include "../webp/format_constants.h"
|
#include "../webp/mux_types.h" // ALPHA_FLAG
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -276,6 +276,7 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
|
|||||||
int* const width,
|
int* const width,
|
||||||
int* const height,
|
int* const height,
|
||||||
int* const has_alpha,
|
int* const has_alpha,
|
||||||
|
int* const has_animation,
|
||||||
WebPHeaderStructure* const headers) {
|
WebPHeaderStructure* const headers) {
|
||||||
int found_riff = 0;
|
int found_riff = 0;
|
||||||
int found_vp8x = 0;
|
int found_vp8x = 0;
|
||||||
@ -309,6 +310,7 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
|
|||||||
return VP8_STATUS_BITSTREAM_ERROR;
|
return VP8_STATUS_BITSTREAM_ERROR;
|
||||||
}
|
}
|
||||||
if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG);
|
if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG);
|
||||||
|
if (has_animation != NULL) *has_animation = !!(flags & ANIMATION_FLAG);
|
||||||
if (found_vp8x && headers == NULL) {
|
if (found_vp8x && headers == NULL) {
|
||||||
return VP8_STATUS_OK; // Return features from VP8X header.
|
return VP8_STATUS_OK; // Return features from VP8X header.
|
||||||
}
|
}
|
||||||
@ -370,10 +372,19 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) {
|
VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) {
|
||||||
|
VP8StatusCode status;
|
||||||
|
int has_animation = 0;
|
||||||
assert(headers != NULL);
|
assert(headers != NULL);
|
||||||
// fill out headers, ignore width/height/has_alpha.
|
// fill out headers, ignore width/height/has_alpha.
|
||||||
return ParseHeadersInternal(headers->data, headers->data_size,
|
status = ParseHeadersInternal(headers->data, headers->data_size,
|
||||||
NULL, NULL, NULL, headers);
|
NULL, NULL, NULL, &has_animation, headers);
|
||||||
|
if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) {
|
||||||
|
// TODO(jzern): full support of animation frames will require API additions.
|
||||||
|
if (has_animation) {
|
||||||
|
status = VP8_STATUS_UNSUPPORTED_FEATURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -625,10 +636,11 @@ static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size,
|
|||||||
}
|
}
|
||||||
DefaultFeatures(features);
|
DefaultFeatures(features);
|
||||||
|
|
||||||
// Only parse enough of the data to retrieve width/height/has_alpha.
|
// Only parse enough of the data to retrieve the features.
|
||||||
return ParseHeadersInternal(data, data_size,
|
return ParseHeadersInternal(data, data_size,
|
||||||
&features->width, &features->height,
|
&features->width, &features->height,
|
||||||
&features->has_alpha, NULL);
|
&features->has_alpha, &features->has_animation,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -61,10 +61,10 @@ typedef struct {
|
|||||||
} WebPHeaderStructure;
|
} WebPHeaderStructure;
|
||||||
|
|
||||||
// Skips over all valid chunks prior to the first VP8/VP8L frame header.
|
// Skips over all valid chunks prior to the first VP8/VP8L frame header.
|
||||||
// Returns VP8_STATUS_OK on success,
|
// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk),
|
||||||
// VP8_STATUS_BITSTREAM_ERROR if an invalid header/chunk is found, and
|
// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE
|
||||||
// VP8_STATUS_NOT_ENOUGH_DATA if case of insufficient data.
|
// in the case of non-decodable features (animation for instance).
|
||||||
// In 'headers', compressed_size, offset, alpha_data, alpha_size and lossless
|
// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless
|
||||||
// fields are updated appropriately upon success.
|
// fields are updated appropriately upon success.
|
||||||
VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
|
VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
|
||||||
|
|
||||||
|
@ -6,7 +6,10 @@ libwebpdemux_la_SOURCES += demux.c
|
|||||||
|
|
||||||
libwebpdemuxinclude_HEADERS =
|
libwebpdemuxinclude_HEADERS =
|
||||||
libwebpdemuxinclude_HEADERS += ../webp/demux.h
|
libwebpdemuxinclude_HEADERS += ../webp/demux.h
|
||||||
|
libwebpdemuxinclude_HEADERS += ../webp/mux_types.h
|
||||||
libwebpdemuxinclude_HEADERS += ../webp/types.h
|
libwebpdemuxinclude_HEADERS += ../webp/types.h
|
||||||
|
|
||||||
libwebpdemux_la_LDFLAGS = -version-info 0:0:0
|
libwebpdemux_la_LIBADD = ../libwebp.la
|
||||||
|
libwebpdemux_la_LDFLAGS = -no-undefined -version-info 0:0:0
|
||||||
libwebpdemuxincludedir = $(includedir)/webp
|
libwebpdemuxincludedir = $(includedir)/webp
|
||||||
|
pkgconfig_DATA = libwebpdemux.pc
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
// WebP container demux.
|
// WebP container demux.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -65,6 +69,7 @@ struct WebPDemuxer {
|
|||||||
uint32_t bgcolor_;
|
uint32_t bgcolor_;
|
||||||
int num_frames_;
|
int num_frames_;
|
||||||
Frame* frames_;
|
Frame* frames_;
|
||||||
|
Frame** frames_tail_;
|
||||||
Chunk* chunks_; // non-image chunks
|
Chunk* chunks_; // non-image chunks
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -179,15 +184,12 @@ static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) {
|
|||||||
// Add a frame to the end of the list, ensuring the last frame is complete.
|
// Add a frame to the end of the list, ensuring the last frame is complete.
|
||||||
// Returns true on success, false otherwise.
|
// Returns true on success, false otherwise.
|
||||||
static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
|
static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
|
||||||
const Frame* last_frame = NULL;
|
const Frame* const last_frame = *dmux->frames_tail_;
|
||||||
Frame** f = &dmux->frames_;
|
|
||||||
while (*f != NULL) {
|
|
||||||
last_frame = *f;
|
|
||||||
f = &(*f)->next_;
|
|
||||||
}
|
|
||||||
if (last_frame != NULL && !last_frame->complete_) return 0;
|
if (last_frame != NULL && !last_frame->complete_) return 0;
|
||||||
*f = frame;
|
|
||||||
|
*dmux->frames_tail_ = frame;
|
||||||
frame->next_ = NULL;
|
frame->next_ = NULL;
|
||||||
|
dmux->frames_tail_ = &frame->next_;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,8 +233,10 @@ static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
|
|||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MKFOURCC('V', 'P', '8', ' '):
|
|
||||||
case MKFOURCC('V', 'P', '8', 'L'):
|
case MKFOURCC('V', 'P', '8', 'L'):
|
||||||
|
if (alpha_chunks > 0) return PARSE_ERROR; // VP8L has its own alpha
|
||||||
|
// fall through
|
||||||
|
case MKFOURCC('V', 'P', '8', ' '):
|
||||||
if (image_chunks == 0) {
|
if (image_chunks == 0) {
|
||||||
// Extract the bitstream features, tolerating failures when the data
|
// Extract the bitstream features, tolerating failures when the data
|
||||||
// is incomplete.
|
// is incomplete.
|
||||||
@ -295,7 +299,7 @@ static ParseStatus NewFrame(const MemBuffer* const mem,
|
|||||||
|
|
||||||
// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow.
|
// Parse a 'ANMF' chunk and any image bearing chunks that immediately follow.
|
||||||
// 'frame_chunk_size' is the previously validated, padded chunk size.
|
// 'frame_chunk_size' is the previously validated, padded chunk size.
|
||||||
static ParseStatus ParseFrame(
|
static ParseStatus ParseAnimationFrame(
|
||||||
WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
|
WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
|
||||||
const int has_frames = !!(dmux->feature_flags_ & ANIMATION_FLAG);
|
const int has_frames = !!(dmux->feature_flags_ & ANIMATION_FLAG);
|
||||||
const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
|
const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
|
||||||
@ -316,8 +320,8 @@ static ParseStatus ParseFrame(
|
|||||||
return PARSE_ERROR;
|
return PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store a frame only if the animation flag is set and all data for this frame
|
// Store a frame only if the animation flag is set there is some data for
|
||||||
// is available.
|
// this frame is available.
|
||||||
status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame,
|
status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame,
|
||||||
NULL);
|
NULL);
|
||||||
if (status != PARSE_ERROR && has_frames && frame->frame_num_ > 0) {
|
if (status != PARSE_ERROR && has_frames && frame->frame_num_ > 0) {
|
||||||
@ -333,6 +337,7 @@ static ParseStatus ParseFrame(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||||
// Parse a 'FRGM' chunk and any image bearing chunks that immediately follow.
|
// Parse a 'FRGM' chunk and any image bearing chunks that immediately follow.
|
||||||
// 'fragment_chunk_size' is the previously validated, padded chunk size.
|
// 'fragment_chunk_size' is the previously validated, padded chunk size.
|
||||||
static ParseStatus ParseFragment(WebPDemuxer* const dmux,
|
static ParseStatus ParseFragment(WebPDemuxer* const dmux,
|
||||||
@ -347,12 +352,12 @@ static ParseStatus ParseFragment(WebPDemuxer* const dmux,
|
|||||||
NewFrame(mem, FRGM_CHUNK_SIZE, fragment_chunk_size, &frame);
|
NewFrame(mem, FRGM_CHUNK_SIZE, fragment_chunk_size, &frame);
|
||||||
if (status != PARSE_OK) return status;
|
if (status != PARSE_OK) return status;
|
||||||
|
|
||||||
frame->is_fragment_ = 1;
|
frame->is_fragment_ = 1;
|
||||||
frame->x_offset_ = 2 * ReadLE24s(mem);
|
frame->x_offset_ = 2 * ReadLE24s(mem);
|
||||||
frame->y_offset_ = 2 * ReadLE24s(mem);
|
frame->y_offset_ = 2 * ReadLE24s(mem);
|
||||||
|
|
||||||
// Store a fragment only if the fragments flag is set and all data for this
|
// Store a fragment only if the fragments flag is set there is some data for
|
||||||
// fragment is available.
|
// this fragment is available.
|
||||||
status = StoreFrame(frame_num, frgm_payload_size, mem, frame, NULL);
|
status = StoreFrame(frame_num, frgm_payload_size, mem, frame, NULL);
|
||||||
if (status != PARSE_ERROR && has_fragments && frame->frame_num_ > 0) {
|
if (status != PARSE_ERROR && has_fragments && frame->frame_num_ > 0) {
|
||||||
added_fragment = AddFrame(dmux, frame);
|
added_fragment = AddFrame(dmux, frame);
|
||||||
@ -366,8 +371,9 @@ static ParseStatus ParseFragment(WebPDemuxer* const dmux,
|
|||||||
if (!added_fragment) free(frame);
|
if (!added_fragment) free(frame);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
#endif // WEBP_EXPERIMENTAL_FEATURES
|
||||||
|
|
||||||
// General chunk storage starting with the header at 'start_offset' allowing
|
// General chunk storage, starting with the header at 'start_offset', allowing
|
||||||
// the user to request the payload via a fourcc string. 'size' includes the
|
// the user to request the payload via a fourcc string. 'size' includes the
|
||||||
// header and the unpadded payload size.
|
// header and the unpadded payload size.
|
||||||
// Returns true on success, false otherwise.
|
// Returns true on success, false otherwise.
|
||||||
@ -424,7 +430,7 @@ static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
|
|||||||
frame = (Frame*)calloc(1, sizeof(*frame));
|
frame = (Frame*)calloc(1, sizeof(*frame));
|
||||||
if (frame == NULL) return PARSE_ERROR;
|
if (frame == NULL) return PARSE_ERROR;
|
||||||
|
|
||||||
// For the single image case, we allow parsing of a partial frame. But we need
|
// For the single image case we allow parsing of a partial frame, but we need
|
||||||
// at least CHUNK_HEADER_SIZE for parsing.
|
// at least CHUNK_HEADER_SIZE for parsing.
|
||||||
status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame,
|
status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame,
|
||||||
&has_vp8l_alpha);
|
&has_vp8l_alpha);
|
||||||
@ -500,6 +506,9 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
|
|||||||
case MKFOURCC('A', 'L', 'P', 'H'):
|
case MKFOURCC('A', 'L', 'P', 'H'):
|
||||||
case MKFOURCC('V', 'P', '8', ' '):
|
case MKFOURCC('V', 'P', '8', ' '):
|
||||||
case MKFOURCC('V', 'P', '8', 'L'): {
|
case MKFOURCC('V', 'P', '8', 'L'): {
|
||||||
|
// check that this isn't an animation (all frames should be in an ANMF).
|
||||||
|
if (anim_chunks > 0) return PARSE_ERROR;
|
||||||
|
|
||||||
Rewind(mem, CHUNK_HEADER_SIZE);
|
Rewind(mem, CHUNK_HEADER_SIZE);
|
||||||
status = ParseSingleImage(dmux);
|
status = ParseSingleImage(dmux);
|
||||||
break;
|
break;
|
||||||
@ -521,13 +530,16 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MKFOURCC('A', 'N', 'M', 'F'): {
|
case MKFOURCC('A', 'N', 'M', 'F'): {
|
||||||
status = ParseFrame(dmux, chunk_size_padded);
|
if (anim_chunks == 0) return PARSE_ERROR; // 'ANIM' precedes frames.
|
||||||
|
status = ParseAnimationFrame(dmux, chunk_size_padded);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||||
case MKFOURCC('F', 'R', 'G', 'M'): {
|
case MKFOURCC('F', 'R', 'G', 'M'): {
|
||||||
status = ParseFragment(dmux, chunk_size_padded);
|
status = ParseFragment(dmux, chunk_size_padded);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
case MKFOURCC('I', 'C', 'C', 'P'): {
|
case MKFOURCC('I', 'C', 'C', 'P'): {
|
||||||
store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG);
|
store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG);
|
||||||
goto Skip;
|
goto Skip;
|
||||||
@ -615,6 +627,9 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
|
|||||||
|
|
||||||
if (f->width_ <= 0 || f->height_ <= 0) return 0;
|
if (f->width_ <= 0 || f->height_ <= 0) return 0;
|
||||||
} else {
|
} else {
|
||||||
|
// There shouldn't be a partial frame in a complete file.
|
||||||
|
if (dmux->state_ == WEBP_DEMUX_DONE) return 0;
|
||||||
|
|
||||||
// Ensure alpha precedes image bitstream.
|
// Ensure alpha precedes image bitstream.
|
||||||
if (alpha->size_ > 0 && image->size_ > 0 &&
|
if (alpha->size_ > 0 && image->size_ > 0 &&
|
||||||
alpha->offset_ > image->offset_) {
|
alpha->offset_ > image->offset_) {
|
||||||
@ -643,6 +658,7 @@ static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) {
|
|||||||
dmux->bgcolor_ = 0xFFFFFFFF; // White background by default.
|
dmux->bgcolor_ = 0xFFFFFFFF; // White background by default.
|
||||||
dmux->canvas_width_ = -1;
|
dmux->canvas_width_ = -1;
|
||||||
dmux->canvas_height_ = -1;
|
dmux->canvas_height_ = -1;
|
||||||
|
dmux->frames_tail_ = &dmux->frames_;
|
||||||
dmux->mem_ = *mem;
|
dmux->mem_ = *mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
src/demux/libwebpdemux.pc.in
Normal file
11
src/demux/libwebpdemux.pc.in
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: libwebpdemux
|
||||||
|
Description: Library for parsing the WebP graphics format container
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Requires: libwebp >= 0.2.0
|
||||||
|
Cflags: -I${includedir}
|
||||||
|
Libs: -L${libdir} -lwebpdemux
|
@ -5,7 +5,10 @@ if BUILD_LIBWEBPDECODER
|
|||||||
noinst_LTLIBRARIES += libwebpdspdecode.la
|
noinst_LTLIBRARIES += libwebpdspdecode.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
COMMON_SOURCES =
|
common_HEADERS = ../webp/types.h
|
||||||
|
commondir = $(includedir)/webp
|
||||||
|
|
||||||
|
COMMON_SOURCES =
|
||||||
COMMON_SOURCES += cpu.c
|
COMMON_SOURCES += cpu.c
|
||||||
COMMON_SOURCES += dec.c
|
COMMON_SOURCES += dec.c
|
||||||
COMMON_SOURCES += dec_neon.c
|
COMMON_SOURCES += dec_neon.c
|
||||||
@ -19,13 +22,12 @@ COMMON_SOURCES += upsampling_sse2.c
|
|||||||
COMMON_SOURCES += yuv.c
|
COMMON_SOURCES += yuv.c
|
||||||
COMMON_SOURCES += yuv.h
|
COMMON_SOURCES += yuv.h
|
||||||
|
|
||||||
ENC_SOURCES =
|
ENC_SOURCES =
|
||||||
ENC_SOURCES += enc.c
|
ENC_SOURCES += enc.c
|
||||||
ENC_SOURCES += enc_neon.c
|
ENC_SOURCES += enc_neon.c
|
||||||
ENC_SOURCES += enc_sse2.c
|
ENC_SOURCES += enc_sse2.c
|
||||||
|
|
||||||
libwebpdsp_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES)
|
libwebpdsp_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES)
|
||||||
libwebpdspinclude_HEADERS = ../webp/types.h
|
|
||||||
|
|
||||||
noinst_HEADERS =
|
noinst_HEADERS =
|
||||||
noinst_HEADERS += ../dec/decode_vp8.h
|
noinst_HEADERS += ../dec/decode_vp8.h
|
||||||
@ -33,13 +35,10 @@ noinst_HEADERS += ../webp/decode.h
|
|||||||
|
|
||||||
libwebpdsp_la_LDFLAGS = -lm
|
libwebpdsp_la_LDFLAGS = -lm
|
||||||
libwebpdsp_la_CPPFLAGS = $(USE_EXPERIMENTAL_CODE) $(USE_SWAP_16BIT_CSP)
|
libwebpdsp_la_CPPFLAGS = $(USE_EXPERIMENTAL_CODE) $(USE_SWAP_16BIT_CSP)
|
||||||
libwebpdspincludedir = $(includedir)/webp
|
|
||||||
|
|
||||||
if BUILD_LIBWEBPDECODER
|
if BUILD_LIBWEBPDECODER
|
||||||
libwebpdspdecode_la_SOURCES = $(COMMON_SOURCES)
|
libwebpdspdecode_la_SOURCES = $(COMMON_SOURCES)
|
||||||
libwebpdspdecodeinclude_HEADERS = $(libwebpdspinclude_HEADERS)
|
|
||||||
|
|
||||||
libwebpdspdecode_la_LDFLAGS = $(libwebpdsp_la_LDFLAGS)
|
libwebpdspdecode_la_LDFLAGS = $(libwebpdsp_la_LDFLAGS)
|
||||||
libwebpdspdecode_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
|
libwebpdspdecode_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
|
||||||
libwebpdspdecodeincludedir = $(libwebpdspincludedir)
|
|
||||||
endif
|
endif
|
||||||
|
@ -631,13 +631,13 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16],
|
|||||||
for (; n < 16; ++n) {
|
for (; n < 16; ++n) {
|
||||||
const int j = kZigzag[n];
|
const int j = kZigzag[n];
|
||||||
const int sign = (in[j] < 0);
|
const int sign = (in[j] < 0);
|
||||||
int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
|
const int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
|
||||||
if (coeff > 2047) coeff = 2047;
|
|
||||||
if (coeff > mtx->zthresh_[j]) {
|
if (coeff > mtx->zthresh_[j]) {
|
||||||
const int Q = mtx->q_[j];
|
const int Q = mtx->q_[j];
|
||||||
const int iQ = mtx->iq_[j];
|
const int iQ = mtx->iq_[j];
|
||||||
const int B = mtx->bias_[j];
|
const int B = mtx->bias_[j];
|
||||||
out[n] = QUANTDIV(coeff, iQ, B);
|
out[n] = QUANTDIV(coeff, iQ, B);
|
||||||
|
if (out[n] > MAX_LEVEL) out[n] = MAX_LEVEL;
|
||||||
if (sign) out[n] = -out[n];
|
if (sign) out[n] = -out[n];
|
||||||
in[j] = out[n] * Q;
|
in[j] = out[n] * Q;
|
||||||
if (out[n]) last = n;
|
if (out[n]) last = n;
|
||||||
|
@ -776,7 +776,7 @@ static int Disto16x16SSE2(const uint8_t* const a, const uint8_t* const b,
|
|||||||
// Simple quantization
|
// Simple quantization
|
||||||
static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
|
static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
|
||||||
int n, const VP8Matrix* const mtx) {
|
int n, const VP8Matrix* const mtx) {
|
||||||
const __m128i max_coeff_2047 = _mm_set1_epi16(2047);
|
const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL);
|
||||||
const __m128i zero = _mm_setzero_si128();
|
const __m128i zero = _mm_setzero_si128();
|
||||||
__m128i coeff0, coeff8;
|
__m128i coeff0, coeff8;
|
||||||
__m128i out0, out8;
|
__m128i out0, out8;
|
||||||
@ -812,10 +812,6 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
|
|||||||
coeff0 = _mm_add_epi16(coeff0, sharpen0);
|
coeff0 = _mm_add_epi16(coeff0, sharpen0);
|
||||||
coeff8 = _mm_add_epi16(coeff8, sharpen8);
|
coeff8 = _mm_add_epi16(coeff8, sharpen8);
|
||||||
|
|
||||||
// if (coeff > 2047) coeff = 2047
|
|
||||||
coeff0 = _mm_min_epi16(coeff0, max_coeff_2047);
|
|
||||||
coeff8 = _mm_min_epi16(coeff8, max_coeff_2047);
|
|
||||||
|
|
||||||
// out = (coeff * iQ + B) >> QFIX;
|
// out = (coeff * iQ + B) >> QFIX;
|
||||||
{
|
{
|
||||||
// doing calculations with 32b precision (QFIX=17)
|
// doing calculations with 32b precision (QFIX=17)
|
||||||
@ -843,9 +839,14 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
|
|||||||
out_04 = _mm_srai_epi32(out_04, QFIX);
|
out_04 = _mm_srai_epi32(out_04, QFIX);
|
||||||
out_08 = _mm_srai_epi32(out_08, QFIX);
|
out_08 = _mm_srai_epi32(out_08, QFIX);
|
||||||
out_12 = _mm_srai_epi32(out_12, QFIX);
|
out_12 = _mm_srai_epi32(out_12, QFIX);
|
||||||
|
|
||||||
// pack result as 16b
|
// pack result as 16b
|
||||||
out0 = _mm_packs_epi32(out_00, out_04);
|
out0 = _mm_packs_epi32(out_00, out_04);
|
||||||
out8 = _mm_packs_epi32(out_08, out_12);
|
out8 = _mm_packs_epi32(out_08, out_12);
|
||||||
|
|
||||||
|
// if (coeff > 2047) coeff = 2047
|
||||||
|
out0 = _mm_min_epi16(out0, max_coeff_2047);
|
||||||
|
out8 = _mm_min_epi16(out8, max_coeff_2047);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get sign back (if (sign[j]) out_n = -out_n)
|
// get sign back (if (sign[j]) out_n = -out_n)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum { YUV_HALF = 1 << (YUV_FIX - 1) };
|
#ifdef WEBP_YUV_USE_TABLE
|
||||||
|
|
||||||
int16_t VP8kVToR[256], VP8kUToB[256];
|
int16_t VP8kVToR[256], VP8kUToB[256];
|
||||||
int32_t VP8kVToG[256], VP8kUToG[256];
|
int32_t VP8kVToG[256], VP8kUToG[256];
|
||||||
@ -62,6 +62,12 @@ void VP8YUVInit(void) {
|
|||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void VP8YUVInit(void) {}
|
||||||
|
|
||||||
|
#endif // WEBP_YUV_USE_TABLE
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
119
src/dsp/yuv.h
119
src/dsp/yuv.h
@ -19,8 +19,9 @@
|
|||||||
// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128)
|
// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128)
|
||||||
// B = 1.164 * (Y-16) + 2.018 * (U-128)
|
// B = 1.164 * (Y-16) + 2.018 * (U-128)
|
||||||
// where Y is in the [16,235] range, and U/V in the [16,240] range.
|
// where Y is in the [16,235] range, and U/V in the [16,240] range.
|
||||||
// But the common term 1.164 * (Y-16) can be handled as an offset in the
|
// In the table-lookup version (WEBP_YUV_USE_TABLE), the common factor
|
||||||
// VP8kClip[] table. So the formulae should be read as:
|
// "1.164 * (Y-16)" can be handled as an offset in the VP8kClip[] table.
|
||||||
|
// So in this case the formulae should be read as:
|
||||||
// R = 1.164 * [Y + 1.371 * (V-128) ] - 18.624
|
// R = 1.164 * [Y + 1.371 * (V-128) ] - 18.624
|
||||||
// G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624
|
// G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624
|
||||||
// B = 1.164 * [Y + 1.733 * (U-128)] - 18.624
|
// B = 1.164 * [Y + 1.733 * (U-128)] - 18.624
|
||||||
@ -33,6 +34,9 @@
|
|||||||
|
|
||||||
#include "../dec/decode_vp8.h"
|
#include "../dec/decode_vp8.h"
|
||||||
|
|
||||||
|
// Define the following to use the LUT-based code:
|
||||||
|
#define WEBP_YUV_USE_TABLE
|
||||||
|
|
||||||
#if defined(WEBP_EXPERIMENTAL_FEATURES)
|
#if defined(WEBP_EXPERIMENTAL_FEATURES)
|
||||||
// Do NOT activate this feature for real compression. This is only experimental!
|
// Do NOT activate this feature for real compression. This is only experimental!
|
||||||
// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace.
|
// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace.
|
||||||
@ -51,9 +55,14 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum { YUV_FIX = 16, // fixed-point precision
|
enum { YUV_FIX = 16, // fixed-point precision
|
||||||
|
YUV_HALF = 1 << (YUV_FIX - 1),
|
||||||
|
YUV_MASK = (256 << YUV_FIX) - 1,
|
||||||
YUV_RANGE_MIN = -227, // min value of r/g/b output
|
YUV_RANGE_MIN = -227, // min value of r/g/b output
|
||||||
YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output
|
YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef WEBP_YUV_USE_TABLE
|
||||||
|
|
||||||
extern int16_t VP8kVToR[256], VP8kUToB[256];
|
extern int16_t VP8kVToR[256], VP8kUToB[256];
|
||||||
extern int32_t VP8kVToG[256], VP8kUToG[256];
|
extern int32_t VP8kVToG[256], VP8kUToG[256];
|
||||||
extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
|
extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
|
||||||
@ -69,6 +78,16 @@ static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
|
|||||||
rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN];
|
rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
|
||||||
|
uint8_t* const bgr) {
|
||||||
|
const int r_off = VP8kVToR[v];
|
||||||
|
const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
|
||||||
|
const int b_off = VP8kUToB[u];
|
||||||
|
bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN];
|
||||||
|
bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
|
||||||
|
bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN];
|
||||||
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
|
static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
|
||||||
uint8_t* const rgb) {
|
uint8_t* const rgb) {
|
||||||
const int r_off = VP8kVToR[v];
|
const int r_off = VP8kVToR[v];
|
||||||
@ -87,12 +106,6 @@ static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
|
|
||||||
uint8_t* const argb) {
|
|
||||||
argb[0] = 0xff;
|
|
||||||
VP8YuvToRgb(y, u, v, argb + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
|
static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
|
||||||
uint8_t* const argb) {
|
uint8_t* const argb) {
|
||||||
const int r_off = VP8kVToR[v];
|
const int r_off = VP8kVToR[v];
|
||||||
@ -110,14 +123,92 @@ static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else // Table-free version (slower on x86)
|
||||||
|
|
||||||
|
// These constants are 16b fixed-point version of ITU-R BT.601 constants
|
||||||
|
#define kYScale 76309 // 1.164 = 255 / 219
|
||||||
|
#define kVToR 104597 // 1.596 = 255 / 112 * 0.701
|
||||||
|
#define kUToG 25674 // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587
|
||||||
|
#define kVToG 53278 // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587
|
||||||
|
#define kUToB 132201 // 2.018 = 255 / 112 * 0.886
|
||||||
|
#define kRCst (-kYScale * 16 - kVToR * 128 + YUV_HALF)
|
||||||
|
#define kGCst (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF)
|
||||||
|
#define kBCst (-kYScale * 16 - kUToB * 128 + YUV_HALF)
|
||||||
|
|
||||||
|
static WEBP_INLINE uint8_t VP8Clip8(int v) {
|
||||||
|
return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> YUV_FIX)
|
||||||
|
: (v < 0) ? 0u : 255u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE uint8_t VP8ClipN(int v, int N) { // clip to N bits
|
||||||
|
return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> (YUV_FIX + (8 - N)))
|
||||||
|
: (v < 0) ? 0u : (255u >> (8 - N));
|
||||||
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE int VP8YUVToR(int y, int v) {
|
||||||
|
return kYScale * y + kVToR * v + kRCst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE int VP8YUVToG(int y, int u, int v) {
|
||||||
|
return kYScale * y - kUToG * u - kVToG * v + kGCst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE int VP8YUVToB(int y, int u) {
|
||||||
|
return kYScale * y + kUToB * u + kBCst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
|
||||||
|
uint8_t* const rgb) {
|
||||||
|
rgb[0] = VP8Clip8(VP8YUVToR(y, v));
|
||||||
|
rgb[1] = VP8Clip8(VP8YUVToG(y, u, v));
|
||||||
|
rgb[2] = VP8Clip8(VP8YUVToB(y, u));
|
||||||
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
|
static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
|
||||||
uint8_t* const bgr) {
|
uint8_t* const bgr) {
|
||||||
const int r_off = VP8kVToR[v];
|
bgr[0] = VP8Clip8(VP8YUVToB(y, u));
|
||||||
const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
|
bgr[1] = VP8Clip8(VP8YUVToG(y, u, v));
|
||||||
const int b_off = VP8kUToB[u];
|
bgr[2] = VP8Clip8(VP8YUVToR(y, v));
|
||||||
bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN];
|
}
|
||||||
bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
|
|
||||||
bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN];
|
static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
|
||||||
|
uint8_t* const rgb) {
|
||||||
|
const int r = VP8Clip8(VP8YUVToR(y, u));
|
||||||
|
const int g = VP8ClipN(VP8YUVToG(y, u, v), 6);
|
||||||
|
const int b = VP8ClipN(VP8YUVToB(y, v), 5);
|
||||||
|
const uint8_t rg = (r & 0xf8) | (g >> 3);
|
||||||
|
const uint8_t gb = (g << 5) | b;
|
||||||
|
#ifdef WEBP_SWAP_16BIT_CSP
|
||||||
|
rgb[0] = gb;
|
||||||
|
rgb[1] = rg;
|
||||||
|
#else
|
||||||
|
rgb[0] = rg;
|
||||||
|
rgb[1] = gb;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
|
||||||
|
uint8_t* const argb) {
|
||||||
|
const int r = VP8Clip8(VP8YUVToR(y, u));
|
||||||
|
const int g = VP8ClipN(VP8YUVToG(y, u, v), 4);
|
||||||
|
const int b = VP8Clip8(VP8YUVToB(y, v));
|
||||||
|
const uint8_t rg = (r & 0xf0) | g;
|
||||||
|
const uint8_t ba = b | 0x0f; // overwrite the lower 4 bits
|
||||||
|
#ifdef WEBP_SWAP_16BIT_CSP
|
||||||
|
argb[0] = ba;
|
||||||
|
argb[1] = rg;
|
||||||
|
#else
|
||||||
|
argb[0] = rg;
|
||||||
|
argb[1] = ba;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WEBP_YUV_USE_TABLE
|
||||||
|
|
||||||
|
static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
|
||||||
|
uint8_t* const argb) {
|
||||||
|
argb[0] = 0xff;
|
||||||
|
VP8YuvToRgb(y, u, v, argb + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v,
|
static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v,
|
||||||
|
@ -127,8 +127,8 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
|
|||||||
VP8BitWriterAppend(bw, &header, ALPHA_HEADER_LEN);
|
VP8BitWriterAppend(bw, &header, ALPHA_HEADER_LEN);
|
||||||
|
|
||||||
filter_func = WebPFilters[filter];
|
filter_func = WebPFilters[filter];
|
||||||
if (filter_func) {
|
if (filter_func != NULL) {
|
||||||
filter_func(data, width, height, 1, width, tmp_alpha);
|
filter_func(data, width, height, width, tmp_alpha);
|
||||||
alpha_src = tmp_alpha;
|
alpha_src = tmp_alpha;
|
||||||
} else {
|
} else {
|
||||||
alpha_src = data;
|
alpha_src = data;
|
||||||
|
@ -75,7 +75,7 @@ const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = {
|
|||||||
|
|
||||||
// fixed costs for coding levels, deduce from the coding tree.
|
// fixed costs for coding levels, deduce from the coding tree.
|
||||||
// This is only the part that doesn't depend on the probability state.
|
// This is only the part that doesn't depend on the probability state.
|
||||||
const uint16_t VP8LevelFixedCosts[2048] = {
|
const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = {
|
||||||
0, 256, 256, 256, 256, 432, 618, 630,
|
0, 256, 256, 256, 256, 432, 618, 630,
|
||||||
731, 640, 640, 828, 901, 948, 1021, 1101,
|
731, 640, 640, 828, 901, 948, 1021, 1101,
|
||||||
1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,
|
1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const uint16_t VP8LevelFixedCosts[2048]; // approximate cost per level
|
// approximate cost per level:
|
||||||
|
extern const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1];
|
||||||
extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p)
|
extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p)
|
||||||
|
|
||||||
// Cost of coding one event with probability 'proba'.
|
// Cost of coding one event with probability 'proba'.
|
||||||
|
@ -901,15 +901,21 @@ int VP8EncLoop(VP8Encoder* const enc) {
|
|||||||
// Single pass using Token Buffer.
|
// Single pass using Token Buffer.
|
||||||
|
|
||||||
#if !defined(DISABLE_TOKEN_BUFFER)
|
#if !defined(DISABLE_TOKEN_BUFFER)
|
||||||
|
|
||||||
|
#define MIN_COUNT 96 // minimum number of macroblocks before updating stats
|
||||||
|
|
||||||
int VP8EncTokenLoop(VP8Encoder* const enc) {
|
int VP8EncTokenLoop(VP8Encoder* const enc) {
|
||||||
int ok;
|
int ok;
|
||||||
// refresh the proba 8 times per pass
|
// Roughly refresh the proba height times per pass
|
||||||
const int max_count = (enc->mb_w_ * enc->mb_h_) >> 3;
|
int max_count = (enc->mb_w_ * enc->mb_h_) >> 3;
|
||||||
int cnt = max_count;
|
int cnt;
|
||||||
VP8EncIterator it;
|
VP8EncIterator it;
|
||||||
VP8Proba* const proba = &enc->proba_;
|
VP8Proba* const proba = &enc->proba_;
|
||||||
const VP8RDLevel rd_opt = enc->rd_opt_level_;
|
const VP8RDLevel rd_opt = enc->rd_opt_level_;
|
||||||
|
|
||||||
|
if (max_count < MIN_COUNT) max_count = MIN_COUNT;
|
||||||
|
cnt = max_count;
|
||||||
|
|
||||||
assert(enc->num_parts_ == 1);
|
assert(enc->num_parts_ == 1);
|
||||||
assert(enc->use_tokens_);
|
assert(enc->use_tokens_);
|
||||||
assert(proba->use_skip_proba_ == 0);
|
assert(proba->use_skip_proba_ == 0);
|
||||||
|
@ -98,8 +98,6 @@ void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static double BitsEntropy(const int* const array, int n) {
|
static double BitsEntropy(const int* const array, int n) {
|
||||||
double retval = 0.;
|
double retval = 0.;
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
@ -149,25 +147,6 @@ static double BitsEntropy(const int* const array, int n) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) {
|
|
||||||
double retval = BitsEntropy(&p->literal_[0], VP8LHistogramNumCodes(p))
|
|
||||||
+ BitsEntropy(&p->red_[0], 256)
|
|
||||||
+ BitsEntropy(&p->blue_[0], 256)
|
|
||||||
+ BitsEntropy(&p->alpha_[0], 256)
|
|
||||||
+ BitsEntropy(&p->distance_[0], NUM_DISTANCE_CODES);
|
|
||||||
// Compute the extra bits cost.
|
|
||||||
int i;
|
|
||||||
for (i = 2; i < NUM_LENGTH_CODES - 2; ++i) {
|
|
||||||
retval +=
|
|
||||||
(i >> 1) * p->literal_[256 + i + 2];
|
|
||||||
}
|
|
||||||
for (i = 2; i < NUM_DISTANCE_CODES - 2; ++i) {
|
|
||||||
retval += (i >> 1) * p->distance_[i + 2];
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Returns the cost encode the rle-encoded entropy code.
|
// Returns the cost encode the rle-encoded entropy code.
|
||||||
// The constants in this function are experimental.
|
// The constants in this function are experimental.
|
||||||
static double HuffmanCost(const int* const population, int length) {
|
static double HuffmanCost(const int* const population, int length) {
|
||||||
@ -207,19 +186,150 @@ static double HuffmanCost(const int* const population, int length) {
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Estimates the Huffman dictionary + other block overhead size.
|
static double PopulationCost(const int* const population, int length) {
|
||||||
static double HistogramEstimateBitsHeader(const VP8LHistogram* const p) {
|
return BitsEntropy(population, length) + HuffmanCost(population, length);
|
||||||
return HuffmanCost(&p->alpha_[0], 256) +
|
|
||||||
HuffmanCost(&p->red_[0], 256) +
|
|
||||||
HuffmanCost(&p->literal_[0], VP8LHistogramNumCodes(p)) +
|
|
||||||
HuffmanCost(&p->blue_[0], 256) +
|
|
||||||
HuffmanCost(&p->distance_[0], NUM_DISTANCE_CODES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
|
static double ExtraCost(const int* const population, int length) {
|
||||||
return HistogramEstimateBitsHeader(p) + VP8LHistogramEstimateBitsBulk(p);
|
int i;
|
||||||
|
double cost = 0.;
|
||||||
|
for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2];
|
||||||
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Estimates the Entropy + Huffman + other block overhead size cost.
|
||||||
|
double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
|
||||||
|
return PopulationCost(p->literal_, VP8LHistogramNumCodes(p))
|
||||||
|
+ PopulationCost(p->red_, 256)
|
||||||
|
+ PopulationCost(p->blue_, 256)
|
||||||
|
+ PopulationCost(p->alpha_, 256)
|
||||||
|
+ PopulationCost(p->distance_, NUM_DISTANCE_CODES)
|
||||||
|
+ ExtraCost(p->literal_ + 256, NUM_LENGTH_CODES)
|
||||||
|
+ ExtraCost(p->distance_, NUM_DISTANCE_CODES);
|
||||||
|
}
|
||||||
|
|
||||||
|
double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) {
|
||||||
|
return BitsEntropy(p->literal_, VP8LHistogramNumCodes(p))
|
||||||
|
+ BitsEntropy(p->red_, 256)
|
||||||
|
+ BitsEntropy(p->blue_, 256)
|
||||||
|
+ BitsEntropy(p->alpha_, 256)
|
||||||
|
+ BitsEntropy(p->distance_, NUM_DISTANCE_CODES)
|
||||||
|
+ ExtraCost(p->literal_ + 256, NUM_LENGTH_CODES)
|
||||||
|
+ ExtraCost(p->distance_, NUM_DISTANCE_CODES);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Various histogram combine/cost-eval functions
|
||||||
|
|
||||||
|
// Adds 'in' histogram to 'out'
|
||||||
|
static void HistogramAdd(const VP8LHistogram* const in,
|
||||||
|
VP8LHistogram* const out) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) {
|
||||||
|
out->literal_[i] += in->literal_[i];
|
||||||
|
}
|
||||||
|
for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
|
||||||
|
out->distance_[i] += in->distance_[i];
|
||||||
|
}
|
||||||
|
for (i = 0; i < 256; ++i) {
|
||||||
|
out->red_[i] += in->red_[i];
|
||||||
|
out->blue_[i] += in->blue_[i];
|
||||||
|
out->alpha_[i] += in->alpha_[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing
|
||||||
|
// to the threshold value 'cost_threshold'. The score returned is
|
||||||
|
// Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed.
|
||||||
|
// Since the previous score passed is 'cost_threshold', we only need to compare
|
||||||
|
// the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out
|
||||||
|
// early.
|
||||||
|
static double HistogramAddEval(const VP8LHistogram* const a,
|
||||||
|
const VP8LHistogram* const b,
|
||||||
|
VP8LHistogram* const out,
|
||||||
|
double cost_threshold) {
|
||||||
|
double cost = 0;
|
||||||
|
const double sum_cost = a->bit_cost_ + b->bit_cost_;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
cost_threshold += sum_cost;
|
||||||
|
|
||||||
|
// palette_code_bits_ is part of the cost evaluation for literal_.
|
||||||
|
// TODO(skal): remove/simplify this palette_code_bits_?
|
||||||
|
out->palette_code_bits_ =
|
||||||
|
(a->palette_code_bits_ > b->palette_code_bits_) ? a->palette_code_bits_ :
|
||||||
|
b->palette_code_bits_;
|
||||||
|
for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) {
|
||||||
|
out->literal_[i] = a->literal_[i] + b->literal_[i];
|
||||||
|
}
|
||||||
|
cost += PopulationCost(out->literal_, VP8LHistogramNumCodes(out));
|
||||||
|
cost += ExtraCost(out->literal_ + 256, NUM_LENGTH_CODES);
|
||||||
|
if (cost > cost_threshold) return cost;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; ++i) out->red_[i] = a->red_[i] + b->red_[i];
|
||||||
|
cost += PopulationCost(out->red_, 256);
|
||||||
|
if (cost > cost_threshold) return cost;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; ++i) out->blue_[i] = a->blue_[i] + b->blue_[i];
|
||||||
|
cost += PopulationCost(out->blue_, 256);
|
||||||
|
if (cost > cost_threshold) return cost;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
|
||||||
|
out->distance_[i] = a->distance_[i] + b->distance_[i];
|
||||||
|
}
|
||||||
|
cost += PopulationCost(out->distance_, NUM_DISTANCE_CODES);
|
||||||
|
cost += ExtraCost(out->distance_, NUM_DISTANCE_CODES);
|
||||||
|
if (cost > cost_threshold) return cost;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; ++i) out->alpha_[i] = a->alpha_[i] + b->alpha_[i];
|
||||||
|
cost += PopulationCost(out->alpha_, 256);
|
||||||
|
|
||||||
|
out->bit_cost_ = cost;
|
||||||
|
return cost - sum_cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as HistogramAddEval(), except that the resulting histogram
|
||||||
|
// is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit
|
||||||
|
// the term C(b) which is constant over all the evaluations.
|
||||||
|
static double HistogramAddThresh(const VP8LHistogram* const a,
|
||||||
|
const VP8LHistogram* const b,
|
||||||
|
double cost_threshold) {
|
||||||
|
int tmp[PIX_OR_COPY_CODES_MAX]; // <= max storage we'll need
|
||||||
|
int i;
|
||||||
|
double cost = -a->bit_cost_;
|
||||||
|
|
||||||
|
for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) {
|
||||||
|
tmp[i] = a->literal_[i] + b->literal_[i];
|
||||||
|
}
|
||||||
|
// note that the tests are ordered so that the usually largest
|
||||||
|
// cost shares come first.
|
||||||
|
cost += PopulationCost(tmp, VP8LHistogramNumCodes(a));
|
||||||
|
cost += ExtraCost(tmp + 256, NUM_LENGTH_CODES);
|
||||||
|
if (cost > cost_threshold) return cost;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; ++i) tmp[i] = a->red_[i] + b->red_[i];
|
||||||
|
cost += PopulationCost(tmp, 256);
|
||||||
|
if (cost > cost_threshold) return cost;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; ++i) tmp[i] = a->blue_[i] + b->blue_[i];
|
||||||
|
cost += PopulationCost(tmp, 256);
|
||||||
|
if (cost > cost_threshold) return cost;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
|
||||||
|
tmp[i] = a->distance_[i] + b->distance_[i];
|
||||||
|
}
|
||||||
|
cost += PopulationCost(tmp, NUM_DISTANCE_CODES);
|
||||||
|
cost += ExtraCost(tmp, NUM_DISTANCE_CODES);
|
||||||
|
if (cost > cost_threshold) return cost;
|
||||||
|
|
||||||
|
for (i = 0; i < 256; ++i) tmp[i] = a->alpha_[i] + b->alpha_[i];
|
||||||
|
cost += PopulationCost(tmp, 256);
|
||||||
|
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
static void HistogramBuildImage(int xsize, int histo_bits,
|
static void HistogramBuildImage(int xsize, int histo_bits,
|
||||||
const VP8LBackwardRefs* const backward_refs,
|
const VP8LBackwardRefs* const backward_refs,
|
||||||
VP8LHistogramSet* const image) {
|
VP8LHistogramSet* const image) {
|
||||||
@ -273,7 +383,7 @@ static int HistogramCombine(const VP8LHistogramSet* const in,
|
|||||||
// Collapse similar histograms in 'out'.
|
// Collapse similar histograms in 'out'.
|
||||||
for (iter = 0; iter < outer_iters && out_size >= min_cluster_size; ++iter) {
|
for (iter = 0; iter < outer_iters && out_size >= min_cluster_size; ++iter) {
|
||||||
double best_cost_diff = 0.;
|
double best_cost_diff = 0.;
|
||||||
int best_idx1 = 0, best_idx2 = 1;
|
int best_idx1 = -1, best_idx2 = 1;
|
||||||
int j;
|
int j;
|
||||||
const int num_tries = (num_pairs < out_size) ? num_pairs : out_size;
|
const int num_tries = (num_pairs < out_size) ? num_pairs : out_size;
|
||||||
seed += iter;
|
seed += iter;
|
||||||
@ -281,20 +391,17 @@ static int HistogramCombine(const VP8LHistogramSet* const in,
|
|||||||
double curr_cost_diff;
|
double curr_cost_diff;
|
||||||
// Choose two histograms at random and try to combine them.
|
// Choose two histograms at random and try to combine them.
|
||||||
const uint32_t idx1 = MyRand(&seed) % out_size;
|
const uint32_t idx1 = MyRand(&seed) % out_size;
|
||||||
const uint32_t tmp = ((j & 7) + 1) % (out_size - 1);
|
const uint32_t tmp = (j & 7) + 1;
|
||||||
const uint32_t diff = (tmp < 3) ? tmp : MyRand(&seed) % (out_size - 1);
|
const uint32_t diff = (tmp < 3) ? tmp : MyRand(&seed) % (out_size - 1);
|
||||||
const uint32_t idx2 = (idx1 + diff + 1) % out_size;
|
const uint32_t idx2 = (idx1 + diff + 1) % out_size;
|
||||||
if (idx1 == idx2) {
|
if (idx1 == idx2) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*cur_combo = *out->histograms[idx1];
|
|
||||||
VP8LHistogramAdd(cur_combo, out->histograms[idx2]);
|
|
||||||
cur_combo->bit_cost_ = VP8LHistogramEstimateBits(cur_combo);
|
|
||||||
// Calculate cost reduction on combining.
|
// Calculate cost reduction on combining.
|
||||||
curr_cost_diff = cur_combo->bit_cost_
|
curr_cost_diff = HistogramAddEval(out->histograms[idx1],
|
||||||
- out->histograms[idx1]->bit_cost_
|
out->histograms[idx2],
|
||||||
- out->histograms[idx2]->bit_cost_;
|
cur_combo, best_cost_diff);
|
||||||
if (best_cost_diff > curr_cost_diff) { // found a better pair?
|
if (curr_cost_diff < best_cost_diff) { // found a better pair?
|
||||||
{ // swap cur/best combo histograms
|
{ // swap cur/best combo histograms
|
||||||
VP8LHistogram* const tmp_histo = cur_combo;
|
VP8LHistogram* const tmp_histo = cur_combo;
|
||||||
cur_combo = best_combo;
|
cur_combo = best_combo;
|
||||||
@ -306,7 +413,7 @@ static int HistogramCombine(const VP8LHistogramSet* const in,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best_cost_diff < 0.0) {
|
if (best_idx1 >= 0) {
|
||||||
*out->histograms[best_idx1] = *best_combo;
|
*out->histograms[best_idx1] = *best_combo;
|
||||||
// swap best_idx2 slot with last one (which is now unused)
|
// swap best_idx2 slot with last one (which is now unused)
|
||||||
--out_size;
|
--out_size;
|
||||||
@ -331,20 +438,11 @@ static int HistogramCombine(const VP8LHistogramSet* const in,
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Histogram refinement
|
// Histogram refinement
|
||||||
|
|
||||||
// What is the bit cost of moving square_histogram from
|
// What is the bit cost of moving square_histogram from cur_symbol to candidate.
|
||||||
// cur_symbol to candidate_symbol.
|
|
||||||
// TODO(skal): we don't really need to copy the histogram and Add(). Instead
|
|
||||||
// we just need VP8LDualHistogramEstimateBits(A, B) estimation function.
|
|
||||||
static double HistogramDistance(const VP8LHistogram* const square_histogram,
|
static double HistogramDistance(const VP8LHistogram* const square_histogram,
|
||||||
const VP8LHistogram* const candidate) {
|
const VP8LHistogram* const candidate,
|
||||||
const double previous_bit_cost = candidate->bit_cost_;
|
double cost_threshold) {
|
||||||
double new_bit_cost;
|
return HistogramAddThresh(candidate, square_histogram, cost_threshold);
|
||||||
VP8LHistogram modified_histo;
|
|
||||||
modified_histo = *candidate;
|
|
||||||
VP8LHistogramAdd(&modified_histo, square_histogram);
|
|
||||||
new_bit_cost = VP8LHistogramEstimateBits(&modified_histo);
|
|
||||||
|
|
||||||
return new_bit_cost - previous_bit_cost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the best 'out' histogram for each of the 'in' histograms.
|
// Find the best 'out' histogram for each of the 'in' histograms.
|
||||||
@ -355,11 +453,12 @@ static void HistogramRemap(const VP8LHistogramSet* const in,
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < in->size; ++i) {
|
for (i = 0; i < in->size; ++i) {
|
||||||
int best_out = 0;
|
int best_out = 0;
|
||||||
double best_bits = HistogramDistance(in->histograms[i], out->histograms[0]);
|
double best_bits =
|
||||||
|
HistogramDistance(in->histograms[i], out->histograms[0], 1.e38);
|
||||||
int k;
|
int k;
|
||||||
for (k = 1; k < out->size; ++k) {
|
for (k = 1; k < out->size; ++k) {
|
||||||
const double cur_bits =
|
const double cur_bits =
|
||||||
HistogramDistance(in->histograms[i], out->histograms[k]);
|
HistogramDistance(in->histograms[i], out->histograms[k], best_bits);
|
||||||
if (cur_bits < best_bits) {
|
if (cur_bits < best_bits) {
|
||||||
best_bits = cur_bits;
|
best_bits = cur_bits;
|
||||||
best_out = k;
|
best_out = k;
|
||||||
@ -373,7 +472,7 @@ static void HistogramRemap(const VP8LHistogramSet* const in,
|
|||||||
HistogramClear(out->histograms[i]);
|
HistogramClear(out->histograms[i]);
|
||||||
}
|
}
|
||||||
for (i = 0; i < in->size; ++i) {
|
for (i = 0; i < in->size; ++i) {
|
||||||
VP8LHistogramAdd(out->histograms[symbols[i]], in->histograms[i]);
|
HistogramAdd(in->histograms[i], out->histograms[symbols[i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,22 +80,6 @@ double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
|
|||||||
// represent the entropy code itself.
|
// represent the entropy code itself.
|
||||||
double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p);
|
double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p);
|
||||||
|
|
||||||
static WEBP_INLINE void VP8LHistogramAdd(VP8LHistogram* const p,
|
|
||||||
const VP8LHistogram* const a) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) {
|
|
||||||
p->literal_[i] += a->literal_[i];
|
|
||||||
}
|
|
||||||
for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
|
|
||||||
p->distance_[i] += a->distance_[i];
|
|
||||||
}
|
|
||||||
for (i = 0; i < 256; ++i) {
|
|
||||||
p->red_[i] += a->red_[i];
|
|
||||||
p->blue_[i] += a->blue_[i];
|
|
||||||
p->alpha_[i] += a->alpha_[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static WEBP_INLINE int VP8LHistogramNumCodes(const VP8LHistogram* const p) {
|
static WEBP_INLINE int VP8LHistogramNumCodes(const VP8LHistogram* const p) {
|
||||||
return 256 + NUM_LENGTH_CODES +
|
return 256 + NUM_LENGTH_CODES +
|
||||||
((p->palette_code_bits_ > 0) ? (1 << p->palette_code_bits_) : 0);
|
((p->palette_code_bits_ > 0) ? (1 << p->palette_code_bits_) : 0);
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "../utils/utils.h"
|
#include "../utils/utils.h"
|
||||||
#include "../webp/format_constants.h"
|
#include "../webp/format_constants.h" // RIFF constants
|
||||||
|
#include "../webp/mux_types.h" // ALPHA_FLAG
|
||||||
#include "./vp8enci.h"
|
#include "./vp8enci.h"
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
@ -27,8 +27,8 @@ extern "C" {
|
|||||||
|
|
||||||
// version numbers
|
// version numbers
|
||||||
#define ENC_MAJ_VERSION 0
|
#define ENC_MAJ_VERSION 0
|
||||||
#define ENC_MIN_VERSION 2
|
#define ENC_MIN_VERSION 3
|
||||||
#define ENC_REV_VERSION 1
|
#define ENC_REV_VERSION 0
|
||||||
|
|
||||||
// intra prediction modes
|
// intra prediction modes
|
||||||
enum { B_DC_PRED = 0, // 4x4 modes
|
enum { B_DC_PRED = 0, // 4x4 modes
|
||||||
@ -55,8 +55,9 @@ enum { NUM_MB_SEGMENTS = 4,
|
|||||||
NUM_BANDS = 8,
|
NUM_BANDS = 8,
|
||||||
NUM_CTX = 3,
|
NUM_CTX = 3,
|
||||||
NUM_PROBAS = 11,
|
NUM_PROBAS = 11,
|
||||||
MAX_LF_LEVELS = 64, // Maximum loop filter level
|
MAX_LF_LEVELS = 64, // Maximum loop filter level
|
||||||
MAX_VARIABLE_LEVEL = 67 // last (inclusive) level with variable cost
|
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
|
||||||
|
MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum { // Rate-distortion optimization levels
|
typedef enum { // Rate-distortion optimization levels
|
||||||
|
@ -563,6 +563,9 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
|||||||
!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
|
!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
// Free combined histograms.
|
||||||
|
free(histogram_image);
|
||||||
|
histogram_image = NULL;
|
||||||
|
|
||||||
// Color Cache parameters.
|
// Color Cache parameters.
|
||||||
VP8LWriteBits(bw, 1, use_color_cache);
|
VP8LWriteBits(bw, 1, use_color_cache);
|
||||||
@ -609,9 +612,6 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
|||||||
ClearHuffmanTreeIfOnlyOneSymbol(codes);
|
ClearHuffmanTreeIfOnlyOneSymbol(codes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Free combined histograms.
|
|
||||||
free(histogram_image);
|
|
||||||
histogram_image = NULL;
|
|
||||||
|
|
||||||
// Store actual literals.
|
// Store actual literals.
|
||||||
StoreImageToBitMask(bw, width, histogram_bits, &refs,
|
StoreImageToBitMask(bw, width, histogram_bits, &refs,
|
||||||
@ -619,7 +619,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
|||||||
ok = 1;
|
ok = 1;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
if (!ok) free(histogram_image);
|
free(histogram_image);
|
||||||
|
|
||||||
VP8LClearBackwardRefs(&refs);
|
VP8LClearBackwardRefs(&refs);
|
||||||
if (huffman_codes != NULL) {
|
if (huffman_codes != NULL) {
|
||||||
|
@ -8,4 +8,4 @@ Description: Library for the WebP graphics format
|
|||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
Libs: -L${libdir} -lwebp
|
Libs: -L${libdir} -lwebp
|
||||||
Libs.private: -lm
|
Libs.private: -lm @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
|
||||||
|
@ -8,4 +8,4 @@ Description: Library for the WebP graphics format (decode only)
|
|||||||
Version: @PACKAGE_VERSION@
|
Version: @PACKAGE_VERSION@
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
Libs: -L${libdir} -lwebpdecoder
|
Libs: -L${libdir} -lwebpdecoder
|
||||||
Libs.private: -lm
|
Libs.private: -lm @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
|
||||||
|
@ -9,7 +9,10 @@ libwebpmux_la_SOURCES += muxread.c
|
|||||||
|
|
||||||
libwebpmuxinclude_HEADERS =
|
libwebpmuxinclude_HEADERS =
|
||||||
libwebpmuxinclude_HEADERS += ../webp/mux.h
|
libwebpmuxinclude_HEADERS += ../webp/mux.h
|
||||||
|
libwebpmuxinclude_HEADERS += ../webp/mux_types.h
|
||||||
libwebpmuxinclude_HEADERS += ../webp/types.h
|
libwebpmuxinclude_HEADERS += ../webp/types.h
|
||||||
|
|
||||||
libwebpmux_la_LDFLAGS = -version-info 0:0:0
|
libwebpmux_la_LIBADD = ../libwebp.la
|
||||||
|
libwebpmux_la_LDFLAGS = -no-undefined -version-info 0:0:0
|
||||||
libwebpmuxincludedir = $(includedir)/webp
|
libwebpmuxincludedir = $(includedir)/webp
|
||||||
|
pkgconfig_DATA = libwebpmux.pc
|
||||||
|
11
src/mux/libwebpmux.pc.in
Normal file
11
src/mux/libwebpmux.pc.in
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: libwebpmux
|
||||||
|
Description: Library for manipulating the WebP graphics format container
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Requires: libwebp >= 0.2.0
|
||||||
|
Cflags: -I${includedir}
|
||||||
|
Libs: -L${libdir} -lwebpmux
|
@ -306,6 +306,11 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
|
|||||||
if (!(is_frame || (frame->id == WEBP_CHUNK_FRGM))) {
|
if (!(is_frame || (frame->id == WEBP_CHUNK_FRGM))) {
|
||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
#ifndef WEBP_EXPERIMENTAL_FEATURES
|
||||||
|
if (frame->id == WEBP_CHUNK_FRGM) { // disabled for now.
|
||||||
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
|
if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
|
||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
@ -121,7 +121,8 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
|
|||||||
|
|
||||||
// Sets 'chunk' at nth position in the 'chunk_list'.
|
// Sets 'chunk' at nth position in the 'chunk_list'.
|
||||||
// nth = 0 has the special meaning "last of the list".
|
// nth = 0 has the special meaning "last of the list".
|
||||||
WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
|
// On success ownership is transferred from 'chunk' to the 'chunk_list'.
|
||||||
|
WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
|
||||||
uint32_t nth);
|
uint32_t nth);
|
||||||
|
|
||||||
// Releases chunk and returns chunk->next_.
|
// Releases chunk and returns chunk->next_.
|
||||||
|
@ -96,7 +96,7 @@ CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) {
|
|||||||
|
|
||||||
// Returns next chunk in the chunk list with the given tag.
|
// Returns next chunk in the chunk list with the given tag.
|
||||||
static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
|
static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
|
||||||
while (chunk && chunk->tag_ != tag) {
|
while (chunk != NULL && chunk->tag_ != tag) {
|
||||||
chunk = chunk->next_;
|
chunk = chunk->next_;
|
||||||
}
|
}
|
||||||
return chunk;
|
return chunk;
|
||||||
@ -105,7 +105,7 @@ static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
|
|||||||
WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
|
WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
|
||||||
uint32_t iter = nth;
|
uint32_t iter = nth;
|
||||||
first = ChunkSearchNextInList(first, tag);
|
first = ChunkSearchNextInList(first, tag);
|
||||||
if (!first) return NULL;
|
if (first == NULL) return NULL;
|
||||||
|
|
||||||
while (--iter != 0) {
|
while (--iter != 0) {
|
||||||
WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag);
|
WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag);
|
||||||
@ -121,10 +121,10 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
|
|||||||
static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
|
static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
|
||||||
WebPChunk*** const location) {
|
WebPChunk*** const location) {
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
assert(chunk_list);
|
assert(chunk_list != NULL);
|
||||||
*location = chunk_list;
|
*location = chunk_list;
|
||||||
|
|
||||||
while (*chunk_list) {
|
while (*chunk_list != NULL) {
|
||||||
WebPChunk* const cur_chunk = *chunk_list;
|
WebPChunk* const cur_chunk = *chunk_list;
|
||||||
++count;
|
++count;
|
||||||
if (count == nth) return 1; // Found.
|
if (count == nth) return 1; // Found.
|
||||||
@ -149,27 +149,18 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
|
|||||||
ChunkRelease(chunk);
|
ChunkRelease(chunk);
|
||||||
|
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
if (copy_data) {
|
if (copy_data) { // Copy data.
|
||||||
// Copy data.
|
if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR;
|
||||||
chunk->data_.bytes = (uint8_t*)malloc(data->size);
|
chunk->owner_ = 1; // Chunk is owner of data.
|
||||||
if (chunk->data_.bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
|
} else { // Don't copy data.
|
||||||
memcpy((uint8_t*)chunk->data_.bytes, data->bytes, data->size);
|
|
||||||
chunk->data_.size = data->size;
|
|
||||||
|
|
||||||
// Chunk is owner of data.
|
|
||||||
chunk->owner_ = 1;
|
|
||||||
} else {
|
|
||||||
// Don't copy data.
|
|
||||||
chunk->data_ = *data;
|
chunk->data_ = *data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk->tag_ = tag;
|
chunk->tag_ = tag;
|
||||||
|
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
|
WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
|
||||||
uint32_t nth) {
|
uint32_t nth) {
|
||||||
WebPChunk* new_chunk;
|
WebPChunk* new_chunk;
|
||||||
|
|
||||||
@ -180,6 +171,7 @@ WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
|
|||||||
new_chunk = (WebPChunk*)malloc(sizeof(*new_chunk));
|
new_chunk = (WebPChunk*)malloc(sizeof(*new_chunk));
|
||||||
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
|
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
|
||||||
*new_chunk = *chunk;
|
*new_chunk = *chunk;
|
||||||
|
chunk->owner_ = 0;
|
||||||
new_chunk->next_ = *chunk_list;
|
new_chunk->next_ = *chunk_list;
|
||||||
*chunk_list = new_chunk;
|
*chunk_list = new_chunk;
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
@ -199,7 +191,7 @@ WebPChunk* ChunkDelete(WebPChunk* const chunk) {
|
|||||||
|
|
||||||
size_t ChunksListDiskSize(const WebPChunk* chunk_list) {
|
size_t ChunksListDiskSize(const WebPChunk* chunk_list) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
while (chunk_list) {
|
while (chunk_list != NULL) {
|
||||||
size += ChunkDiskSize(chunk_list);
|
size += ChunkDiskSize(chunk_list);
|
||||||
chunk_list = chunk_list->next_;
|
chunk_list = chunk_list->next_;
|
||||||
}
|
}
|
||||||
@ -220,7 +212,7 @@ static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) {
|
uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) {
|
||||||
while (chunk_list) {
|
while (chunk_list != NULL) {
|
||||||
dst = ChunkEmit(chunk_list, dst);
|
dst = ChunkEmit(chunk_list, dst);
|
||||||
chunk_list = chunk_list->next_;
|
chunk_list = chunk_list->next_;
|
||||||
}
|
}
|
||||||
@ -281,7 +273,7 @@ static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth,
|
|||||||
if (nth == 0) return 0; // Not found.
|
if (nth == 0) return 0; // Not found.
|
||||||
}
|
}
|
||||||
|
|
||||||
while (*wpi_list) {
|
while (*wpi_list != NULL) {
|
||||||
WebPMuxImage* const cur_wpi = *wpi_list;
|
WebPMuxImage* const cur_wpi = *wpi_list;
|
||||||
++count;
|
++count;
|
||||||
if (count == nth) return 1; // Found.
|
if (count == nth) return 1; // Found.
|
||||||
@ -327,7 +319,7 @@ WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MuxImageDeleteAll(WebPMuxImage** const wpi_list) {
|
void MuxImageDeleteAll(WebPMuxImage** const wpi_list) {
|
||||||
while (*wpi_list) {
|
while (*wpi_list != NULL) {
|
||||||
*wpi_list = MuxImageDelete(*wpi_list);
|
*wpi_list = MuxImageDelete(*wpi_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,7 +362,7 @@ size_t MuxImageDiskSize(const WebPMuxImage* const wpi) {
|
|||||||
|
|
||||||
size_t MuxImageListDiskSize(const WebPMuxImage* wpi_list) {
|
size_t MuxImageListDiskSize(const WebPMuxImage* wpi_list) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
while (wpi_list) {
|
while (wpi_list != NULL) {
|
||||||
size += MuxImageDiskSize(wpi_list);
|
size += MuxImageDiskSize(wpi_list);
|
||||||
wpi_list = wpi_list->next_;
|
wpi_list = wpi_list->next_;
|
||||||
}
|
}
|
||||||
@ -409,7 +401,7 @@ uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* MuxImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) {
|
uint8_t* MuxImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) {
|
||||||
while (wpi_list) {
|
while (wpi_list != NULL) {
|
||||||
dst = MuxImageEmit(wpi_list, dst);
|
dst = MuxImageEmit(wpi_list, dst);
|
||||||
wpi_list = wpi_list->next_;
|
wpi_list = wpi_list->next_;
|
||||||
}
|
}
|
||||||
|
@ -223,7 +223,9 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
|||||||
MuxImageInit(wpi); // Reset for reading next image.
|
MuxImageInit(wpi); // Reset for reading next image.
|
||||||
break;
|
break;
|
||||||
case WEBP_CHUNK_ANMF:
|
case WEBP_CHUNK_ANMF:
|
||||||
|
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||||
case WEBP_CHUNK_FRGM:
|
case WEBP_CHUNK_FRGM:
|
||||||
|
#endif
|
||||||
if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete.
|
if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete.
|
||||||
if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err;
|
if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err;
|
||||||
ChunkRelease(&chunk);
|
ChunkRelease(&chunk);
|
||||||
@ -378,6 +380,9 @@ static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi,
|
|||||||
const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag);
|
const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag);
|
||||||
const CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM;
|
const CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM;
|
||||||
const WebPData* frame_frgm_data;
|
const WebPData* frame_frgm_data;
|
||||||
|
#ifndef WEBP_EXPERIMENTAL_FEATURES
|
||||||
|
if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
#endif
|
||||||
assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame().
|
assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame().
|
||||||
// Get frame/fragment chunk.
|
// Get frame/fragment chunk.
|
||||||
frame_frgm_data = &wpi->header_->data_;
|
frame_frgm_data = &wpi->header_->data_;
|
||||||
|
@ -5,7 +5,10 @@ if BUILD_LIBWEBPDECODER
|
|||||||
noinst_LTLIBRARIES += libwebputilsdecode.la
|
noinst_LTLIBRARIES += libwebputilsdecode.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
COMMON_SOURCES =
|
common_HEADERS = ../webp/types.h
|
||||||
|
commondir = $(includedir)/webp
|
||||||
|
|
||||||
|
COMMON_SOURCES =
|
||||||
COMMON_SOURCES += bit_reader.c
|
COMMON_SOURCES += bit_reader.c
|
||||||
COMMON_SOURCES += bit_reader.h
|
COMMON_SOURCES += bit_reader.h
|
||||||
COMMON_SOURCES += color_cache.c
|
COMMON_SOURCES += color_cache.c
|
||||||
@ -23,7 +26,7 @@ COMMON_SOURCES += thread.h
|
|||||||
COMMON_SOURCES += utils.c
|
COMMON_SOURCES += utils.c
|
||||||
COMMON_SOURCES += utils.h
|
COMMON_SOURCES += utils.h
|
||||||
|
|
||||||
ENC_SOURCES =
|
ENC_SOURCES =
|
||||||
ENC_SOURCES += bit_writer.c
|
ENC_SOURCES += bit_writer.c
|
||||||
ENC_SOURCES += bit_writer.h
|
ENC_SOURCES += bit_writer.h
|
||||||
ENC_SOURCES += huffman_encode.c
|
ENC_SOURCES += huffman_encode.c
|
||||||
@ -31,15 +34,8 @@ ENC_SOURCES += huffman_encode.h
|
|||||||
ENC_SOURCES += quant_levels.c
|
ENC_SOURCES += quant_levels.c
|
||||||
ENC_SOURCES += quant_levels.h
|
ENC_SOURCES += quant_levels.h
|
||||||
|
|
||||||
|
|
||||||
libwebputils_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES)
|
libwebputils_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES)
|
||||||
|
|
||||||
libwebputilsinclude_HEADERS = ../webp/types.h
|
|
||||||
libwebputilsincludedir = $(includedir)/webp
|
|
||||||
|
|
||||||
if BUILD_LIBWEBPDECODER
|
if BUILD_LIBWEBPDECODER
|
||||||
libwebputilsdecode_la_SOURCES = $(COMMON_SOURCES)
|
libwebputilsdecode_la_SOURCES = $(COMMON_SOURCES)
|
||||||
|
|
||||||
libwebputilsdecodeinclude_HEADERS = $(libwebputilsinclude_HEADERS)
|
|
||||||
libwebputilsdecodeincludedir = $(libwebputilsincludedir)
|
|
||||||
endif
|
endif
|
||||||
|
@ -59,7 +59,7 @@ extern "C" {
|
|||||||
// The right-justify strategy tends to use less shifts and is often faster.
|
// The right-justify strategy tends to use less shifts and is often faster.
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// BITS can be either 32, 24, 16 or 8.
|
// BITS can be any multiple of 8 from 8 to 56 (inclusive).
|
||||||
// Pick values that fit natural register size.
|
// Pick values that fit natural register size.
|
||||||
|
|
||||||
#if !defined(WEBP_REFERENCE_IMPLEMENTATION)
|
#if !defined(WEBP_REFERENCE_IMPLEMENTATION)
|
||||||
@ -68,7 +68,9 @@ extern "C" {
|
|||||||
|
|
||||||
#if defined(__i386__) || defined(_M_IX86) // x86 32bit
|
#if defined(__i386__) || defined(_M_IX86) // x86 32bit
|
||||||
#define BITS 16
|
#define BITS 16
|
||||||
#elif defined(__arm__) || defined(_M_ARM) // ARM
|
#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit
|
||||||
|
#define BITS 56
|
||||||
|
#elif defined(__arm__) || defined(_M_ARM) // ARM
|
||||||
#define BITS 24
|
#define BITS 24
|
||||||
#else // reasonable default
|
#else // reasonable default
|
||||||
#define BITS 24
|
#define BITS 24
|
||||||
@ -84,9 +86,15 @@ extern "C" {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Derived types and constants
|
// Derived types and constants
|
||||||
|
|
||||||
#if (BITS == 32)
|
// bit_t = natural register type
|
||||||
typedef uint64_t bit_t; // natural register type
|
// lbit_t = natural type for memory I/O
|
||||||
typedef uint32_t lbit_t; // natural type for memory I/O
|
|
||||||
|
#if (BITS > 32)
|
||||||
|
typedef uint64_t bit_t;
|
||||||
|
typedef uint64_t lbit_t;
|
||||||
|
#elif (BITS == 32)
|
||||||
|
typedef uint64_t bit_t;
|
||||||
|
typedef uint32_t lbit_t;
|
||||||
#elif (BITS == 24)
|
#elif (BITS == 24)
|
||||||
typedef uint32_t bit_t;
|
typedef uint32_t bit_t;
|
||||||
typedef uint32_t lbit_t;
|
typedef uint32_t lbit_t;
|
||||||
@ -148,19 +156,36 @@ static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) {
|
|||||||
lbit_t in_bits = *(lbit_t*)br->buf_;
|
lbit_t in_bits = *(lbit_t*)br->buf_;
|
||||||
br->buf_ += (BITS) >> 3;
|
br->buf_ += (BITS) >> 3;
|
||||||
#if !defined(__BIG_ENDIAN__)
|
#if !defined(__BIG_ENDIAN__)
|
||||||
#if (BITS == 32) || (BITS == 24)
|
#if (BITS > 32)
|
||||||
|
// gcc 4.3 has builtin functions for swap32/swap64
|
||||||
|
#if defined(__GNUC__) && \
|
||||||
|
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||||
|
bits = (bit_t)__builtin_bswap64(in_bits);
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
bits = (bit_t)_byteswap_uint64(in_bits);
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
__asm__ volatile("bswapq %0" : "=r"(bits) : "0"(in_bits));
|
||||||
|
#else // generic code for swapping 64-bit values (suggested by bdb@)
|
||||||
|
bits = (bit_t)in_bits;
|
||||||
|
bits = ((bits & 0xffffffff00000000ull) >> 32) |
|
||||||
|
((bits & 0x00000000ffffffffull) << 32);
|
||||||
|
bits = ((bits & 0xffff0000ffff0000ull) >> 16) |
|
||||||
|
((bits & 0x0000ffff0000ffffull) << 16);
|
||||||
|
bits = ((bits & 0xff00ff00ff00ff00ull) >> 8) |
|
||||||
|
((bits & 0x00ff00ff00ff00ffull) << 8);
|
||||||
|
#endif
|
||||||
|
bits >>= 64 - BITS;
|
||||||
|
#elif (BITS >= 24)
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
__asm__ volatile("bswap %k0" : "=r"(in_bits) : "0"(in_bits));
|
__asm__ volatile("bswap %k0" : "=r"(in_bits) : "0"(in_bits));
|
||||||
bits = (bit_t)in_bits; // 24b/32b -> 32b/64b zero-extension
|
bits = (bit_t)in_bits; // 24b/32b -> 32b/64b zero-extension
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
bits = _byteswap_ulong(in_bits);
|
bits = (bit_t)_byteswap_ulong(in_bits);
|
||||||
#else
|
#else
|
||||||
bits = (bit_t)(in_bits >> 24) | ((in_bits >> 8) & 0xff00)
|
bits = (bit_t)(in_bits >> 24) | ((in_bits >> 8) & 0xff00)
|
||||||
| ((in_bits << 8) & 0xff0000) | (in_bits << 24);
|
| ((in_bits << 8) & 0xff0000) | (in_bits << 24);
|
||||||
#endif // x86
|
#endif // x86
|
||||||
#if (BITS == 24)
|
bits >>= (32 - BITS);
|
||||||
bits >>= 8;
|
|
||||||
#endif
|
|
||||||
#elif (BITS == 16)
|
#elif (BITS == 16)
|
||||||
// gcc will recognize a 'rorw $8, ...' here:
|
// gcc will recognize a 'rorw $8, ...' here:
|
||||||
bits = (bit_t)(in_bits >> 8) | ((in_bits & 0xff) << 8);
|
bits = (bit_t)(in_bits >> 8) | ((in_bits & 0xff) << 8);
|
||||||
@ -248,7 +273,7 @@ static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
|
static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
|
||||||
const bit_t split = (br->range_ >> 1);
|
const range_t split = (br->range_ >> 1);
|
||||||
const int bit = VP8BitUpdate(br, split);
|
const int bit = VP8BitUpdate(br, split);
|
||||||
VP8Shift(br);
|
VP8Shift(br);
|
||||||
return bit ? -v : v;
|
return bit ? -v : v;
|
||||||
|
@ -26,8 +26,7 @@ extern "C" {
|
|||||||
assert(out != NULL); \
|
assert(out != NULL); \
|
||||||
assert(width > 0); \
|
assert(width > 0); \
|
||||||
assert(height > 0); \
|
assert(height > 0); \
|
||||||
assert(bpp > 0); \
|
assert(stride >= width);
|
||||||
assert(stride >= width * bpp);
|
|
||||||
|
|
||||||
static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred,
|
static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred,
|
||||||
uint8_t* dst, int length, int inverse) {
|
uint8_t* dst, int length, int inverse) {
|
||||||
@ -43,7 +42,8 @@ static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred,
|
|||||||
// Horizontal filter.
|
// Horizontal filter.
|
||||||
|
|
||||||
static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
|
static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
|
||||||
int width, int height, int bpp, int stride, int inverse, uint8_t* out) {
|
int width, int height, int stride,
|
||||||
|
int inverse, uint8_t* out) {
|
||||||
int h;
|
int h;
|
||||||
const uint8_t* preds = (inverse ? out : in);
|
const uint8_t* preds = (inverse ? out : in);
|
||||||
SANITY_CHECK(in, out);
|
SANITY_CHECK(in, out);
|
||||||
@ -52,11 +52,11 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
|
|||||||
for (h = 0; h < height; ++h) {
|
for (h = 0; h < height; ++h) {
|
||||||
// Leftmost pixel is predicted from above (except for topmost scanline).
|
// Leftmost pixel is predicted from above (except for topmost scanline).
|
||||||
if (h == 0) {
|
if (h == 0) {
|
||||||
memcpy((void*)out, (const void*)in, bpp);
|
out[0] = in[0];
|
||||||
} else {
|
} else {
|
||||||
PredictLine(in, preds - stride, out, bpp, inverse);
|
PredictLine(in, preds - stride, out, 1, inverse);
|
||||||
}
|
}
|
||||||
PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
|
PredictLine(in + 1, preds, out + 1, width - 1, inverse);
|
||||||
preds += stride;
|
preds += stride;
|
||||||
in += stride;
|
in += stride;
|
||||||
out += stride;
|
out += stride;
|
||||||
@ -64,46 +64,46 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void HorizontalFilter(const uint8_t* data, int width, int height,
|
static void HorizontalFilter(const uint8_t* data, int width, int height,
|
||||||
int bpp, int stride, uint8_t* filtered_data) {
|
int stride, uint8_t* filtered_data) {
|
||||||
DoHorizontalFilter(data, width, height, bpp, stride, 0, filtered_data);
|
DoHorizontalFilter(data, width, height, stride, 0, filtered_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HorizontalUnfilter(const uint8_t* data, int width, int height,
|
static void HorizontalUnfilter(int width, int height, int stride,
|
||||||
int bpp, int stride, uint8_t* recon_data) {
|
uint8_t* data) {
|
||||||
DoHorizontalFilter(data, width, height, bpp, stride, 1, recon_data);
|
DoHorizontalFilter(data, width, height, stride, 1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Vertical filter.
|
// Vertical filter.
|
||||||
|
|
||||||
static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
|
static WEBP_INLINE void DoVerticalFilter(const uint8_t* in,
|
||||||
int width, int height, int bpp, int stride, int inverse, uint8_t* out) {
|
int width, int height, int stride,
|
||||||
|
int inverse, uint8_t* out) {
|
||||||
int h;
|
int h;
|
||||||
const uint8_t* preds = (inverse ? out : in);
|
const uint8_t* preds = (inverse ? out : in);
|
||||||
SANITY_CHECK(in, out);
|
SANITY_CHECK(in, out);
|
||||||
|
|
||||||
// Very first top-left pixel is copied.
|
// Very first top-left pixel is copied.
|
||||||
memcpy((void*)out, (const void*)in, bpp);
|
out[0] = in[0];
|
||||||
// Rest of top scan-line is left-predicted.
|
// Rest of top scan-line is left-predicted.
|
||||||
PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
|
PredictLine(in + 1, preds, out + 1, width - 1, inverse);
|
||||||
|
|
||||||
// Filter line-by-line.
|
// Filter line-by-line.
|
||||||
for (h = 1; h < height; ++h) {
|
for (h = 1; h < height; ++h) {
|
||||||
in += stride;
|
in += stride;
|
||||||
out += stride;
|
out += stride;
|
||||||
PredictLine(in, preds, out, bpp * width, inverse);
|
PredictLine(in, preds, out, width, inverse);
|
||||||
preds += stride;
|
preds += stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VerticalFilter(const uint8_t* data, int width, int height,
|
static void VerticalFilter(const uint8_t* data, int width, int height,
|
||||||
int bpp, int stride, uint8_t* filtered_data) {
|
int stride, uint8_t* filtered_data) {
|
||||||
DoVerticalFilter(data, width, height, bpp, stride, 0, filtered_data);
|
DoVerticalFilter(data, width, height, stride, 0, filtered_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VerticalUnfilter(const uint8_t* data, int width, int height,
|
static void VerticalUnfilter(int width, int height, int stride, uint8_t* data) {
|
||||||
int bpp, int stride, uint8_t* recon_data) {
|
DoVerticalFilter(data, width, height, stride, 1, data);
|
||||||
DoVerticalFilter(data, width, height, bpp, stride, 1, recon_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -111,19 +111,19 @@ static void VerticalUnfilter(const uint8_t* data, int width, int height,
|
|||||||
|
|
||||||
static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
|
static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) {
|
||||||
const int g = a + b - c;
|
const int g = a + b - c;
|
||||||
return (g < 0) ? 0 : (g > 255) ? 255 : g;
|
return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit
|
||||||
}
|
}
|
||||||
|
|
||||||
static WEBP_INLINE
|
static WEBP_INLINE
|
||||||
void DoGradientFilter(const uint8_t* in, int width, int height,
|
void DoGradientFilter(const uint8_t* in, int width, int height,
|
||||||
int bpp, int stride, int inverse, uint8_t* out) {
|
int stride, int inverse, uint8_t* out) {
|
||||||
const uint8_t* preds = (inverse ? out : in);
|
const uint8_t* preds = (inverse ? out : in);
|
||||||
int h;
|
int h;
|
||||||
SANITY_CHECK(in, out);
|
SANITY_CHECK(in, out);
|
||||||
|
|
||||||
// left prediction for top scan-line
|
// left prediction for top scan-line
|
||||||
memcpy((void*)out, (const void*)in, bpp);
|
out[0] = in[0];
|
||||||
PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
|
PredictLine(in + 1, preds, out + 1, width - 1, inverse);
|
||||||
|
|
||||||
// Filter line-by-line.
|
// Filter line-by-line.
|
||||||
for (h = 1; h < height; ++h) {
|
for (h = 1; h < height; ++h) {
|
||||||
@ -132,24 +132,23 @@ void DoGradientFilter(const uint8_t* in, int width, int height,
|
|||||||
in += stride;
|
in += stride;
|
||||||
out += stride;
|
out += stride;
|
||||||
// leftmost pixel: predict from above.
|
// leftmost pixel: predict from above.
|
||||||
PredictLine(in, preds - stride, out, bpp, inverse);
|
PredictLine(in, preds - stride, out, 1, inverse);
|
||||||
for (w = bpp; w < width * bpp; ++w) {
|
for (w = 1; w < width; ++w) {
|
||||||
const int pred = GradientPredictor(preds[w - bpp],
|
const int pred = GradientPredictor(preds[w - 1],
|
||||||
preds[w - stride],
|
preds[w - stride],
|
||||||
preds[w - stride - bpp]);
|
preds[w - stride - 1]);
|
||||||
out[w] = in[w] + (inverse ? pred : -pred);
|
out[w] = in[w] + (inverse ? pred : -pred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GradientFilter(const uint8_t* data, int width, int height,
|
static void GradientFilter(const uint8_t* data, int width, int height,
|
||||||
int bpp, int stride, uint8_t* filtered_data) {
|
int stride, uint8_t* filtered_data) {
|
||||||
DoGradientFilter(data, width, height, bpp, stride, 0, filtered_data);
|
DoGradientFilter(data, width, height, stride, 0, filtered_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GradientUnfilter(const uint8_t* data, int width, int height,
|
static void GradientUnfilter(int width, int height, int stride, uint8_t* data) {
|
||||||
int bpp, int stride, uint8_t* recon_data) {
|
DoGradientFilter(data, width, height, stride, 1, data);
|
||||||
DoGradientFilter(data, width, height, bpp, stride, 1, recon_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef SANITY_CHECK
|
#undef SANITY_CHECK
|
||||||
@ -215,7 +214,7 @@ const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST] = {
|
|||||||
GradientFilter // WEBP_FILTER_GRADIENT
|
GradientFilter // WEBP_FILTER_GRADIENT
|
||||||
};
|
};
|
||||||
|
|
||||||
const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST] = {
|
const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST] = {
|
||||||
NULL, // WEBP_FILTER_NONE
|
NULL, // WEBP_FILTER_NONE
|
||||||
HorizontalUnfilter, // WEBP_FILTER_HORIZONTAL
|
HorizontalUnfilter, // WEBP_FILTER_HORIZONTAL
|
||||||
VerticalUnfilter, // WEBP_FILTER_VERTICAL
|
VerticalUnfilter, // WEBP_FILTER_VERTICAL
|
||||||
|
@ -30,18 +30,19 @@ typedef enum {
|
|||||||
} WEBP_FILTER_TYPE;
|
} WEBP_FILTER_TYPE;
|
||||||
|
|
||||||
typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height,
|
typedef void (*WebPFilterFunc)(const uint8_t* in, int width, int height,
|
||||||
int bpp, int stride, uint8_t* out);
|
int stride, uint8_t* out);
|
||||||
|
typedef void (*WebPUnfilterFunc)(int width, int height, int stride,
|
||||||
|
uint8_t* data);
|
||||||
|
|
||||||
// Filter the given data using the given predictor.
|
// Filter the given data using the given predictor.
|
||||||
// 'in' corresponds to a 2-dimensional pixel array of size (stride * height)
|
// 'in' corresponds to a 2-dimensional pixel array of size (stride * height)
|
||||||
// in raster order.
|
// in raster order.
|
||||||
// 'bpp' is number of bytes per pixel, and
|
|
||||||
// 'stride' is number of bytes per scan line (with possible padding).
|
// 'stride' is number of bytes per scan line (with possible padding).
|
||||||
// 'out' should be pre-allocated.
|
// 'out' should be pre-allocated.
|
||||||
extern const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
|
extern const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
|
||||||
|
|
||||||
// Reconstruct the original data from the given filtered data.
|
// In-place reconstruct the original data from the given filtered data.
|
||||||
extern const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST];
|
extern const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST];
|
||||||
|
|
||||||
// Fast estimate of a potentially good filter.
|
// Fast estimate of a potentially good filter.
|
||||||
extern WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
|
extern WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WEBP_DECODER_ABI_VERSION 0x0200 // MAJOR(8b) + MINOR(8b)
|
#define WEBP_DECODER_ABI_VERSION 0x0201 // MAJOR(8b) + MINOR(8b)
|
||||||
|
|
||||||
typedef struct WebPRGBABuffer WebPRGBABuffer;
|
typedef struct WebPRGBABuffer WebPRGBABuffer;
|
||||||
typedef struct WebPYUVABuffer WebPYUVABuffer;
|
typedef struct WebPYUVABuffer WebPYUVABuffer;
|
||||||
@ -392,9 +392,10 @@ WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea(
|
|||||||
|
|
||||||
// Features gathered from the bitstream
|
// Features gathered from the bitstream
|
||||||
struct WebPBitstreamFeatures {
|
struct WebPBitstreamFeatures {
|
||||||
int width; // Width in pixels, as read from the bitstream.
|
int width; // Width in pixels, as read from the bitstream.
|
||||||
int height; // Height in pixels, as read from the bitstream.
|
int height; // Height in pixels, as read from the bitstream.
|
||||||
int has_alpha; // True if the bitstream contains an alpha channel.
|
int has_alpha; // True if the bitstream contains an alpha channel.
|
||||||
|
int has_animation; // True if the bitstream is an animation.
|
||||||
|
|
||||||
// Unused for now:
|
// Unused for now:
|
||||||
int bitstream_version; // should be 0 for now. TODO(later)
|
int bitstream_version; // should be 0 for now. TODO(later)
|
||||||
@ -402,7 +403,7 @@ struct WebPBitstreamFeatures {
|
|||||||
// recommended.
|
// recommended.
|
||||||
int rotate; // TODO(later)
|
int rotate; // TODO(later)
|
||||||
int uv_sampling; // should be 0 for now. TODO(later)
|
int uv_sampling; // should be 0 for now. TODO(later)
|
||||||
uint32_t pad[3]; // padding for later use
|
uint32_t pad[2]; // padding for later use
|
||||||
};
|
};
|
||||||
|
|
||||||
// Internal, version-checked, entry point
|
// Internal, version-checked, entry point
|
||||||
|
@ -45,7 +45,6 @@
|
|||||||
#ifndef WEBP_WEBP_DEMUX_H_
|
#ifndef WEBP_WEBP_DEMUX_H_
|
||||||
#define WEBP_WEBP_DEMUX_H_
|
#define WEBP_WEBP_DEMUX_H_
|
||||||
|
|
||||||
#include "./format_constants.h"
|
|
||||||
#include "./mux_types.h"
|
#include "./mux_types.h"
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
@ -81,14 +80,13 @@ enum WebPDemuxState {
|
|||||||
WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(
|
WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(
|
||||||
const WebPData*, int, WebPDemuxState*, int);
|
const WebPData*, int, WebPDemuxState*, int);
|
||||||
|
|
||||||
// Parses the WebP file given by 'data'.
|
// Parses the full WebP file given by 'data'.
|
||||||
// A complete WebP file must be present in 'data' for the function to succeed.
|
|
||||||
// Returns a WebPDemuxer object on successful parse, NULL otherwise.
|
// Returns a WebPDemuxer object on successful parse, NULL otherwise.
|
||||||
static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
|
static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
|
||||||
return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION);
|
return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses the WebP file given by 'data'.
|
// Parses the possibly incomplete WebP file given by 'data'.
|
||||||
// If 'state' is non-NULL it will be set to indicate the status of the demuxer.
|
// If 'state' is non-NULL it will be set to indicate the status of the demuxer.
|
||||||
// Returns a WebPDemuxer object on successful parse, NULL otherwise.
|
// Returns a WebPDemuxer object on successful parse, NULL otherwise.
|
||||||
static WEBP_INLINE WebPDemuxer* WebPDemuxPartial(
|
static WEBP_INLINE WebPDemuxer* WebPDemuxPartial(
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_
|
#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_
|
||||||
#define WEBP_WEBP_FORMAT_CONSTANTS_H_
|
#define WEBP_WEBP_FORMAT_CONSTANTS_H_
|
||||||
|
|
||||||
|
// Create fourcc of the chunk from the chunk tag characters.
|
||||||
|
#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24)
|
||||||
|
|
||||||
// VP8 related constants.
|
// VP8 related constants.
|
||||||
#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data.
|
#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data.
|
||||||
#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition
|
#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition
|
||||||
@ -70,19 +73,6 @@ typedef enum {
|
|||||||
#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk.
|
#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk.
|
||||||
#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk.
|
#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk.
|
||||||
|
|
||||||
// VP8X Feature Flags.
|
|
||||||
#if !(defined(__cplusplus) || defined(c_plusplus))
|
|
||||||
typedef enum WebPFeatureFlags WebPFeatureFlags;
|
|
||||||
#endif
|
|
||||||
enum WebPFeatureFlags {
|
|
||||||
FRAGMENTS_FLAG = 0x00000001,
|
|
||||||
ANIMATION_FLAG = 0x00000002,
|
|
||||||
XMP_FLAG = 0x00000004,
|
|
||||||
EXIF_FLAG = 0x00000008,
|
|
||||||
ALPHA_FLAG = 0x00000010,
|
|
||||||
ICCP_FLAG = 0x00000020
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
|
#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
|
||||||
#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
|
#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
|
||||||
#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
|
#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
|
||||||
|
@ -45,7 +45,6 @@
|
|||||||
#ifndef WEBP_WEBP_MUX_H_
|
#ifndef WEBP_WEBP_MUX_H_
|
||||||
#define WEBP_WEBP_MUX_H_
|
#define WEBP_WEBP_MUX_H_
|
||||||
|
|
||||||
#include "./format_constants.h"
|
|
||||||
#include "./mux_types.h"
|
#include "./mux_types.h"
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
|
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Internal header for some common data-types used by mux and demux libraries.
|
// Data-types common to the mux and demux libraries.
|
||||||
//
|
//
|
||||||
// Author: Urvang (urvang@google.com)
|
// Author: Urvang (urvang@google.com)
|
||||||
|
|
||||||
@ -20,14 +20,23 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create fourcc of the chunk from the chunk tag characters.
|
#if !(defined(__cplusplus) || defined(c_plusplus))
|
||||||
#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24)
|
typedef enum WebPFeatureFlags WebPFeatureFlags;
|
||||||
|
typedef enum WebPMuxAnimDispose WebPMuxAnimDispose;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// VP8X Feature Flags.
|
||||||
|
enum WebPFeatureFlags {
|
||||||
|
FRAGMENTS_FLAG = 0x00000001,
|
||||||
|
ANIMATION_FLAG = 0x00000002,
|
||||||
|
XMP_FLAG = 0x00000004,
|
||||||
|
EXIF_FLAG = 0x00000008,
|
||||||
|
ALPHA_FLAG = 0x00000010,
|
||||||
|
ICCP_FLAG = 0x00000020
|
||||||
|
};
|
||||||
|
|
||||||
// Dispose method (animation only). Indicates how the area used by the current
|
// Dispose method (animation only). Indicates how the area used by the current
|
||||||
// frame is to be treated before rendering the next frame on the canvas.
|
// frame is to be treated before rendering the next frame on the canvas.
|
||||||
#if !(defined(__cplusplus) || defined(c_plusplus))
|
|
||||||
typedef enum WebPMuxAnimDispose WebPMuxAnimDispose;
|
|
||||||
#endif
|
|
||||||
enum WebPMuxAnimDispose {
|
enum WebPMuxAnimDispose {
|
||||||
WEBP_MUX_DISPOSE_NONE, // Do not dispose.
|
WEBP_MUX_DISPOSE_NONE, // Do not dispose.
|
||||||
WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color.
|
WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user