mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01: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>
|
||||
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:
|
||||
- James Zern (jzern at google dot com)
|
||||
- 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)
|
||||
- Lou Quillio (louquillio at google dot com)
|
||||
- Mans Rullgard (mans at mansr dot com)
|
||||
- Martin Olsson (mnemo at minimum dot se)
|
||||
- Mikołaj Zalewski (mikolajz at google dot com)
|
||||
- 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
|
||||
57cf313 update NEWS
|
||||
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
|
||||
ef5cc47 make *InitSSE2() functions be empty on non-SSE2 platform
|
||||
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)
|
||||
c655380 dec/io.c: cosmetics
|
||||
fe1958f RGBA4444: harmonize lossless/lossy alpha values
|
||||
@ -135,7 +514,7 @@ f0b5def bump versions
|
||||
05108f6 Merge "More spec/code matching in mux:"
|
||||
6808e69 More spec/code matching in mux:
|
||||
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
|
||||
b5e9067 fix some int <-> size_t mix for buffer sizes
|
||||
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."
|
||||
7c68980 Fix asserts in Palette and BackwardReference code.
|
||||
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
|
||||
eaee9e7 Bug-Fix: Decode small (less than 32 bytes) images.
|
||||
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
|
||||
#
|
||||
LIBWEBPDECODER_BASENAME = libwebpdecoder
|
||||
LIBWEBP_BASENAME = libwebp
|
||||
LIBWEBPMUX_BASENAME = libwebpmux
|
||||
LIBWEBPDEMUX_BASENAME = libwebpdemux
|
||||
@ -75,6 +76,7 @@ STATICLIBBUILD = TRUE
|
||||
CC = $(CCDEBUG)
|
||||
RTLIB = $(RTLIBD)
|
||||
STATICLIBBUILD = TRUE
|
||||
LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
|
||||
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
|
||||
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
|
||||
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
||||
@ -85,6 +87,7 @@ DLLBUILD = TRUE
|
||||
CC = $(CCDEBUG)
|
||||
RTLIB = $(RTLIBD)
|
||||
DLLBUILD = TRUE
|
||||
LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
|
||||
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
|
||||
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
|
||||
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
||||
@ -93,17 +96,19 @@ LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
||||
!IF "$(STATICLIBBUILD)" == "TRUE"
|
||||
CC = $(CC) $(RTLIB)
|
||||
CFGSET = TRUE
|
||||
LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME).lib
|
||||
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib
|
||||
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME).lib
|
||||
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib
|
||||
!ELSE IF "$(DLLBUILD)" == "TRUE"
|
||||
DLLC = webp_dll.c
|
||||
DLLINC = webp_dll.h
|
||||
DLL_OBJS = $(DIROBJ)\$(DLLC:.c=.obj)
|
||||
CC = $(CC) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL
|
||||
LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib
|
||||
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib
|
||||
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib
|
||||
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPMDEMUX_BASENAME)_dll.lib
|
||||
LIBWEBP_OBJS = $(DIROBJ)\$(DLLC:.c=.obj)
|
||||
LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
|
||||
CFGSET = TRUE
|
||||
!ENDIF
|
||||
@ -160,17 +165,22 @@ DEC_OBJS = \
|
||||
DEMUX_OBJS = \
|
||||
$(DIROBJ)\demux\demux.obj \
|
||||
|
||||
DSP_OBJS = \
|
||||
DSP_DEC_OBJS = \
|
||||
$(DIROBJ)\dsp\cpu.obj \
|
||||
$(DIROBJ)\dsp\dec.obj \
|
||||
$(DIROBJ)\dsp\dec_neon.obj \
|
||||
$(DIROBJ)\dsp\dec_sse2.obj \
|
||||
$(DIROBJ)\dsp\enc.obj \
|
||||
$(DIROBJ)\dsp\enc_sse2.obj \
|
||||
$(DIROBJ)\dsp\lossless.obj \
|
||||
$(DIROBJ)\dsp\upsampling.obj \
|
||||
$(DIROBJ)\dsp\upsampling_neon.obj \
|
||||
$(DIROBJ)\dsp\upsampling_sse2.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 = \
|
||||
$(DIROBJ)\examples\jpegdec.obj \
|
||||
$(DIROBJ)\examples\metadata.obj \
|
||||
@ -205,29 +215,35 @@ MUX_OBJS = \
|
||||
$(DIROBJ)\mux\muxinternal.obj \
|
||||
$(DIROBJ)\mux\muxread.obj \
|
||||
|
||||
UTILS_OBJS = \
|
||||
UTILS_DEC_OBJS = \
|
||||
$(DIROBJ)\utils\bit_reader.obj \
|
||||
$(DIROBJ)\utils\bit_writer.obj \
|
||||
$(DIROBJ)\utils\color_cache.obj \
|
||||
$(DIROBJ)\utils\filters.obj \
|
||||
$(DIROBJ)\utils\huffman.obj \
|
||||
$(DIROBJ)\utils\huffman_encode.obj \
|
||||
$(DIROBJ)\utils\quant_levels.obj \
|
||||
$(DIROBJ)\utils\quant_levels_dec.obj \
|
||||
$(DIROBJ)\utils\rescaler.obj \
|
||||
$(DIROBJ)\utils\thread.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)
|
||||
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) $(LIBWEBPDEMUX_OBJS)
|
||||
|
||||
OUT_LIBS = $(LIBWEBP)
|
||||
OUT_LIBS = $(LIBWEBPDECODER) $(LIBWEBP)
|
||||
OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe
|
||||
|
||||
all: $(OUT_LIBS) $(OUT_EXAMPLES)
|
||||
$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(EX_FORMAT_DEC_OBJS)
|
||||
$(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: $(EX_UTIL_OBJS) $(LIBWEBP)
|
||||
$(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP)
|
||||
@ -237,6 +253,7 @@ experimental:
|
||||
CFG=$(CFG) \
|
||||
CFLAGS="$(CFLAGS) /DWEBP_EXPERIMENTAL_FEATURES" /$(MAKEFLAGS)
|
||||
|
||||
$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS)
|
||||
$(LIBWEBP): $(LIBWEBP_OBJS)
|
||||
$(LIBWEBPMUX): $(LIBWEBPMUX_OBJS)
|
||||
$(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS)
|
||||
@ -244,8 +261,8 @@ $(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS)
|
||||
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): $(OUTPUT_DIRS)
|
||||
|
||||
!IF "$(DLLBUILD)" == "TRUE"
|
||||
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS):
|
||||
$(DIROBJ)\$(DLLINC) $(DIROBJ)\$(DLLC)
|
||||
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): \
|
||||
$(DIROBJ)\$(DLLINC) $(DIROBJ)\$(DLLC)
|
||||
|
||||
{$(DIROBJ)}.c{$(DIROBJ)}.obj:
|
||||
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
|
||||
@ -253,14 +270,14 @@ $(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS):
|
||||
$(LIBWEBPMUX): $(LIBWEBP)
|
||||
$(LIBWEBPDEMUX): $(LIBWEBP)
|
||||
|
||||
$(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
||||
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
||||
$(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $**
|
||||
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
|
||||
|
||||
clean::
|
||||
@-erase /s $(DIROBJ)\$(DLLC) $(DIROBJ)\$(DLLINC) 2> NUL
|
||||
!ELSE
|
||||
$(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
||||
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
||||
$(LNKLIB) /out:$@ $(LFLAGS) $**
|
||||
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
|
||||
!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
|
||||
and will perform auto-allocation.
|
||||
* default filter option is now '-strong -f 60'
|
||||
* encoding speed-up for lossy methods 3 to 6
|
||||
* 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
|
||||
* Various security related fixes
|
||||
|
62
README
62
README
@ -4,7 +4,7 @@
|
||||
\__\__/\____/\_____/__/ ____ ___
|
||||
/ _/ / \ \ / _ \/ _/
|
||||
/ \_/ / / \ \ __/ \__
|
||||
\____/____/\_____/_____/____/v0.2.1
|
||||
\____/____/\_____/_____/____/v0.3.0
|
||||
|
||||
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
|
||||
is supplied, as this is a simple alternative to the full installation
|
||||
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:
|
||||
---------------------
|
||||
@ -71,10 +71,11 @@ should be all you need to have the following files
|
||||
|
||||
installed.
|
||||
|
||||
Note: The encoding and decoding libraries are compiled separately
|
||||
(as src/dec/libwebpdecode.* and src/dec/libwebpencode.*). They
|
||||
can be installed independently using a minor modification in the
|
||||
corresponding Makefile.am configure files (see comments there).
|
||||
Note: A decode-only library, libwebpdecoder, is available using the
|
||||
'--enable-libwebpdecoder' flag. The encode library is built separately and can
|
||||
be installed independently using a minor modification in the corresponding
|
||||
Makefile.am configure files (see comments there). See './configure --help' for
|
||||
more options.
|
||||
|
||||
SWIG bindings:
|
||||
--------------
|
||||
@ -176,7 +177,7 @@ options:
|
||||
|
||||
-metadata <string> ..... comma separated list of metadata to
|
||||
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
|
||||
-quiet ................. don't print anything.
|
||||
@ -263,12 +264,51 @@ Visualization tool:
|
||||
|
||||
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
|
||||
a decoded WebP file. It's not yet integrated in the automake or makefile.unix
|
||||
build system, but you can try to manually compile it using the recommendations
|
||||
at the top of the source file.
|
||||
a decoded WebP file. It's not yet integrated in the automake build system, but
|
||||
you can try to manually compile it using the recommendations below.
|
||||
|
||||
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:
|
||||
=============
|
||||
|
47
README.mux
47
README.mux
@ -1,7 +1,7 @@
|
||||
__ __ ____ ____ ____ __ __ _ __ __
|
||||
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
|
||||
\ / __/ _ \ __/ / / (_/ /__
|
||||
\__\__/\_____/_____/__/ \__//_/\_____/__/___/
|
||||
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.1.0
|
||||
|
||||
|
||||
Description:
|
||||
@ -9,9 +9,9 @@ Description:
|
||||
|
||||
WebPMux: set of two libraries 'Mux' and 'Demux' for creation, extraction and
|
||||
manipulation of an extended format WebP file, which can have features like
|
||||
color profile, metadata, animation and fragmented images. Reference
|
||||
command-line tools 'webpmux' and 'vwebp' as well as the WebP container
|
||||
specification 'doc/webp-container-spec.txt' are also provided in this package.
|
||||
color profile, metadata and animation. Reference command-line tools 'webpmux'
|
||||
and 'vwebp' as well as the WebP container specification
|
||||
'doc/webp-container-spec.txt' are also provided in this package.
|
||||
|
||||
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
|
||||
webpmux -set SET_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]
|
||||
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
|
||||
webpmux -info INPUT
|
||||
@ -38,7 +37,6 @@ GET_OPTIONS:
|
||||
icc Get ICC profile.
|
||||
exif Get EXIF metadata.
|
||||
xmp Get XMP metadata.
|
||||
frgm n Get nth fragment.
|
||||
frame n Get nth frame.
|
||||
|
||||
SET_OPTIONS:
|
||||
@ -47,7 +45,7 @@ SET_OPTIONS:
|
||||
exif file.exif Set EXIF metadata.
|
||||
xmp file.xmp Set XMP metadata.
|
||||
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
|
||||
|
||||
STRIP_OPTIONS:
|
||||
@ -56,12 +54,6 @@ STRIP_OPTIONS:
|
||||
exif Strip EXIF 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):
|
||||
Create animation.
|
||||
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
|
||||
valid.
|
||||
|
||||
WebP viewer tool:
|
||||
================
|
||||
Visualization tool:
|
||||
===================
|
||||
|
||||
The examples/ directory also contains a tool (vwebp) for viewing WebP files.
|
||||
It decodes the image and visualizes it using OpenGL.
|
||||
|
||||
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.
|
||||
It decodes the image and visualizes it using OpenGL. See the libwebp README
|
||||
for details on building and running this program.
|
||||
|
||||
Mux API:
|
||||
========
|
||||
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
|
||||
and fragmented images. Other features may be added in subsequent releases.
|
||||
files. This API currently supports XMP/EXIF metadata, ICC profile and animation.
|
||||
Other features may be added in subsequent releases.
|
||||
|
||||
Example#1 (pseudo code): Creating a WebPMux object with image data, color
|
||||
profile and XMP metadata.
|
||||
@ -145,11 +126,11 @@ For a detailed Mux API reference, please refer to the header file
|
||||
(src/webp/mux.h).
|
||||
|
||||
Demux API:
|
||||
=========
|
||||
==========
|
||||
The Demux API enables extraction of images and extended format data from
|
||||
WebP files. This API currently supports reading of XMP/EXIF metadata, ICC
|
||||
profile, animation and fragmented images. Other features may be added in
|
||||
subsequent releases.
|
||||
profile and animated images. Other features may be added in subsequent
|
||||
releases.
|
||||
|
||||
Code Example: Demuxing WebP data to extract all the frames, ICC profile
|
||||
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://developers.google.com/speed/webp])
|
||||
AC_CANONICAL_TARGET
|
||||
@ -176,7 +176,7 @@ CPPFLAGS=$SAVED_CPPFLAGS
|
||||
LIBS=$SAVED_LIBS
|
||||
|
||||
if test "$gif_support" = "yes" -a \
|
||||
"$enable_experimental_libwebpmux" = "yes"; then
|
||||
"$enable_libwebpmux" = "yes"; then
|
||||
build_gif2webp=yes
|
||||
fi
|
||||
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],
|
||||
[Activate experimental features]))
|
||||
if test "$enable_experimental" = "yes"; then
|
||||
AC_DEFINE(EXPERIMENTAL,,[Enable experimental code])
|
||||
USE_EXPERIMENTAL_CODE="-DWEBP_EXPERIMENTAL_FEATURES"
|
||||
AC_DEFINE(WEBP_EXPERIMENTAL_FEATURES, [1], [Enable experimental code])
|
||||
USE_EXPERIMENTAL_CODE="-DWEBP_EXPERIMENTAL_FEATURES"
|
||||
fi
|
||||
AC_MSG_RESULT(${enable_experimental-no})
|
||||
AC_SUBST(USE_EXPERIMENTAL_CODE)
|
||||
|
||||
dnl === Check whether libwebpmux should be built
|
||||
AC_MSG_CHECKING(whether libwebpmux is to be built)
|
||||
AC_ARG_ENABLE([experimental-libwebpmux],
|
||||
AS_HELP_STRING([--enable-experimental-libwebpmux],
|
||||
AC_ARG_ENABLE([libwebpmux],
|
||||
AS_HELP_STRING([--enable-libwebpmux],
|
||||
[Build libwebpmux @<:@default=no@:>@]))
|
||||
AC_MSG_RESULT(${enable_experimental_libwebpmux-no})
|
||||
AM_CONDITIONAL([WANT_MUX], [test "$enable_experimental_libwebpmux" = "yes"])
|
||||
AC_MSG_RESULT(${enable_libwebpmux-no})
|
||||
AM_CONDITIONAL([WANT_MUX], [test "$enable_libwebpmux" = "yes"])
|
||||
|
||||
dnl === Check whether libwebpdemux should be built
|
||||
AC_MSG_CHECKING(whether libwebpdemux is to be built)
|
||||
AC_ARG_ENABLE([experimental-libwebpdemux],
|
||||
AS_HELP_STRING([--enable-experimental-libwebpdemux],
|
||||
AC_ARG_ENABLE([libwebpdemux],
|
||||
AS_HELP_STRING([--enable-libwebpdemux],
|
||||
[Build libwebpdemux @<:@default=no@:>@]))
|
||||
AC_MSG_RESULT(${enable_experimental_libwebpdemux-no})
|
||||
AM_CONDITIONAL([WANT_DEMUX], [test "$enable_experimental_libwebpdemux" = "yes"])
|
||||
AC_MSG_RESULT(${enable_libwebpdemux-no})
|
||||
AM_CONDITIONAL([WANT_DEMUX], [test "$enable_libwebpdemux" = "yes"])
|
||||
|
||||
dnl === Check whether decoder library should 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/demux/Makefile src/mux/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
|
||||
@ -297,8 +298,8 @@ Static libraries: ${enable_static}
|
||||
Threaded decode: ${enable_threading-no}
|
||||
libwebp: yes
|
||||
libwebpdecoder: ${enable_libwebpdecoder-no}
|
||||
libwebpdemux: ${enable_experimental_libwebpdemux-no}
|
||||
libwebpmux: ${enable_experimental_libwebpmux-no}
|
||||
libwebpdemux: ${enable_libwebpdemux-no}
|
||||
libwebpmux: ${enable_libwebpmux-no}
|
||||
|
||||
Tools:
|
||||
cwebp: yes
|
||||
@ -314,5 +315,5 @@ dwebp: yes
|
||||
PNG : ${png_support-no}
|
||||
WIC : ${wic_support-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][].
|
||||
|
||||
**Note:** Out of the features mentioned above, lossy compression, lossless
|
||||
compression and transparency are finalized and are to be considered stable.
|
||||
On the other hand, metadata, color profile, animation and image fragmentation
|
||||
are experimental as of now, and are open to discussion, feedback and comments.
|
||||
compression, transparency, metadata, color profile and animation are finalized
|
||||
and are to be considered stable. On the other hand, image fragmentation is
|
||||
experimental as of now, and is open to discussion, feedback and comments.
|
||||
The same is indicated using annotation "_status: experimental_" in the relevant
|
||||
sections of this document.
|
||||
|
||||
@ -93,11 +93,21 @@ _uint32_
|
||||
|
||||
: 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_
|
||||
|
||||
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
|
||||
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:
|
||||
|
||||
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
|
||||
|
||||
: ASCII four character code or _chunk tag_ used for chunk identification.
|
||||
: ASCII four-character code used for chunk identification.
|
||||
|
||||
Chunk Size: 32 bits (_uint32_)
|
||||
|
||||
: The size of the chunk (_ckSize_) not including this field, the chunk
|
||||
identifier and padding.
|
||||
: The size of the chunk not including this field, the chunk identifier or
|
||||
padding.
|
||||
|
||||
Chunk Payload: _Chunk Size_ bytes
|
||||
|
||||
@ -126,43 +136,13 @@ Chunk Payload: _Chunk Size_ bytes
|
||||
|
||||
_ChunkHeader('ABCD')_
|
||||
|
||||
: This is used to describe the fourcc and size header of individual
|
||||
chunks, where 'ABCD' is the fourcc for the chunk. This element's
|
||||
: 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
|
||||
size is 8 bytes.
|
||||
|
||||
: Note that, in this specification, all chunk tag characters are in
|
||||
file order, not in byte order of a uint32 of any particular
|
||||
architecture.
|
||||
|
||||
_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.
|
||||
|
||||
**Note:** RIFF has a convention that all-uppercase chunk FourCCs are standard
|
||||
chunks that apply to any RIFF file format, while FourCCs specific to a file
|
||||
format are all lowercase. WebP does not follow this convention.
|
||||
|
||||
WebP file header
|
||||
----------------
|
||||
@ -183,12 +163,20 @@ WebP file header
|
||||
|
||||
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
|
||||
|
||||
: 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)
|
||||
--------------------------
|
||||
|
||||
@ -274,15 +262,15 @@ An extended format file consists of:
|
||||
|
||||
* 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.
|
||||
|
||||
* 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\]_
|
||||
|
||||
@ -325,7 +313,7 @@ Reserved (Rsv): 2 bits
|
||||
|
||||
: SHOULD be `0`.
|
||||
|
||||
ICC profile (I): 1 bit _\[status: experimental\]_
|
||||
ICC profile (I): 1 bit
|
||||
|
||||
: 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
|
||||
("alpha").
|
||||
|
||||
EXIF metadata (E): 1 bit _\[status: experimental\]_
|
||||
EXIF metadata (E): 1 bit
|
||||
|
||||
: 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.
|
||||
|
||||
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
|
||||
used to control the animation.
|
||||
@ -371,11 +359,12 @@ Future specifications MAY add more fields.
|
||||
|
||||
### Chunks
|
||||
|
||||
#### Animation _\[status: experimental\]_
|
||||
#### Animation
|
||||
|
||||
An animation is controlled by ANIM and ANMF chunks.
|
||||
|
||||
ANIM Chunk:
|
||||
{:#anim_chunk}
|
||||
|
||||
For an animated image, this chunk contains the _global parameters_ of the
|
||||
animation.
|
||||
@ -392,10 +381,14 @@ animation.
|
||||
|
||||
Background Color: 32 bits (_uint32_)
|
||||
|
||||
: The background color of the canvas in \[Blue, Green, Red, Alpha\] byte order.
|
||||
The background color is the color used for those pixels of the canvas that are
|
||||
not covered by a frame. Background color is also used when disposal method is
|
||||
`1`.
|
||||
: The default background color of the canvas in \[Blue, Green, Red, Alpha\]
|
||||
byte order. This color is used to fill the unused space on the canvas around the
|
||||
frames, as well as the transparent pixels of the first frame. Background color
|
||||
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_)
|
||||
|
||||
@ -457,14 +450,45 @@ Reserved: 7 bits
|
||||
|
||||
Disposal method (D): 1 bit
|
||||
|
||||
: Indicates how the area used by this frame is to be treated before rendering
|
||||
the next frame on canvas:
|
||||
: Indicates how _the current frame_ is to be treated after it has been displayed
|
||||
(before rendering the next frame) on the canvas:
|
||||
|
||||
* `0`: Do not dispose. Keep the area used by this frame as it is and render
|
||||
the next frame on top of it.
|
||||
* `0`: Do not dispose. Leave the canvas as is.
|
||||
|
||||
* `1`: Dispose to background color (also part of this chunk). Restore the
|
||||
area used by this frame to background color before rendering the next frame.
|
||||
* `1`: Dispose to background color. Fill the _rectangle_ on the canvas covered
|
||||
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
|
||||
|
||||
@ -478,6 +502,9 @@ Frame Data: _Chunk Size_ - `16` bytes
|
||||
|
||||
* 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\]_
|
||||
|
||||
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)
|
||||
and [Simple file format (lossless)](#simple-file-format-lossless) respectively.
|
||||
|
||||
#### Color profile _\[status: experimental\]_
|
||||
#### Color profile
|
||||
|
||||
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
|
||||
@ -666,7 +693,7 @@ See the [ICC Specification][iccspec] for details.
|
||||
|
||||
If this chunk is not present, sRGB SHOULD be assumed.
|
||||
|
||||
#### Metadata _\[status: experimental\]_
|
||||
#### Metadata
|
||||
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
Displaying a _fragmented image_ canvas MUST be equivalent to the following
|
||||
pseudocode:
|
||||
pseudocode: _\[status: experimental\]_
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
assert VP8X.flags.hasFragments
|
||||
|
@ -11,9 +11,7 @@ endif
|
||||
|
||||
noinst_LTLIBRARIES = libexampleutil.la
|
||||
|
||||
libexampleutil_la_SOURCES = example_util.c
|
||||
libexampleutilinclude_HEADERS = example_util.h
|
||||
libexampleutilincludedir =
|
||||
libexampleutil_la_SOURCES = example_util.c example_util.h
|
||||
|
||||
dwebp_SOURCES = dwebp.c stopwatch.h
|
||||
dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
|
||||
|
@ -366,14 +366,30 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
|
||||
|
||||
enum {
|
||||
METADATA_EXIF = (1 << 0),
|
||||
METADATA_ICCP = (1 << 1),
|
||||
METADATA_ICC = (1 << 1),
|
||||
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 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'.
|
||||
static int WriteLE(FILE* const out, uint32_t val, int num) {
|
||||
uint8_t buf[4];
|
||||
@ -424,7 +440,8 @@ static int WriteWebPWithMetadata(FILE* const out,
|
||||
const WebPPicture* const picture,
|
||||
const WebPMemoryWriter* const memory_writer,
|
||||
const Metadata* const metadata,
|
||||
int keep_metadata) {
|
||||
int keep_metadata,
|
||||
int* const metadata_written) {
|
||||
const char kVP8XHeader[] = "VP8X\x0a\x00\x00\x00";
|
||||
const int kAlphaFlag = 0x10;
|
||||
const int kEXIFFlag = 0x08;
|
||||
@ -439,13 +456,16 @@ static int WriteWebPWithMetadata(FILE* const out,
|
||||
!!(keep_metadata & METADATA_EXIF),
|
||||
kEXIFFlag, &flags, &metadata_size);
|
||||
const int write_iccp = UpdateFlagsAndSize(&metadata->iccp,
|
||||
!!(keep_metadata & METADATA_ICCP),
|
||||
!!(keep_metadata & METADATA_ICC),
|
||||
kICCPFlag, &flags, &metadata_size);
|
||||
const int write_xmp = UpdateFlagsAndSize(&metadata->xmp,
|
||||
!!(keep_metadata & METADATA_XMP),
|
||||
kXMPFlag, &flags, &metadata_size);
|
||||
uint8_t* webp = memory_writer->mem;
|
||||
size_t webp_size = memory_writer->size;
|
||||
|
||||
*metadata_written = 0;
|
||||
|
||||
if (webp_size < kMinSize) return 0;
|
||||
if (webp_size - kChunkHeaderSize + metadata_size > kMaxChunkPayload) {
|
||||
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->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
|
||||
ok = ok && (fwrite(webp, webp_size, 1, out) == 1);
|
||||
if (write_exif) ok = ok && WriteMetadataChunk(out, "EXIF", &metadata->exif);
|
||||
if (write_xmp) ok = ok && WriteMetadataChunk(out, "XMP ", &metadata->xmp);
|
||||
if (write_exif) {
|
||||
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;
|
||||
} else {
|
||||
// No metadata, just write the original image file.
|
||||
@ -575,7 +604,7 @@ static void HelpLong(void) {
|
||||
printf(" ");
|
||||
printf("copy from the input to the output if present.\n");
|
||||
printf(" "
|
||||
"Valid values: all, none (default), exif, iccp, xmp\n");
|
||||
"Valid values: all, none (default), exif, icc, xmp\n");
|
||||
|
||||
printf("\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 show_progress = 0;
|
||||
int keep_metadata = 0;
|
||||
int metadata_written = 0;
|
||||
WebPPicture picture;
|
||||
int print_distortion = -1; // -1=off, 0=PSNR, 1=SSIM, 2=LSIM
|
||||
WebPPicture original_picture; // when PSNR or SSIM is requested
|
||||
@ -812,7 +842,7 @@ int main(int argc, const char *argv[]) {
|
||||
{ "all", METADATA_ALL },
|
||||
{ "none", 0 },
|
||||
{ "exif", METADATA_EXIF },
|
||||
{ "iccp", METADATA_ICCP },
|
||||
{ "icc", METADATA_ICC },
|
||||
{ "xmp", METADATA_XMP },
|
||||
};
|
||||
const size_t kNumTokens = sizeof(kTokens) / sizeof(kTokens[0]);
|
||||
@ -844,7 +874,7 @@ int main(int argc, const char *argv[]) {
|
||||
start = token + 1;
|
||||
}
|
||||
#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.
|
||||
fprintf(stderr, "Warning: only ICC profile extraction is currently"
|
||||
" supported on this platform!\n");
|
||||
@ -978,7 +1008,7 @@ int main(int argc, const char *argv[]) {
|
||||
|
||||
if (keep_metadata != 0 && out != NULL) {
|
||||
if (!WriteWebPWithMetadata(out, &picture, &memory_writer,
|
||||
&metadata, keep_metadata)) {
|
||||
&metadata, keep_metadata, &metadata_written)) {
|
||||
fprintf(stderr, "Error writing WebP file with metadata!\n");
|
||||
goto Error;
|
||||
}
|
||||
@ -990,6 +1020,9 @@ int main(int argc, const char *argv[]) {
|
||||
} else {
|
||||
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
|
||||
static const char* distortion_names[] = { "PSNR", "SSIM", "LSIM" };
|
||||
|
@ -460,6 +460,13 @@ int main(int argc, const char *argv[]) {
|
||||
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) {
|
||||
case PNG:
|
||||
#ifdef HAVE_WINCODEC_H
|
||||
|
@ -44,8 +44,8 @@ int ExUtilReadFile(const char* const file_name,
|
||||
fclose(in);
|
||||
|
||||
if (!ok) {
|
||||
fprintf(stderr, "Could not read %zu bytes of data from file %s\n",
|
||||
file_size, file_name);
|
||||
fprintf(stderr, "Could not read %d bytes of data from file %s\n",
|
||||
(int)file_size, file_name);
|
||||
free(file_data);
|
||||
return 0;
|
||||
}
|
||||
|
@ -117,36 +117,42 @@ static int ReadSubImage(GifFileType* gif, WebPPicture* pic, WebPPicture* view) {
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int GetColorFromIndex(const ColorMapObject* const color_map, GifWord idx,
|
||||
uint32_t* const argb) {
|
||||
assert(color_map != NULL && color_map->Colors != NULL);
|
||||
if (idx >= color_map->ColorCount) {
|
||||
return 0; // Invalid index.
|
||||
static int GetBackgroundColor(const ColorMapObject* const color_map,
|
||||
GifWord bgcolor_idx, uint32_t* const bgcolor) {
|
||||
if (transparent_index != -1 && bgcolor_idx == transparent_index) {
|
||||
*bgcolor = TRANSPARENT_COLOR; // Special case.
|
||||
return 1;
|
||||
} else if (color_map == NULL || color_map->Colors == NULL
|
||||
|| bgcolor_idx >= color_map->ColorCount) {
|
||||
return 0; // Invalid color map or index.
|
||||
} else {
|
||||
const GifColorType color = color_map->Colors[idx];
|
||||
*argb = (0xff << 24)
|
||||
| (color.Red << 16)
|
||||
| (color.Green << 8)
|
||||
| (color.Blue << 0);
|
||||
const GifColorType color = color_map->Colors[bgcolor_idx];
|
||||
*bgcolor = (0xff << 24)
|
||||
| (color.Red << 16)
|
||||
| (color.Green << 8)
|
||||
| (color.Blue << 0);
|
||||
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.
|
||||
// libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
|
||||
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) && \
|
||||
((GIFLIB_MAJOR == 4 && GIFLIB_MINOR >= 2) || GIFLIB_MAJOR > 4)
|
||||
#if GIFLIB_MAJOR >= 5
|
||||
// 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
|
||||
const char* error_str = (const char*)GifErrorString();
|
||||
(void)gif;
|
||||
#endif
|
||||
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
|
||||
fprintf(stderr, "GIFLib Error: ");
|
||||
(void)gif;
|
||||
fprintf(stderr, "GIFLib Error %d: ", gif_error);
|
||||
PrintGifError();
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
@ -184,7 +190,7 @@ static void Help(void) {
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
int verbose = 0;
|
||||
int gif_error = -1;
|
||||
int gif_error = GIF_ERROR;
|
||||
WebPMuxError err = WEBP_MUX_OK;
|
||||
int ok = 0;
|
||||
const char *in_file = NULL, *out_file = NULL;
|
||||
@ -196,6 +202,7 @@ int main(int argc, const char *argv[]) {
|
||||
WebPMuxFrameInfo frame;
|
||||
WebPMuxAnimParams anim = { WHITE_COLOR, 0 };
|
||||
|
||||
int is_first_frame = 1;
|
||||
int done;
|
||||
int c;
|
||||
int quiet = 0;
|
||||
@ -280,14 +287,6 @@ int main(int argc, const char *argv[]) {
|
||||
picture.custom_ptr = &memory;
|
||||
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();
|
||||
if (mux == NULL) {
|
||||
fprintf(stderr, "ERROR: could not create a mux object.\n");
|
||||
@ -340,11 +339,11 @@ int main(int argc, const char *argv[]) {
|
||||
goto End;
|
||||
}
|
||||
if (verbose) {
|
||||
fprintf(stderr, "Added frame %dx%d (offset:%d,%d duration:%d) ",
|
||||
view.width, view.height, frame.x_offset, frame.y_offset,
|
||||
frame.duration);
|
||||
fprintf(stderr, "dispose:%d transparent index:%d\n",
|
||||
frame.dispose_method, transparent_index);
|
||||
printf("Added frame %dx%d (offset:%d,%d duration:%d) ",
|
||||
view.width, view.height, frame.x_offset, frame.y_offset,
|
||||
frame.duration);
|
||||
printf("dispose:%d transparent index:%d\n",
|
||||
frame.dispose_method, transparent_index);
|
||||
}
|
||||
WebPDataClear(&frame.bitstream);
|
||||
break;
|
||||
@ -376,6 +375,15 @@ int main(int argc, const char *argv[]) {
|
||||
: WEBP_MUX_DISPOSE_NONE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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[0] != 3 && data[1] != 1) break; // wrong size/marker
|
||||
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)) {
|
||||
// Read XMP metadata.
|
||||
WebPData xmp;
|
||||
@ -398,7 +406,7 @@ int main(int argc, const char *argv[]) {
|
||||
xmp.bytes = (uint8_t*)data;
|
||||
xmp.size = data[0] + 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)) {
|
||||
// Read ICC profile.
|
||||
WebPData icc;
|
||||
@ -407,7 +415,7 @@ int main(int argc, const char *argv[]) {
|
||||
icc.bytes = (uint8_t*)data;
|
||||
icc.size = data[0] + 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;
|
||||
}
|
||||
@ -451,12 +459,18 @@ int main(int argc, const char *argv[]) {
|
||||
fprintf(stderr, "Error writing output file: %s\n", out_file);
|
||||
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.
|
||||
ok = 1;
|
||||
gif_error = 0;
|
||||
gif_error = GIF_OK;
|
||||
|
||||
End:
|
||||
WebPDataClear(&webp_data);
|
||||
@ -464,8 +478,8 @@ int main(int argc, const char *argv[]) {
|
||||
WebPPictureFree(&picture);
|
||||
if (out != NULL && out_file != NULL) fclose(out);
|
||||
|
||||
if (gif_error != 0) {
|
||||
DisplayGifError(gif);
|
||||
if (gif_error != GIF_OK) {
|
||||
DisplayGifError(gif, gif_error);
|
||||
}
|
||||
if (gif != NULL) {
|
||||
DGifCloseFile(gif);
|
||||
|
@ -79,9 +79,9 @@ static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
||||
ICCPSegment* segment;
|
||||
|
||||
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",
|
||||
segment_size, seq, count);
|
||||
(int)segment_size, seq, count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
259
examples/vwebp.c
259
examples/vwebp.c
@ -8,7 +8,7 @@
|
||||
// Simple WebP file viewer.
|
||||
//
|
||||
// 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
|
||||
// Compiling on Mac + XCode:
|
||||
// gcc -o vwebp vwebp.c -lwebp -lwebpmux -framework GLUT -framework OpenGL
|
||||
@ -19,9 +19,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webp/decode.h"
|
||||
#include "webp/demux.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
@ -31,6 +28,13 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WEBP_HAVE_QCMS
|
||||
#include <qcms.h>
|
||||
#endif
|
||||
|
||||
#include "webp/decode.h"
|
||||
#include "webp/demux.h"
|
||||
|
||||
#include "./example_util.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -42,9 +46,11 @@ static void Help(void);
|
||||
// Unfortunate global variables. Gathered into a struct for comfort.
|
||||
static struct {
|
||||
int has_animation;
|
||||
int has_color_profile;
|
||||
int done;
|
||||
int decoding_error;
|
||||
int print_info;
|
||||
int use_color_profile;
|
||||
|
||||
int canvas_width, canvas_height;
|
||||
int loop_count;
|
||||
@ -56,6 +62,12 @@ static struct {
|
||||
const WebPDecBuffer* pic;
|
||||
WebPDemuxer* dmux;
|
||||
WebPIterator frameiter;
|
||||
struct {
|
||||
int width, height;
|
||||
int x_offset, y_offset;
|
||||
enum WebPMuxAnimDispose dispose_method;
|
||||
} prev_frame;
|
||||
WebPChunkIterator iccp;
|
||||
} kParams;
|
||||
|
||||
static void ClearPreviousPic(void) {
|
||||
@ -67,10 +79,128 @@ static void ClearParams(void) {
|
||||
ClearPreviousPic();
|
||||
WebPDataClear(&kParams.data);
|
||||
WebPDemuxReleaseIterator(&kParams.frameiter);
|
||||
WebPDemuxReleaseChunkIterator(&kParams.iccp);
|
||||
WebPDemuxDelete(kParams.dmux);
|
||||
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
|
||||
|
||||
@ -84,6 +214,24 @@ static void HandleKey(unsigned char key, int pos_x, int pos_y) {
|
||||
ClearParams();
|
||||
exit(0);
|
||||
#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') {
|
||||
kParams.print_info = 1 - kParams.print_info;
|
||||
glutPostRedisplay();
|
||||
@ -141,24 +289,46 @@ static void HandleDisplay(void) {
|
||||
glPixelZoom(1, -1);
|
||||
xoff = (GLfloat)(2. * iter->x_offset / kParams.canvas_width);
|
||||
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_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
|
||||
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,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
(GLvoid*)pic->u.RGBA.rgba);
|
||||
if (kParams.print_info) {
|
||||
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);
|
||||
PrintString(kParams.file_name);
|
||||
|
||||
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);
|
||||
PrintString(tmp);
|
||||
if (iter->x_offset != 0 || iter->y_offset != 0) {
|
||||
@ -192,55 +362,6 @@ static void StartDisplay(void) {
|
||||
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
|
||||
|
||||
@ -249,6 +370,7 @@ static void Help(void) {
|
||||
"Decodes the WebP image file and visualize it using OpenGL\n"
|
||||
"Options are:\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"
|
||||
" -nofilter .... disable in-loop filtering.\n"
|
||||
" -mt .......... use multi-threading.\n"
|
||||
@ -256,6 +378,7 @@ static void Help(void) {
|
||||
" -h ....... this help message.\n"
|
||||
"\n"
|
||||
"Keyboard shortcuts:\n"
|
||||
" 'c' ................ toggle use of color profile.\n"
|
||||
" 'i' ................ overlay file information.\n"
|
||||
" 'q' / 'Q' / ESC .... quit.\n"
|
||||
);
|
||||
@ -270,11 +393,14 @@ int main(int argc, char *argv[]) {
|
||||
return -1;
|
||||
}
|
||||
kParams.config = &config;
|
||||
kParams.use_color_profile = 1;
|
||||
|
||||
for (c = 1; c < argc; ++c) {
|
||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||
Help();
|
||||
return 0;
|
||||
} else if (!strcmp(argv[c], "-noicc")) {
|
||||
kParams.use_color_profile = 0;
|
||||
} else if (!strcmp(argv[c], "-nofancy")) {
|
||||
config.options.no_fancy_upsampling = 1;
|
||||
} 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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
kParams.has_animation = (kParams.frameiter.num_frames > 1);
|
||||
|
@ -17,12 +17,6 @@
|
||||
/* Usage examples:
|
||||
|
||||
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 \
|
||||
-frame anim_2.webp +100+25+25+1 \
|
||||
-frame anim_3.webp +100+50+50+1 \
|
||||
@ -52,6 +46,10 @@
|
||||
webpmux -version
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -185,6 +183,9 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
||||
uint32_t 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");
|
||||
|
||||
if (flag == 0) {
|
||||
@ -196,7 +197,7 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
||||
printf("Features present:");
|
||||
if (flag & ANIMATION_FLAG) printf(" animation");
|
||||
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 & XMP_FLAG) printf(" XMP metadata");
|
||||
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);
|
||||
printf("%3d: %8d %8d ", i, frame.x_offset, frame.y_offset);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -241,28 +242,28 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
||||
WebPData icc_profile;
|
||||
err = WebPMuxGetChunk(mux, "ICCP", &icc_profile);
|
||||
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) {
|
||||
WebPData exif;
|
||||
err = WebPMuxGetChunk(mux, "EXIF", &exif);
|
||||
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) {
|
||||
WebPData xmp;
|
||||
err = WebPMuxGetChunk(mux, "XMP ", &xmp);
|
||||
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))) {
|
||||
WebPMuxFrameInfo image;
|
||||
err = WebPMuxGetFrame(mux, 1, &image);
|
||||
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;
|
||||
@ -272,7 +273,9 @@ static void PrintHelp(void) {
|
||||
printf("Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT\n");
|
||||
printf(" webpmux -set SET_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");
|
||||
#endif
|
||||
printf(" webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]"
|
||||
"\n");
|
||||
printf(" [-bgcolor BACKGROUND_COLOR] -o OUTPUT\n");
|
||||
@ -286,7 +289,9 @@ static void PrintHelp(void) {
|
||||
printf(" icc Get ICC profile.\n");
|
||||
printf(" exif Get EXIF metadata.\n");
|
||||
printf(" xmp Get XMP metadata.\n");
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
printf(" frgm n Get nth fragment.\n");
|
||||
#endif
|
||||
printf(" frame n Get nth frame.\n");
|
||||
|
||||
printf("\n");
|
||||
@ -306,6 +311,7 @@ static void PrintHelp(void) {
|
||||
printf(" exif Strip EXIF metadata.\n");
|
||||
printf(" xmp Strip XMP metadata.\n");
|
||||
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
printf("\n");
|
||||
printf("FRAGMENT_OPTIONS(i):\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(" 'xi','yi' specify the image offset for this fragment."
|
||||
"\n");
|
||||
#endif
|
||||
|
||||
printf("\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) {
|
||||
fprintf(stderr, "Error writing file %s!\n", filename);
|
||||
} 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;
|
||||
}
|
||||
if (fout != stdout) fclose(fout);
|
||||
@ -596,6 +604,7 @@ static int ParseCommandLine(int argc, const char* argv[],
|
||||
arg->params_ = argv[i + 1];
|
||||
++feature_arg_index;
|
||||
i += 2;
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
} else if (!strcmp(argv[i], "-frgm")) {
|
||||
CHECK_NUM_ARGS_LESS(3, ErrParse);
|
||||
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];
|
||||
++feature_arg_index;
|
||||
i += 3;
|
||||
#endif
|
||||
} else if (!strcmp(argv[i], "-o")) {
|
||||
CHECK_NUM_ARGS_LESS(2, ErrParse);
|
||||
config->output_ = argv[i + 1];
|
||||
@ -660,8 +670,12 @@ static int ParseCommandLine(int argc, const char* argv[],
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
} else if ((!strcmp(argv[i], "frame") ||
|
||||
!strcmp(argv[i], "frgm")) &&
|
||||
#else
|
||||
} else if (!strcmp(argv[i], "frame") &&
|
||||
#endif
|
||||
(config->action_type_ == ACTION_GET)) {
|
||||
CHECK_NUM_ARGS_LESS(2, ErrParse);
|
||||
feature->type_ = (!strcmp(argv[i], "frame")) ? FEATURE_ANMF :
|
||||
@ -763,12 +777,12 @@ static int InitializeConfig(int argc, const char* argv[],
|
||||
// Processing.
|
||||
|
||||
static int GetFrameFragment(const WebPMux* mux,
|
||||
const WebPMuxConfig* config, int isFrame) {
|
||||
const WebPMuxConfig* config, int is_frame) {
|
||||
WebPMuxError err = WEBP_MUX_OK;
|
||||
WebPMux* mux_single = NULL;
|
||||
long num = 0;
|
||||
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;
|
||||
WebPDataInit(&info.bitstream);
|
||||
|
||||
|
@ -168,7 +168,10 @@ LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS)
|
||||
|
||||
HDRS_INSTALLED = \
|
||||
src/webp/decode.h \
|
||||
src/webp/demux.h \
|
||||
src/webp/encode.h \
|
||||
src/webp/mux.h \
|
||||
src/webp/mux_types.h \
|
||||
src/webp/types.h \
|
||||
|
||||
HDRS = \
|
||||
@ -191,22 +194,21 @@ HDRS = \
|
||||
src/utils/quant_levels_dec.h \
|
||||
src/utils/rescaler.h \
|
||||
src/utils/thread.h \
|
||||
src/webp/demux.h \
|
||||
src/webp/format_constants.h \
|
||||
src/webp/mux.h \
|
||||
src/webp/mux_types.h \
|
||||
$(HDRS_INSTALLED) \
|
||||
|
||||
OUT_LIBS = examples/libexample_util.a src/libwebpdecoder.a src/libwebp.a
|
||||
OUT_EXAMPLES = examples/cwebp examples/dwebp
|
||||
EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux
|
||||
|
||||
OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES)
|
||||
ifeq ($(MAKECMDGOALS),clean)
|
||||
OUTPUT += examples/gif2webp examples/vwebp examples/webpmux
|
||||
OUTPUT += $(EXTRA_EXAMPLES)
|
||||
OUTPUT += src/demux/libwebpdemux.a src/mux/libwebpmux.a
|
||||
endif
|
||||
|
||||
all: ex
|
||||
ex: $(OUT_EXAMPLES)
|
||||
all: ex $(EXTRA_EXAMPLES)
|
||||
|
||||
$(EX_FORMAT_DEC_OBJS): %.o: %.h
|
||||
|
||||
@ -222,8 +224,6 @@ src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS)
|
||||
%.a:
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
ex: $(OUT_EXAMPLES)
|
||||
|
||||
examples/cwebp: examples/cwebp.o $(EX_FORMAT_DEC_OBJS)
|
||||
examples/dwebp: examples/dwebp.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: src/libwebpdecoder.a
|
||||
|
||||
$(OUT_EXAMPLES) examples/gif2webp examples/vwebp examples/webpmux:
|
||||
$(OUT_EXAMPLES) $(EXTRA_EXAMPLES):
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
dist: DESTDIR := dist
|
||||
dist: OUT_EXAMPLES += $(EXTRA_EXAMPLES)
|
||||
dist: all
|
||||
$(INSTALL) -m755 -d $(DESTDIR)/include/webp \
|
||||
$(DESTDIR)/doc $(DESTDIR)/lib
|
||||
$(INSTALL) -m755 -s $(OUT_EXAMPLES) $(DESTDIR)
|
||||
$(INSTALL) -m644 $(HDRS_INSTALLED) $(DESTDIR)/include/webp
|
||||
$(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; \
|
||||
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); \
|
||||
$(GROFF) -t -e -man -T utf8 $$m \
|
||||
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH CWEBP 1 "March 8, 2013"
|
||||
.TH CWEBP 1 "March 13, 2013"
|
||||
.SH NAME
|
||||
cwebp \- compress an image file to a WebP file
|
||||
.SH SYNOPSIS
|
||||
@ -200,7 +200,7 @@ Specify the hint about input image type. Possible values are:
|
||||
.BI \-metadata " string
|
||||
A comma separated list of metadata to copy from the input to the output if
|
||||
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.
|
||||
|
||||
Note: each input format may not support all combinations.
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH WEBPMUX 1 "February 26, 2013"
|
||||
.TH WEBPMUX 1 "March 16, 2013"
|
||||
.SH NAME
|
||||
webpmux \- command line tool to create WebP Mux/container file.
|
||||
.SH SYNOPSIS
|
||||
@ -21,11 +21,6 @@ webpmux \- command line tool to create WebP Mux/container file.
|
||||
.B \-o
|
||||
.I OUTPUT
|
||||
.br
|
||||
.B webpmux \-frgm
|
||||
.I FRAGMENT_OPTIONS
|
||||
.B [ \-frgm ... ] \-o
|
||||
.I OUTPUT
|
||||
.br
|
||||
.B webpmux \-frame
|
||||
.I FRAME_OPTIONS
|
||||
.B [ \-frame ... ] [ \-loop
|
||||
@ -64,9 +59,6 @@ Get EXIF metadata.
|
||||
.B xmp
|
||||
Get XMP metadata.
|
||||
.TP
|
||||
.BI frgm " n
|
||||
Get nth fragment.
|
||||
.TP
|
||||
.BI frame " n
|
||||
Get nth frame.
|
||||
|
||||
@ -98,12 +90,6 @@ Strip EXIF metadata.
|
||||
.B xmp
|
||||
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)
|
||||
.TP
|
||||
.I file_i +di[+xi+yi[+mi]]
|
||||
@ -163,18 +149,13 @@ webpmux \-get exif exif_container.webp \-o image_metadata.exif
|
||||
.br
|
||||
webpmux \-strip exif exif_container.webp \-o without_exif.webp
|
||||
.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
|
||||
.RS 8
|
||||
\-bgcolor 255,255,255,255 \-o anim_container.webp
|
||||
.RE
|
||||
.br
|
||||
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
|
||||
\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
|
||||
SUBDIRS += mux
|
||||
endif
|
||||
@ -13,11 +15,14 @@ if BUILD_LIBWEBPDECODER
|
||||
lib_LTLIBRARIES += libwebpdecoder.la
|
||||
endif
|
||||
|
||||
common_HEADERS =
|
||||
common_HEADERS += webp/decode.h
|
||||
common_HEADERS += webp/types.h
|
||||
commondir = $(includedir)/webp
|
||||
|
||||
libwebp_la_SOURCES =
|
||||
libwebpinclude_HEADERS =
|
||||
libwebpinclude_HEADERS += webp/decode.h
|
||||
libwebpinclude_HEADERS += webp/encode.h
|
||||
libwebpinclude_HEADERS += webp/types.h
|
||||
noinst_HEADERS =
|
||||
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
|
||||
# not have unresolved symbols. Some platforms (Windows among them) require all
|
||||
# symbols in shared libraries to be resolved at library creation.
|
||||
libwebp_la_LDFLAGS = -no-undefined -version-info 4:1:0
|
||||
libwebp_la_LDFLAGS = -no-undefined -version-info 4:2:0
|
||||
libwebpincludedir = $(includedir)/webp
|
||||
pkgconfig_DATA = libwebp.pc
|
||||
|
||||
if BUILD_LIBWEBPDECODER
|
||||
libwebpdecoder_la_SOURCES =
|
||||
libwebpdecoderinclude_HEADERS =
|
||||
libwebpdecoderinclude_HEADERS += webp/decode.h
|
||||
libwebpdecoderinclude_HEADERS += webp/types.h
|
||||
|
||||
libwebpdecoder_la_LIBADD =
|
||||
libwebpdecoder_la_LIBADD += dec/libwebpdecode.la
|
||||
@ -47,7 +49,6 @@ if BUILD_LIBWEBPDECODER
|
||||
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
||||
|
||||
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 0:0:0
|
||||
libwebpdecoderincludedir = $(includedir)/webp
|
||||
pkgconfig_DATA += libwebpdecoder.pc
|
||||
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) {
|
||||
uint8_t* decoded_data = NULL;
|
||||
const size_t decoded_size = height * width;
|
||||
uint8_t* unfiltered_data = NULL;
|
||||
WEBP_FILTER_TYPE filter;
|
||||
int pre_processing;
|
||||
int rsrv;
|
||||
@ -83,29 +82,19 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size,
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
WebPFilterFunc unfilter_func = WebPUnfilters[filter];
|
||||
WebPUnfilterFunc unfilter_func = WebPUnfilters[filter];
|
||||
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
|
||||
// and apply filter per image-row.
|
||||
unfilter_func(decoded_data, width, height, 1, width, unfiltered_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);
|
||||
unfilter_func(width, height, width, decoded_data);
|
||||
}
|
||||
// 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) {
|
||||
ok = DequantizeLevels(decoded_data, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
Error:
|
||||
if (method != ALPHA_NO_COMPRESSION) {
|
||||
free(decoded_data);
|
||||
}
|
||||
|
@ -27,8 +27,8 @@ extern "C" {
|
||||
|
||||
// version numbers
|
||||
#define DEC_MAJ_VERSION 0
|
||||
#define DEC_MIN_VERSION 2
|
||||
#define DEC_REV_VERSION 1
|
||||
#define DEC_MIN_VERSION 3
|
||||
#define DEC_REV_VERSION 0
|
||||
|
||||
#define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include "./vp8i.h"
|
||||
#include "./vp8li.h"
|
||||
#include "./webpi.h"
|
||||
#include "../webp/format_constants.h"
|
||||
#include "../webp/mux_types.h" // ALPHA_FLAG
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
@ -276,6 +276,7 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
|
||||
int* const width,
|
||||
int* const height,
|
||||
int* const has_alpha,
|
||||
int* const has_animation,
|
||||
WebPHeaderStructure* const headers) {
|
||||
int found_riff = 0;
|
||||
int found_vp8x = 0;
|
||||
@ -309,6 +310,7 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
|
||||
return VP8_STATUS_BITSTREAM_ERROR;
|
||||
}
|
||||
if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG);
|
||||
if (has_animation != NULL) *has_animation = !!(flags & ANIMATION_FLAG);
|
||||
if (found_vp8x && headers == NULL) {
|
||||
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 status;
|
||||
int has_animation = 0;
|
||||
assert(headers != NULL);
|
||||
// fill out headers, ignore width/height/has_alpha.
|
||||
return ParseHeadersInternal(headers->data, headers->data_size,
|
||||
NULL, NULL, NULL, headers);
|
||||
status = ParseHeadersInternal(headers->data, headers->data_size,
|
||||
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);
|
||||
|
||||
// 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,
|
||||
&features->width, &features->height,
|
||||
&features->has_alpha, NULL);
|
||||
&features->has_alpha, &features->has_animation,
|
||||
NULL);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -61,10 +61,10 @@ typedef struct {
|
||||
} WebPHeaderStructure;
|
||||
|
||||
// Skips over all valid chunks prior to the first VP8/VP8L frame header.
|
||||
// Returns VP8_STATUS_OK on success,
|
||||
// VP8_STATUS_BITSTREAM_ERROR if an invalid header/chunk is found, and
|
||||
// VP8_STATUS_NOT_ENOUGH_DATA if case of insufficient data.
|
||||
// In 'headers', compressed_size, offset, alpha_data, alpha_size and lossless
|
||||
// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk),
|
||||
// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE
|
||||
// in the case of non-decodable features (animation for instance).
|
||||
// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless
|
||||
// fields are updated appropriately upon success.
|
||||
VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
|
||||
|
||||
|
@ -6,7 +6,10 @@ libwebpdemux_la_SOURCES += demux.c
|
||||
|
||||
libwebpdemuxinclude_HEADERS =
|
||||
libwebpdemuxinclude_HEADERS += ../webp/demux.h
|
||||
libwebpdemuxinclude_HEADERS += ../webp/mux_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
|
||||
pkgconfig_DATA = libwebpdemux.pc
|
||||
|
@ -8,6 +8,10 @@
|
||||
// WebP container demux.
|
||||
//
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -65,6 +69,7 @@ struct WebPDemuxer {
|
||||
uint32_t bgcolor_;
|
||||
int num_frames_;
|
||||
Frame* frames_;
|
||||
Frame** frames_tail_;
|
||||
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.
|
||||
// Returns true on success, false otherwise.
|
||||
static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
|
||||
const Frame* last_frame = NULL;
|
||||
Frame** f = &dmux->frames_;
|
||||
while (*f != NULL) {
|
||||
last_frame = *f;
|
||||
f = &(*f)->next_;
|
||||
}
|
||||
const Frame* const last_frame = *dmux->frames_tail_;
|
||||
if (last_frame != NULL && !last_frame->complete_) return 0;
|
||||
*f = frame;
|
||||
|
||||
*dmux->frames_tail_ = frame;
|
||||
frame->next_ = NULL;
|
||||
dmux->frames_tail_ = &frame->next_;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -231,8 +233,10 @@ static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
|
||||
goto Done;
|
||||
}
|
||||
break;
|
||||
case MKFOURCC('V', 'P', '8', ' '):
|
||||
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) {
|
||||
// Extract the bitstream features, tolerating failures when the data
|
||||
// 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.
|
||||
// 'frame_chunk_size' is the previously validated, padded chunk size.
|
||||
static ParseStatus ParseFrame(
|
||||
static ParseStatus ParseAnimationFrame(
|
||||
WebPDemuxer* const dmux, uint32_t frame_chunk_size) {
|
||||
const int has_frames = !!(dmux->feature_flags_ & ANIMATION_FLAG);
|
||||
const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
|
||||
@ -316,8 +320,8 @@ static ParseStatus ParseFrame(
|
||||
return PARSE_ERROR;
|
||||
}
|
||||
|
||||
// Store a frame only if the animation flag is set and all data for this frame
|
||||
// is available.
|
||||
// Store a frame only if the animation flag is set there is some data for
|
||||
// this frame is available.
|
||||
status = StoreFrame(dmux->num_frames_ + 1, anmf_payload_size, mem, frame,
|
||||
NULL);
|
||||
if (status != PARSE_ERROR && has_frames && frame->frame_num_ > 0) {
|
||||
@ -333,6 +337,7 @@ static ParseStatus ParseFrame(
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
// Parse a 'FRGM' chunk and any image bearing chunks that immediately follow.
|
||||
// 'fragment_chunk_size' is the previously validated, padded chunk size.
|
||||
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);
|
||||
if (status != PARSE_OK) return status;
|
||||
|
||||
frame->is_fragment_ = 1;
|
||||
frame->is_fragment_ = 1;
|
||||
frame->x_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
|
||||
// fragment is available.
|
||||
// Store a fragment only if the fragments flag is set there is some data for
|
||||
// this fragment is available.
|
||||
status = StoreFrame(frame_num, frgm_payload_size, mem, frame, NULL);
|
||||
if (status != PARSE_ERROR && has_fragments && frame->frame_num_ > 0) {
|
||||
added_fragment = AddFrame(dmux, frame);
|
||||
@ -366,8 +371,9 @@ static ParseStatus ParseFragment(WebPDemuxer* const dmux,
|
||||
if (!added_fragment) free(frame);
|
||||
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
|
||||
// header and the unpadded payload size.
|
||||
// Returns true on success, false otherwise.
|
||||
@ -424,7 +430,7 @@ static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) {
|
||||
frame = (Frame*)calloc(1, sizeof(*frame));
|
||||
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.
|
||||
status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame,
|
||||
&has_vp8l_alpha);
|
||||
@ -500,6 +506,9 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
|
||||
case MKFOURCC('A', 'L', 'P', 'H'):
|
||||
case MKFOURCC('V', 'P', '8', ' '):
|
||||
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);
|
||||
status = ParseSingleImage(dmux);
|
||||
break;
|
||||
@ -521,13 +530,16 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
case MKFOURCC('F', 'R', 'G', 'M'): {
|
||||
status = ParseFragment(dmux, chunk_size_padded);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case MKFOURCC('I', 'C', 'C', 'P'): {
|
||||
store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG);
|
||||
goto Skip;
|
||||
@ -615,6 +627,9 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
|
||||
|
||||
if (f->width_ <= 0 || f->height_ <= 0) return 0;
|
||||
} 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.
|
||||
if (alpha->size_ > 0 && image->size_ > 0 &&
|
||||
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->canvas_width_ = -1;
|
||||
dmux->canvas_height_ = -1;
|
||||
dmux->frames_tail_ = &dmux->frames_;
|
||||
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
|
||||
endif
|
||||
|
||||
COMMON_SOURCES =
|
||||
common_HEADERS = ../webp/types.h
|
||||
commondir = $(includedir)/webp
|
||||
|
||||
COMMON_SOURCES =
|
||||
COMMON_SOURCES += cpu.c
|
||||
COMMON_SOURCES += dec.c
|
||||
COMMON_SOURCES += dec_neon.c
|
||||
@ -19,13 +22,12 @@ COMMON_SOURCES += upsampling_sse2.c
|
||||
COMMON_SOURCES += yuv.c
|
||||
COMMON_SOURCES += yuv.h
|
||||
|
||||
ENC_SOURCES =
|
||||
ENC_SOURCES =
|
||||
ENC_SOURCES += enc.c
|
||||
ENC_SOURCES += enc_neon.c
|
||||
ENC_SOURCES += enc_sse2.c
|
||||
|
||||
libwebpdsp_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES)
|
||||
libwebpdspinclude_HEADERS = ../webp/types.h
|
||||
|
||||
noinst_HEADERS =
|
||||
noinst_HEADERS += ../dec/decode_vp8.h
|
||||
@ -33,13 +35,10 @@ noinst_HEADERS += ../webp/decode.h
|
||||
|
||||
libwebpdsp_la_LDFLAGS = -lm
|
||||
libwebpdsp_la_CPPFLAGS = $(USE_EXPERIMENTAL_CODE) $(USE_SWAP_16BIT_CSP)
|
||||
libwebpdspincludedir = $(includedir)/webp
|
||||
|
||||
if BUILD_LIBWEBPDECODER
|
||||
libwebpdspdecode_la_SOURCES = $(COMMON_SOURCES)
|
||||
libwebpdspdecodeinclude_HEADERS = $(libwebpdspinclude_HEADERS)
|
||||
|
||||
libwebpdspdecode_la_LDFLAGS = $(libwebpdsp_la_LDFLAGS)
|
||||
libwebpdspdecode_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS)
|
||||
libwebpdspdecodeincludedir = $(libwebpdspincludedir)
|
||||
endif
|
||||
|
@ -631,13 +631,13 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16],
|
||||
for (; n < 16; ++n) {
|
||||
const int j = kZigzag[n];
|
||||
const int sign = (in[j] < 0);
|
||||
int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
|
||||
if (coeff > 2047) coeff = 2047;
|
||||
const int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
|
||||
if (coeff > mtx->zthresh_[j]) {
|
||||
const int Q = mtx->q_[j];
|
||||
const int iQ = mtx->iq_[j];
|
||||
const int B = mtx->bias_[j];
|
||||
out[n] = QUANTDIV(coeff, iQ, B);
|
||||
if (out[n] > MAX_LEVEL) out[n] = MAX_LEVEL;
|
||||
if (sign) out[n] = -out[n];
|
||||
in[j] = out[n] * Q;
|
||||
if (out[n]) last = n;
|
||||
|
@ -776,7 +776,7 @@ static int Disto16x16SSE2(const uint8_t* const a, const uint8_t* const b,
|
||||
// Simple quantization
|
||||
static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
|
||||
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();
|
||||
__m128i coeff0, coeff8;
|
||||
__m128i out0, out8;
|
||||
@ -812,10 +812,6 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
|
||||
coeff0 = _mm_add_epi16(coeff0, sharpen0);
|
||||
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;
|
||||
{
|
||||
// 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_08 = _mm_srai_epi32(out_08, QFIX);
|
||||
out_12 = _mm_srai_epi32(out_12, QFIX);
|
||||
|
||||
// pack result as 16b
|
||||
out0 = _mm_packs_epi32(out_00, out_04);
|
||||
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)
|
||||
|
@ -15,7 +15,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum { YUV_HALF = 1 << (YUV_FIX - 1) };
|
||||
#ifdef WEBP_YUV_USE_TABLE
|
||||
|
||||
int16_t VP8kVToR[256], VP8kUToB[256];
|
||||
int32_t VP8kVToG[256], VP8kUToG[256];
|
||||
@ -62,6 +62,12 @@ void VP8YUVInit(void) {
|
||||
done = 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void VP8YUVInit(void) {}
|
||||
|
||||
#endif // WEBP_YUV_USE_TABLE
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} // extern "C"
|
||||
#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)
|
||||
// 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.
|
||||
// But the common term 1.164 * (Y-16) can be handled as an offset in the
|
||||
// VP8kClip[] table. So the formulae should be read as:
|
||||
// In the table-lookup version (WEBP_YUV_USE_TABLE), the common factor
|
||||
// "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
|
||||
// G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624
|
||||
// B = 1.164 * [Y + 1.733 * (U-128)] - 18.624
|
||||
@ -33,6 +34,9 @@
|
||||
|
||||
#include "../dec/decode_vp8.h"
|
||||
|
||||
// Define the following to use the LUT-based code:
|
||||
#define WEBP_YUV_USE_TABLE
|
||||
|
||||
#if defined(WEBP_EXPERIMENTAL_FEATURES)
|
||||
// Do NOT activate this feature for real compression. This is only experimental!
|
||||
// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace.
|
||||
@ -51,9 +55,14 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
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_MAX = 256 + 226 // max value of r/g/b output
|
||||
};
|
||||
|
||||
#ifdef WEBP_YUV_USE_TABLE
|
||||
|
||||
extern int16_t VP8kVToR[256], VP8kUToB[256];
|
||||
extern int32_t VP8kVToG[256], VP8kUToG[256];
|
||||
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];
|
||||
}
|
||||
|
||||
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,
|
||||
uint8_t* const rgb) {
|
||||
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
|
||||
}
|
||||
|
||||
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,
|
||||
uint8_t* const argb) {
|
||||
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
|
||||
}
|
||||
|
||||
#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,
|
||||
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];
|
||||
bgr[0] = VP8Clip8(VP8YUVToB(y, u));
|
||||
bgr[1] = VP8Clip8(VP8YUVToG(y, u, v));
|
||||
bgr[2] = VP8Clip8(VP8YUVToR(y, v));
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -127,8 +127,8 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
|
||||
VP8BitWriterAppend(bw, &header, ALPHA_HEADER_LEN);
|
||||
|
||||
filter_func = WebPFilters[filter];
|
||||
if (filter_func) {
|
||||
filter_func(data, width, height, 1, width, tmp_alpha);
|
||||
if (filter_func != NULL) {
|
||||
filter_func(data, width, height, width, tmp_alpha);
|
||||
alpha_src = tmp_alpha;
|
||||
} else {
|
||||
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.
|
||||
// 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,
|
||||
731, 640, 640, 828, 901, 948, 1021, 1101,
|
||||
1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,
|
||||
|
@ -18,7 +18,8 @@
|
||||
extern "C" {
|
||||
#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)
|
||||
|
||||
// Cost of coding one event with probability 'proba'.
|
||||
|
@ -901,15 +901,21 @@ int VP8EncLoop(VP8Encoder* const enc) {
|
||||
// Single pass using Token Buffer.
|
||||
|
||||
#if !defined(DISABLE_TOKEN_BUFFER)
|
||||
|
||||
#define MIN_COUNT 96 // minimum number of macroblocks before updating stats
|
||||
|
||||
int VP8EncTokenLoop(VP8Encoder* const enc) {
|
||||
int ok;
|
||||
// refresh the proba 8 times per pass
|
||||
const int max_count = (enc->mb_w_ * enc->mb_h_) >> 3;
|
||||
int cnt = max_count;
|
||||
// Roughly refresh the proba height times per pass
|
||||
int max_count = (enc->mb_w_ * enc->mb_h_) >> 3;
|
||||
int cnt;
|
||||
VP8EncIterator it;
|
||||
VP8Proba* const proba = &enc->proba_;
|
||||
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->use_tokens_);
|
||||
assert(proba->use_skip_proba_ == 0);
|
||||
|
@ -98,8 +98,6 @@ void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static double BitsEntropy(const int* const array, int n) {
|
||||
double retval = 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.
|
||||
// The constants in this function are experimental.
|
||||
static double HuffmanCost(const int* const population, int length) {
|
||||
@ -207,19 +186,150 @@ static double HuffmanCost(const int* const population, int length) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Estimates the Huffman dictionary + other block overhead size.
|
||||
static double HistogramEstimateBitsHeader(const VP8LHistogram* const p) {
|
||||
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);
|
||||
static double PopulationCost(const int* const population, int length) {
|
||||
return BitsEntropy(population, length) + HuffmanCost(population, length);
|
||||
}
|
||||
|
||||
double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
|
||||
return HistogramEstimateBitsHeader(p) + VP8LHistogramEstimateBitsBulk(p);
|
||||
static double ExtraCost(const int* const population, int length) {
|
||||
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,
|
||||
const VP8LBackwardRefs* const backward_refs,
|
||||
VP8LHistogramSet* const image) {
|
||||
@ -273,7 +383,7 @@ static int HistogramCombine(const VP8LHistogramSet* const in,
|
||||
// Collapse similar histograms in 'out'.
|
||||
for (iter = 0; iter < outer_iters && out_size >= min_cluster_size; ++iter) {
|
||||
double best_cost_diff = 0.;
|
||||
int best_idx1 = 0, best_idx2 = 1;
|
||||
int best_idx1 = -1, best_idx2 = 1;
|
||||
int j;
|
||||
const int num_tries = (num_pairs < out_size) ? num_pairs : out_size;
|
||||
seed += iter;
|
||||
@ -281,20 +391,17 @@ static int HistogramCombine(const VP8LHistogramSet* const in,
|
||||
double curr_cost_diff;
|
||||
// Choose two histograms at random and try to combine them.
|
||||
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 idx2 = (idx1 + diff + 1) % out_size;
|
||||
if (idx1 == idx2) {
|
||||
continue;
|
||||
}
|
||||
*cur_combo = *out->histograms[idx1];
|
||||
VP8LHistogramAdd(cur_combo, out->histograms[idx2]);
|
||||
cur_combo->bit_cost_ = VP8LHistogramEstimateBits(cur_combo);
|
||||
// Calculate cost reduction on combining.
|
||||
curr_cost_diff = cur_combo->bit_cost_
|
||||
- out->histograms[idx1]->bit_cost_
|
||||
- out->histograms[idx2]->bit_cost_;
|
||||
if (best_cost_diff > curr_cost_diff) { // found a better pair?
|
||||
curr_cost_diff = HistogramAddEval(out->histograms[idx1],
|
||||
out->histograms[idx2],
|
||||
cur_combo, best_cost_diff);
|
||||
if (curr_cost_diff < best_cost_diff) { // found a better pair?
|
||||
{ // swap cur/best combo histograms
|
||||
VP8LHistogram* const tmp_histo = cur_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;
|
||||
// swap best_idx2 slot with last one (which is now unused)
|
||||
--out_size;
|
||||
@ -331,20 +438,11 @@ static int HistogramCombine(const VP8LHistogramSet* const in,
|
||||
// -----------------------------------------------------------------------------
|
||||
// Histogram refinement
|
||||
|
||||
// What is the bit cost of moving square_histogram from
|
||||
// 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.
|
||||
// What is the bit cost of moving square_histogram from cur_symbol to candidate.
|
||||
static double HistogramDistance(const VP8LHistogram* const square_histogram,
|
||||
const VP8LHistogram* const candidate) {
|
||||
const double previous_bit_cost = candidate->bit_cost_;
|
||||
double new_bit_cost;
|
||||
VP8LHistogram modified_histo;
|
||||
modified_histo = *candidate;
|
||||
VP8LHistogramAdd(&modified_histo, square_histogram);
|
||||
new_bit_cost = VP8LHistogramEstimateBits(&modified_histo);
|
||||
|
||||
return new_bit_cost - previous_bit_cost;
|
||||
const VP8LHistogram* const candidate,
|
||||
double cost_threshold) {
|
||||
return HistogramAddThresh(candidate, square_histogram, cost_threshold);
|
||||
}
|
||||
|
||||
// Find the best 'out' histogram for each of the 'in' histograms.
|
||||
@ -355,11 +453,12 @@ static void HistogramRemap(const VP8LHistogramSet* const in,
|
||||
int i;
|
||||
for (i = 0; i < in->size; ++i) {
|
||||
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;
|
||||
for (k = 1; k < out->size; ++k) {
|
||||
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) {
|
||||
best_bits = cur_bits;
|
||||
best_out = k;
|
||||
@ -373,7 +472,7 @@ static void HistogramRemap(const VP8LHistogramSet* const in,
|
||||
HistogramClear(out->histograms[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.
|
||||
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) {
|
||||
return 256 + NUM_LENGTH_CODES +
|
||||
((p->palette_code_bits_ > 0) ? (1 << p->palette_code_bits_) : 0);
|
||||
|
@ -12,7 +12,8 @@
|
||||
#include <assert.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"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
|
@ -27,8 +27,8 @@ extern "C" {
|
||||
|
||||
// version numbers
|
||||
#define ENC_MAJ_VERSION 0
|
||||
#define ENC_MIN_VERSION 2
|
||||
#define ENC_REV_VERSION 1
|
||||
#define ENC_MIN_VERSION 3
|
||||
#define ENC_REV_VERSION 0
|
||||
|
||||
// intra prediction modes
|
||||
enum { B_DC_PRED = 0, // 4x4 modes
|
||||
@ -55,8 +55,9 @@ enum { NUM_MB_SEGMENTS = 4,
|
||||
NUM_BANDS = 8,
|
||||
NUM_CTX = 3,
|
||||
NUM_PROBAS = 11,
|
||||
MAX_LF_LEVELS = 64, // Maximum loop filter level
|
||||
MAX_VARIABLE_LEVEL = 67 // last (inclusive) level with variable cost
|
||||
MAX_LF_LEVELS = 64, // Maximum loop filter level
|
||||
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
|
||||
|
@ -563,6 +563,9 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
||||
!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
|
||||
goto Error;
|
||||
}
|
||||
// Free combined histograms.
|
||||
free(histogram_image);
|
||||
histogram_image = NULL;
|
||||
|
||||
// Color Cache parameters.
|
||||
VP8LWriteBits(bw, 1, use_color_cache);
|
||||
@ -609,9 +612,6 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
||||
ClearHuffmanTreeIfOnlyOneSymbol(codes);
|
||||
}
|
||||
}
|
||||
// Free combined histograms.
|
||||
free(histogram_image);
|
||||
histogram_image = NULL;
|
||||
|
||||
// Store actual literals.
|
||||
StoreImageToBitMask(bw, width, histogram_bits, &refs,
|
||||
@ -619,7 +619,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
||||
ok = 1;
|
||||
|
||||
Error:
|
||||
if (!ok) free(histogram_image);
|
||||
free(histogram_image);
|
||||
|
||||
VP8LClearBackwardRefs(&refs);
|
||||
if (huffman_codes != NULL) {
|
||||
|
@ -8,4 +8,4 @@ Description: Library for the WebP graphics format
|
||||
Version: @PACKAGE_VERSION@
|
||||
Cflags: -I${includedir}
|
||||
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@
|
||||
Cflags: -I${includedir}
|
||||
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 += ../webp/mux.h
|
||||
libwebpmuxinclude_HEADERS += ../webp/mux_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
|
||||
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))) {
|
||||
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) {
|
||||
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'.
|
||||
// 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);
|
||||
|
||||
// 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.
|
||||
static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
|
||||
while (chunk && chunk->tag_ != tag) {
|
||||
while (chunk != NULL && chunk->tag_ != tag) {
|
||||
chunk = chunk->next_;
|
||||
}
|
||||
return chunk;
|
||||
@ -105,7 +105,7 @@ static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
|
||||
WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
|
||||
uint32_t iter = nth;
|
||||
first = ChunkSearchNextInList(first, tag);
|
||||
if (!first) return NULL;
|
||||
if (first == NULL) return NULL;
|
||||
|
||||
while (--iter != 0) {
|
||||
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,
|
||||
WebPChunk*** const location) {
|
||||
uint32_t count = 0;
|
||||
assert(chunk_list);
|
||||
assert(chunk_list != NULL);
|
||||
*location = chunk_list;
|
||||
|
||||
while (*chunk_list) {
|
||||
while (*chunk_list != NULL) {
|
||||
WebPChunk* const cur_chunk = *chunk_list;
|
||||
++count;
|
||||
if (count == nth) return 1; // Found.
|
||||
@ -149,27 +149,18 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
|
||||
ChunkRelease(chunk);
|
||||
|
||||
if (data != NULL) {
|
||||
if (copy_data) {
|
||||
// Copy data.
|
||||
chunk->data_.bytes = (uint8_t*)malloc(data->size);
|
||||
if (chunk->data_.bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
|
||||
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.
|
||||
if (copy_data) { // Copy data.
|
||||
if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR;
|
||||
chunk->owner_ = 1; // Chunk is owner of data.
|
||||
} else { // Don't copy data.
|
||||
chunk->data_ = *data;
|
||||
}
|
||||
}
|
||||
|
||||
chunk->tag_ = tag;
|
||||
|
||||
return WEBP_MUX_OK;
|
||||
}
|
||||
|
||||
WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
|
||||
WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
|
||||
uint32_t nth) {
|
||||
WebPChunk* new_chunk;
|
||||
|
||||
@ -180,6 +171,7 @@ WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
|
||||
new_chunk = (WebPChunk*)malloc(sizeof(*new_chunk));
|
||||
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
|
||||
*new_chunk = *chunk;
|
||||
chunk->owner_ = 0;
|
||||
new_chunk->next_ = *chunk_list;
|
||||
*chunk_list = new_chunk;
|
||||
return WEBP_MUX_OK;
|
||||
@ -199,7 +191,7 @@ WebPChunk* ChunkDelete(WebPChunk* const chunk) {
|
||||
|
||||
size_t ChunksListDiskSize(const WebPChunk* chunk_list) {
|
||||
size_t size = 0;
|
||||
while (chunk_list) {
|
||||
while (chunk_list != NULL) {
|
||||
size += ChunkDiskSize(chunk_list);
|
||||
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) {
|
||||
while (chunk_list) {
|
||||
while (chunk_list != NULL) {
|
||||
dst = ChunkEmit(chunk_list, dst);
|
||||
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.
|
||||
}
|
||||
|
||||
while (*wpi_list) {
|
||||
while (*wpi_list != NULL) {
|
||||
WebPMuxImage* const cur_wpi = *wpi_list;
|
||||
++count;
|
||||
if (count == nth) return 1; // Found.
|
||||
@ -327,7 +319,7 @@ WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) {
|
||||
}
|
||||
|
||||
void MuxImageDeleteAll(WebPMuxImage** const wpi_list) {
|
||||
while (*wpi_list) {
|
||||
while (*wpi_list != NULL) {
|
||||
*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 size = 0;
|
||||
while (wpi_list) {
|
||||
while (wpi_list != NULL) {
|
||||
size += MuxImageDiskSize(wpi_list);
|
||||
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) {
|
||||
while (wpi_list) {
|
||||
while (wpi_list != NULL) {
|
||||
dst = MuxImageEmit(wpi_list, dst);
|
||||
wpi_list = wpi_list->next_;
|
||||
}
|
||||
|
@ -223,7 +223,9 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
||||
MuxImageInit(wpi); // Reset for reading next image.
|
||||
break;
|
||||
case WEBP_CHUNK_ANMF:
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
case WEBP_CHUNK_FRGM:
|
||||
#endif
|
||||
if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete.
|
||||
if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err;
|
||||
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 CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM;
|
||||
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().
|
||||
// Get frame/fragment chunk.
|
||||
frame_frgm_data = &wpi->header_->data_;
|
||||
|
@ -5,7 +5,10 @@ if BUILD_LIBWEBPDECODER
|
||||
noinst_LTLIBRARIES += libwebputilsdecode.la
|
||||
endif
|
||||
|
||||
COMMON_SOURCES =
|
||||
common_HEADERS = ../webp/types.h
|
||||
commondir = $(includedir)/webp
|
||||
|
||||
COMMON_SOURCES =
|
||||
COMMON_SOURCES += bit_reader.c
|
||||
COMMON_SOURCES += bit_reader.h
|
||||
COMMON_SOURCES += color_cache.c
|
||||
@ -23,7 +26,7 @@ COMMON_SOURCES += thread.h
|
||||
COMMON_SOURCES += utils.c
|
||||
COMMON_SOURCES += utils.h
|
||||
|
||||
ENC_SOURCES =
|
||||
ENC_SOURCES =
|
||||
ENC_SOURCES += bit_writer.c
|
||||
ENC_SOURCES += bit_writer.h
|
||||
ENC_SOURCES += huffman_encode.c
|
||||
@ -31,15 +34,8 @@ ENC_SOURCES += huffman_encode.h
|
||||
ENC_SOURCES += quant_levels.c
|
||||
ENC_SOURCES += quant_levels.h
|
||||
|
||||
|
||||
libwebputils_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES)
|
||||
|
||||
libwebputilsinclude_HEADERS = ../webp/types.h
|
||||
libwebputilsincludedir = $(includedir)/webp
|
||||
|
||||
if BUILD_LIBWEBPDECODER
|
||||
libwebputilsdecode_la_SOURCES = $(COMMON_SOURCES)
|
||||
|
||||
libwebputilsdecodeinclude_HEADERS = $(libwebputilsinclude_HEADERS)
|
||||
libwebputilsdecodeincludedir = $(libwebputilsincludedir)
|
||||
endif
|
||||
|
@ -59,7 +59,7 @@ extern "C" {
|
||||
// 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.
|
||||
|
||||
#if !defined(WEBP_REFERENCE_IMPLEMENTATION)
|
||||
@ -68,7 +68,9 @@ extern "C" {
|
||||
|
||||
#if defined(__i386__) || defined(_M_IX86) // x86 32bit
|
||||
#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
|
||||
#else // reasonable default
|
||||
#define BITS 24
|
||||
@ -84,9 +86,15 @@ extern "C" {
|
||||
//------------------------------------------------------------------------------
|
||||
// Derived types and constants
|
||||
|
||||
#if (BITS == 32)
|
||||
typedef uint64_t bit_t; // natural register type
|
||||
typedef uint32_t lbit_t; // natural type for memory I/O
|
||||
// bit_t = natural register type
|
||||
// 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)
|
||||
typedef uint32_t bit_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_;
|
||||
br->buf_ += (BITS) >> 3;
|
||||
#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__)
|
||||
__asm__ volatile("bswap %k0" : "=r"(in_bits) : "0"(in_bits));
|
||||
bits = (bit_t)in_bits; // 24b/32b -> 32b/64b zero-extension
|
||||
#elif defined(_MSC_VER)
|
||||
bits = _byteswap_ulong(in_bits);
|
||||
bits = (bit_t)_byteswap_ulong(in_bits);
|
||||
#else
|
||||
bits = (bit_t)(in_bits >> 24) | ((in_bits >> 8) & 0xff00)
|
||||
| ((in_bits << 8) & 0xff0000) | (in_bits << 24);
|
||||
#endif // x86
|
||||
#if (BITS == 24)
|
||||
bits >>= 8;
|
||||
#endif
|
||||
bits >>= (32 - BITS);
|
||||
#elif (BITS == 16)
|
||||
// gcc will recognize a 'rorw $8, ...' here:
|
||||
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) {
|
||||
const bit_t split = (br->range_ >> 1);
|
||||
const range_t split = (br->range_ >> 1);
|
||||
const int bit = VP8BitUpdate(br, split);
|
||||
VP8Shift(br);
|
||||
return bit ? -v : v;
|
||||
|
@ -26,8 +26,7 @@ extern "C" {
|
||||
assert(out != NULL); \
|
||||
assert(width > 0); \
|
||||
assert(height > 0); \
|
||||
assert(bpp > 0); \
|
||||
assert(stride >= width * bpp);
|
||||
assert(stride >= width);
|
||||
|
||||
static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred,
|
||||
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.
|
||||
|
||||
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;
|
||||
const uint8_t* preds = (inverse ? out : in);
|
||||
SANITY_CHECK(in, out);
|
||||
@ -52,11 +52,11 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in,
|
||||
for (h = 0; h < height; ++h) {
|
||||
// Leftmost pixel is predicted from above (except for topmost scanline).
|
||||
if (h == 0) {
|
||||
memcpy((void*)out, (const void*)in, bpp);
|
||||
out[0] = in[0];
|
||||
} 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;
|
||||
in += 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,
|
||||
int bpp, int stride, uint8_t* filtered_data) {
|
||||
DoHorizontalFilter(data, width, height, bpp, stride, 0, filtered_data);
|
||||
int stride, uint8_t* filtered_data) {
|
||||
DoHorizontalFilter(data, width, height, stride, 0, filtered_data);
|
||||
}
|
||||
|
||||
static void HorizontalUnfilter(const uint8_t* data, int width, int height,
|
||||
int bpp, int stride, uint8_t* recon_data) {
|
||||
DoHorizontalFilter(data, width, height, bpp, stride, 1, recon_data);
|
||||
static void HorizontalUnfilter(int width, int height, int stride,
|
||||
uint8_t* data) {
|
||||
DoHorizontalFilter(data, width, height, stride, 1, data);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Vertical filter.
|
||||
|
||||
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;
|
||||
const uint8_t* preds = (inverse ? out : in);
|
||||
SANITY_CHECK(in, out);
|
||||
|
||||
// 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.
|
||||
PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
|
||||
PredictLine(in + 1, preds, out + 1, width - 1, inverse);
|
||||
|
||||
// Filter line-by-line.
|
||||
for (h = 1; h < height; ++h) {
|
||||
in += stride;
|
||||
out += stride;
|
||||
PredictLine(in, preds, out, bpp * width, inverse);
|
||||
PredictLine(in, preds, out, width, inverse);
|
||||
preds += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void VerticalFilter(const uint8_t* data, int width, int height,
|
||||
int bpp, int stride, uint8_t* filtered_data) {
|
||||
DoVerticalFilter(data, width, height, bpp, stride, 0, filtered_data);
|
||||
int stride, uint8_t* filtered_data) {
|
||||
DoVerticalFilter(data, width, height, stride, 0, filtered_data);
|
||||
}
|
||||
|
||||
static void VerticalUnfilter(const uint8_t* data, int width, int height,
|
||||
int bpp, int stride, uint8_t* recon_data) {
|
||||
DoVerticalFilter(data, width, height, bpp, stride, 1, recon_data);
|
||||
static void VerticalUnfilter(int width, int height, int stride, uint8_t* data) {
|
||||
DoVerticalFilter(data, width, height, stride, 1, 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) {
|
||||
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
|
||||
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);
|
||||
int h;
|
||||
SANITY_CHECK(in, out);
|
||||
|
||||
// left prediction for top scan-line
|
||||
memcpy((void*)out, (const void*)in, bpp);
|
||||
PredictLine(in + bpp, preds, out + bpp, bpp * (width - 1), inverse);
|
||||
out[0] = in[0];
|
||||
PredictLine(in + 1, preds, out + 1, width - 1, inverse);
|
||||
|
||||
// Filter line-by-line.
|
||||
for (h = 1; h < height; ++h) {
|
||||
@ -132,24 +132,23 @@ void DoGradientFilter(const uint8_t* in, int width, int height,
|
||||
in += stride;
|
||||
out += stride;
|
||||
// leftmost pixel: predict from above.
|
||||
PredictLine(in, preds - stride, out, bpp, inverse);
|
||||
for (w = bpp; w < width * bpp; ++w) {
|
||||
const int pred = GradientPredictor(preds[w - bpp],
|
||||
PredictLine(in, preds - stride, out, 1, inverse);
|
||||
for (w = 1; w < width; ++w) {
|
||||
const int pred = GradientPredictor(preds[w - 1],
|
||||
preds[w - stride],
|
||||
preds[w - stride - bpp]);
|
||||
preds[w - stride - 1]);
|
||||
out[w] = in[w] + (inverse ? pred : -pred);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GradientFilter(const uint8_t* data, int width, int height,
|
||||
int bpp, int stride, uint8_t* filtered_data) {
|
||||
DoGradientFilter(data, width, height, bpp, stride, 0, filtered_data);
|
||||
int stride, uint8_t* filtered_data) {
|
||||
DoGradientFilter(data, width, height, stride, 0, filtered_data);
|
||||
}
|
||||
|
||||
static void GradientUnfilter(const uint8_t* data, int width, int height,
|
||||
int bpp, int stride, uint8_t* recon_data) {
|
||||
DoGradientFilter(data, width, height, bpp, stride, 1, recon_data);
|
||||
static void GradientUnfilter(int width, int height, int stride, uint8_t* data) {
|
||||
DoGradientFilter(data, width, height, stride, 1, data);
|
||||
}
|
||||
|
||||
#undef SANITY_CHECK
|
||||
@ -215,7 +214,7 @@ const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST] = {
|
||||
GradientFilter // WEBP_FILTER_GRADIENT
|
||||
};
|
||||
|
||||
const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST] = {
|
||||
const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST] = {
|
||||
NULL, // WEBP_FILTER_NONE
|
||||
HorizontalUnfilter, // WEBP_FILTER_HORIZONTAL
|
||||
VerticalUnfilter, // WEBP_FILTER_VERTICAL
|
||||
|
@ -30,18 +30,19 @@ typedef enum {
|
||||
} WEBP_FILTER_TYPE;
|
||||
|
||||
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.
|
||||
// 'in' corresponds to a 2-dimensional pixel array of size (stride * height)
|
||||
// in raster order.
|
||||
// 'bpp' is number of bytes per pixel, and
|
||||
// 'stride' is number of bytes per scan line (with possible padding).
|
||||
// 'out' should be pre-allocated.
|
||||
extern const WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
|
||||
|
||||
// Reconstruct the original data from the given filtered data.
|
||||
extern const WebPFilterFunc WebPUnfilters[WEBP_FILTER_LAST];
|
||||
// In-place reconstruct the original data from the given filtered data.
|
||||
extern const WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST];
|
||||
|
||||
// Fast estimate of a potentially good filter.
|
||||
extern WEBP_FILTER_TYPE EstimateBestFilter(const uint8_t* data,
|
||||
|
@ -18,7 +18,7 @@
|
||||
extern "C" {
|
||||
#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 WebPYUVABuffer WebPYUVABuffer;
|
||||
@ -392,9 +392,10 @@ WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea(
|
||||
|
||||
// Features gathered from the bitstream
|
||||
struct WebPBitstreamFeatures {
|
||||
int width; // Width 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 width; // Width 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_animation; // True if the bitstream is an animation.
|
||||
|
||||
// Unused for now:
|
||||
int bitstream_version; // should be 0 for now. TODO(later)
|
||||
@ -402,7 +403,7 @@ struct WebPBitstreamFeatures {
|
||||
// recommended.
|
||||
int rotate; // 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
|
||||
|
@ -45,7 +45,6 @@
|
||||
#ifndef WEBP_WEBP_DEMUX_H_
|
||||
#define WEBP_WEBP_DEMUX_H_
|
||||
|
||||
#include "./format_constants.h"
|
||||
#include "./mux_types.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
@ -81,14 +80,13 @@ enum WebPDemuxState {
|
||||
WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(
|
||||
const WebPData*, int, WebPDemuxState*, int);
|
||||
|
||||
// Parses the WebP file given by 'data'.
|
||||
// A complete WebP file must be present in 'data' for the function to succeed.
|
||||
// Parses the full WebP file given by 'data'.
|
||||
// Returns a WebPDemuxer object on successful parse, NULL otherwise.
|
||||
static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
|
||||
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.
|
||||
// Returns a WebPDemuxer object on successful parse, NULL otherwise.
|
||||
static WEBP_INLINE WebPDemuxer* WebPDemuxPartial(
|
||||
|
@ -12,6 +12,9 @@
|
||||
#ifndef 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.
|
||||
#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data.
|
||||
#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 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_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
|
||||
#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
|
||||
|
@ -45,7 +45,6 @@
|
||||
#ifndef WEBP_WEBP_MUX_H_
|
||||
#define WEBP_WEBP_MUX_H_
|
||||
|
||||
#include "./format_constants.h"
|
||||
#include "./mux_types.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
|
@ -5,7 +5,7 @@
|
||||
// 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)
|
||||
|
||||
@ -20,14 +20,23 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// 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)
|
||||
#if !(defined(__cplusplus) || defined(c_plusplus))
|
||||
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
|
||||
// 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 {
|
||||
WEBP_MUX_DISPOSE_NONE, // Do not dispose.
|
||||
WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color.
|
||||
|
Loading…
Reference in New Issue
Block a user