mirror of
https://github.com/webmproject/libwebp.git
synced 2025-07-13 14:34:33 +02:00
Compare commits
608 Commits
1.2.2
...
webp-rfc96
Author | SHA1 | Date | |
---|---|---|---|
dfdcb7f95c | |||
78ed683978 | |||
d516a68e54 | |||
874069042e | |||
fdb229ea3a | |||
0c3cd9cc2c | |||
169dfbf931 | |||
2dd5eb9862 | |||
23bbafbeb8 | |||
35915b389e | |||
a32b436bd5 | |||
04d4b4f387 | |||
b1cb37e659 | |||
201894ef24 | |||
02eac8a741 | |||
84b118c9c3 | |||
052cf42f1a | |||
220ee52967 | |||
7861947813 | |||
14f09ab75b | |||
a78c5356ba | |||
bc49176355 | |||
34f9223829 | |||
367ca938f1 | |||
a582b53b74 | |||
0fd25d8406 | |||
f888291359 | |||
40e4ca60ea | |||
57883c78ed | |||
1c8eba978b | |||
2e81017c7a | |||
94de6c7fed | |||
51d9832a36 | |||
7bcb36b884 | |||
8e0cc14c3e | |||
cea684626d | |||
615e58744f | |||
233e86b91f | |||
1a29fd2fc3 | |||
dd9d3770d7 | |||
ab451a495c | |||
f9a480f7c3 | |||
04834acae7 | |||
39a602afe6 | |||
f28c837dc1 | |||
74be8e22d9 | |||
0c01db7c3c | |||
f2d6dc1eef | |||
caa19e5b3a | |||
c9dd9bd40b | |||
8a7c8dc662 | |||
f0c53cd966 | |||
eef903d04a | |||
6296cc8d0d | |||
fbd93896a6 | |||
cc7ff5459a | |||
4e2828bae8 | |||
d742b24a88 | |||
c7bb4cb585 | |||
952a989b1b | |||
dde11574b0 | |||
a1ca153d51 | |||
3bd9420289 | |||
d27d246e42 | |||
4838611f91 | |||
314a142a34 | |||
3bfb05e38c | |||
baa93808d9 | |||
41a5e582c2 | |||
fb444b692b | |||
c1c89f5189 | |||
66408c2c7c | |||
ac1e410ded | |||
b78d39571f | |||
cff21a7d87 | |||
6853a8e5ac | |||
9bc09db4b8 | |||
0a9f1c19f8 | |||
db0cb9c27e | |||
ff2b5b15ae | |||
c4af79d053 | |||
0ec80aef3d | |||
96d79f8481 | |||
c35c7e0240 | |||
f2fe8decce | |||
9ce982fdf2 | |||
3ba8af1a33 | |||
ea0e121b6a | |||
27731afd47 | |||
ddd6245eb7 | |||
50074930e3 | |||
20e92f7d40 | |||
4f200de591 | |||
64186bb36c | |||
0905f61c85 | |||
e86787586b | |||
5e5b8f0c95 | |||
45129ee027 | |||
ee26766a89 | |||
7ec51c5916 | |||
3cd16fd3e2 | |||
971a03d820 | |||
1bf198a22b | |||
1e462ca80e | |||
64d1ec23ac | |||
a90160e11a | |||
a7aa7525b8 | |||
68ff4e1efe | |||
79e7968ad0 | |||
d33455cd31 | |||
a67ff735a2 | |||
edc289092a | |||
3cada4cef4 | |||
dc9505855e | |||
845d5476a8 | |||
8a6a55bba8 | |||
cf7c5a5de8 | |||
cc34288aa3 | |||
f13c08868a | |||
7455595072 | |||
d781646c29 | |||
c2e394de91 | |||
f6d15cb747 | |||
57c388b8ff | |||
b3d1b2cbf7 | |||
07216886a7 | |||
f88666eb47 | |||
e2c8f233ef | |||
d537cd3704 | |||
6c484cbf92 | |||
7b0bc2352b | |||
3c0011bbd1 | |||
955a3d14ae | |||
00abc0007c | |||
40e85a0b56 | |||
1bf46358c4 | |||
eba03acb05 | |||
a16d30cb57 | |||
8a7e911231 | |||
7fac6c1bf2 | |||
e2922e4390 | |||
501d9274a7 | |||
fba7d62ee5 | |||
661c1b6641 | |||
8487860a8c | |||
8ea678b990 | |||
79e05c7f9f | |||
45f995a37e | |||
1fb9f3dcf1 | |||
4723db65bc | |||
f4b9bc9ea1 | |||
713982b883 | |||
cbe825e4cc | |||
f99305e9e5 | |||
5efd6300dc | |||
e78e924f84 | |||
d7a0506dcc | |||
89c5b91746 | |||
34c8074915 | |||
13d9c30b2b | |||
24d7f9cb6e | |||
0b56dedc98 | |||
a429c0de64 | |||
f0cd786125 | |||
339231cc37 | |||
307071f144 | |||
deadc339d5 | |||
e7b78d4375 | |||
15a1309efc | |||
54ca975245 | |||
d2cb2d8cfc | |||
e9d5010718 | |||
786579711f | |||
e30a588456 | |||
09ca136801 | |||
38cb4fc0ea | |||
40afa9269b | |||
9db21143d0 | |||
cdbf88aed2 | |||
05c469843c | |||
8534f53960 | |||
35e197bdb7 | |||
61441425fe | |||
dce8397fec | |||
57c58105f3 | |||
c1ffd9ac75 | |||
a3965948e0 | |||
f80e9b7e4c | |||
accd141da3 | |||
ac17ffffcb | |||
433c7dca11 | |||
5fac76cf8d | |||
ca332209cb | |||
1ace578c91 | |||
63234c4296 | |||
a35ea50de4 | |||
95ea5226c8 | |||
2af26267cd | |||
902bc91903 | |||
7ba44f80f3 | |||
68e271354e | |||
943b932a7e | |||
1cc94f9521 | |||
63acdd1e06 | |||
aac5c5d0df | |||
a2de25f6b6 | |||
68820f0e53 | |||
cdb31aa806 | |||
0535a8cf88 | |||
b6c4ce2635 | |||
dd7364c3ce | |||
c63c5df618 | |||
0a2cad5115 | |||
dd88d2ff3e | |||
6e75054736 | |||
67a7cc2b07 | |||
1432ebbadb | |||
cd436142f6 | |||
3cb66f64b0 | |||
56471a53cf | |||
af7fbfd2d9 | |||
7d8e0896e9 | |||
a71ce1cf74 | |||
e94b36d66d | |||
84628e5611 | |||
ee72299796 | |||
0081693d61 | |||
0fcb311cfc | |||
982c177c8a | |||
56cf562570 | |||
6c6b3fd317 | |||
29b9eb1517 | |||
47c0af8daf | |||
b92deba353 | |||
6be9bf8bae | |||
5c965e55dd | |||
e4fc2f78c7 | |||
71916726b6 | |||
eac3bd5c53 | |||
e2c85878f6 | |||
4222b00679 | |||
25d94f473b | |||
2153a6797c | |||
4298e9765c | |||
cd7e02bece | |||
6c3845f9e0 | |||
7f1b6799db | |||
7b634d8f0c | |||
6d6d4915ce | |||
fd7bb21c0c | |||
e1adea50ed | |||
6b1c722a5b | |||
08d60d6006 | |||
7a12afcc54 | |||
4339332038 | |||
287fdefe95 | |||
c3bd7cff2e | |||
14a9dbfba0 | |||
64819c7cf3 | |||
d49cfbb348 | |||
2e5a9ec3b6 | |||
ebb6f949f4 | |||
59a2b1f9e3 | |||
8e965ccb0f | |||
fe80fbbd6b | |||
e8ed317609 | |||
03a7a04892 | |||
c437c7aace | |||
e4f17a31a7 | |||
e2ecd5e937 | |||
8b55425a56 | |||
29c9f2d410 | |||
6b02f66015 | |||
7f75c91ced | |||
f6499943c4 | |||
49918af32b | |||
7f0a341943 | |||
bab7efbe73 | |||
7138bf8fc3 | |||
435b4ded42 | |||
473512298a | |||
46bc4fc9d9 | |||
828b4ce062 | |||
ff6c7f4e71 | |||
dd530437f6 | |||
adbe2cb17e | |||
15b365083d | |||
c369c4bf0b | |||
1de35f476b | |||
bb06a16ed1 | |||
9f38b71e01 | |||
7acb6b829a | |||
4967e7cd78 | |||
e3366659a0 | |||
428588ef90 | |||
709ec152df | |||
8dd80ef814 | |||
8f187b9f7f | |||
cba300781f | |||
6cf9a76ae2 | |||
740943b276 | |||
2d547e24dc | |||
ac42dde1c5 | |||
17e0ef1da5 | |||
ed27437160 | |||
3fb8294762 | |||
0c496a4ff9 | |||
8151f388eb | |||
916548c28c | |||
4070b271ab | |||
761f49c3ab | |||
84d04c4845 | |||
0696e1a7fb | |||
93d88aa25b | |||
118e0035df | |||
4c3d7018c0 | |||
a6a09b3296 | |||
50ac4f7c97 | |||
4b7d7b4f2b | |||
0afbd97b45 | |||
349f4353dd | |||
8f7513b7c0 | |||
cbf624b561 | |||
89edfdd1e9 | |||
859f19f74f | |||
a4f0483579 | |||
1275fac820 | |||
2fe27bb96d | |||
24bed3d9fb | |||
0825faa4c1 | |||
d64e6d7d9d | |||
0e12a22d88 | |||
0edbb6ea71 | |||
41ffe04e12 | |||
2d9d9265f5 | |||
a486d800b6 | |||
1347a32d82 | |||
52b6f06703 | |||
7361842839 | |||
b54d21a01d | |||
31c28db53c | |||
d9a505ffb6 | |||
bdf33d03b0 | |||
b557776962 | |||
0ba772442e | |||
e763eb1ea3 | |||
2a8686fcab | |||
106a57c1db | |||
c5e841c417 | |||
dbc3071512 | |||
6fc1a9f96e | |||
d3e151fc03 | |||
ed92a62649 | |||
6eb0189b24 | |||
1d58575b18 | |||
e5fe2cfc1b | |||
0ceeeab987 | |||
607611cd86 | |||
f853685e13 | |||
786497e48a | |||
c6ac672dbc | |||
b5700efb70 | |||
d8ed8c117c | |||
52ec0b8f61 | |||
5097ef6255 | |||
e3ba2b1f5b | |||
1e8e3ded21 | |||
017cb6fa94 | |||
f6a4684ba8 | |||
54ebd5a375 | |||
44741f9c58 | |||
fad0ece7ed | |||
3f73e8f7ac | |||
ce2f2d668e | |||
a458e3086c | |||
9ba800a745 | |||
979c0ebbcd | |||
8bab09a4a8 | |||
769387c54a | |||
a02978c250 | |||
28aedcb9b0 | |||
c42e6d5a89 | |||
dfc843aa63 | |||
2498209ba9 | |||
ac252b6118 | |||
5694476244 | |||
d34f9b99b9 | |||
dc05b4db2a | |||
83270c7f89 | |||
73b19b64fd | |||
57101d3fc5 | |||
dfd32e4592 | |||
8a6185dd27 | |||
72776530d8 | |||
d992bb08b7 | |||
3ed2b27517 | |||
951c292d12 | |||
902dd78762 | |||
a8f6b5ee94 | |||
1dc594352f | |||
280a810f2a | |||
41f0bf680b | |||
6bdd36dbe7 | |||
87e36c485a | |||
5b01f32162 | |||
19b1a71c48 | |||
780db75618 | |||
e407d4b37c | |||
abf73d628e | |||
25807fb4cb | |||
5dbc4bfa1b | |||
b2a175dd04 | |||
cb90f76b68 | |||
02d1525869 | |||
5ba046e25f | |||
e68765af42 | |||
e8f83de286 | |||
15a91ab179 | |||
0dd49d1a3a | |||
62b1bfe8bd | |||
95c8fe5f3d | |||
e7c805cfad | |||
6af8845a8f | |||
639619ce72 | |||
782ed48cd3 | |||
cad0d5adb6 | |||
ef70ee06fa | |||
f0f9eda406 | |||
9b902cbace | |||
9c1d457c01 | |||
9ac25bcb39 | |||
76c353bab7 | |||
5000de5435 | |||
e17293095b | |||
00ff988a59 | |||
e2fecc22e1 | |||
129cf9e97e | |||
ad7d1753c5 | |||
5037220e55 | |||
2ee786c740 | |||
4cc157d48a | |||
892cf033b9 | |||
3a9a4d4589 | |||
704a3d0a1f | |||
1a6c109c99 | |||
c626e7d544 | |||
866e349cef | |||
c170df3830 | |||
9d7ff74a55 | |||
0d1f12546b | |||
fcbc2d78ab | |||
4ad0e1895e | |||
980d24884c | |||
9fde812779 | |||
7a0a9935ed | |||
c040a615b1 | |||
aff1c546ef | |||
ab540ae0c5 | |||
8980362eed | |||
e626925cef | |||
835392393b | |||
8a4576ce26 | |||
db87088162 | |||
01d7d378d1 | |||
337cf69f58 | |||
79be856e6e | |||
5b87983ad0 | |||
bd9391232d | |||
04764b56a0 | |||
7deee8103e | |||
1a64a7e649 | |||
bec2c88a11 | |||
c9359332a3 | |||
70fe3063a5 | |||
ddbf3f3f2a | |||
c151e95bdc | |||
748e92bbb9 | |||
3fe15b6773 | |||
4f402f34a1 | |||
a3b68c195e | |||
b4994eaa6d | |||
94cd711779 | |||
e91451b69b | |||
231bdfb762 | |||
bfad7ab589 | |||
c2e3fd30c4 | |||
7366f7f394 | |||
84163d9d02 | |||
d01c1eb309 | |||
8813ca8e69 | |||
3c4a0fbfbc | |||
56a480e80c | |||
62b45bddcd | |||
8764ec7a07 | |||
bcb872c31f | |||
67c44ac5db | |||
8278825aac | |||
14a49e018d | |||
34b1dc336d | |||
0b397fda9d | |||
c16488ac4a | |||
5a2d929cd8 | |||
169f867f3c | |||
a94b855c54 | |||
f83bdb5251 | |||
bef0d79764 | |||
404c1622f8 | |||
8895f8a345 | |||
92a673d258 | |||
67c1d72239 | |||
1124ff662d | |||
e15b356014 | |||
ec9e782a35 | |||
7bd07f3b5d | |||
5ecee06f7a | |||
f81dd7d63e | |||
2d607ee646 | |||
266cbbc511 | |||
9fc12274ce | |||
7d18f40ac1 | |||
11309aa54c | |||
4bc762f729 | |||
0d1b9bc433 | |||
20ef48f05a | |||
93c5437115 | |||
53cf2b4997 | |||
d3006f4b96 | |||
ea967098a4 | |||
11bc8410bd | |||
30453ea4e6 | |||
6c43219a5f | |||
4f59fa7390 | |||
e74f8a62b2 | |||
5a709ec0d7 | |||
a2093acc4b | |||
86c669303a | |||
232f22da5a | |||
44dd765def | |||
7a7e33e977 | |||
86f94ee010 | |||
a3927cc800 | |||
6c45cef7ff | |||
0c8b0e67a4 | |||
dc3841e077 | |||
a19a25bb03 | |||
42888f6c7c | |||
7efcf3cc26 | |||
8f4b5c62b7 | |||
90084d84f9 | |||
ed643f619d | |||
8fa053d134 | |||
99a8756201 | |||
deb426becc | |||
779597d443 | |||
40e8aa57f8 | |||
01a05de1a7 | |||
2de4b05a56 | |||
b8bca81fb6 | |||
e8e77b9c47 | |||
7e7d5d503a | |||
10c5084842 | |||
89f774e61d | |||
2d3293ad76 | |||
ec34fd7023 | |||
e471728754 | |||
e3cfafaf71 | |||
a828a59b49 | |||
fe153fae98 | |||
919acc0ef5 | |||
efa0731b9d | |||
0957fd69ee | |||
e685feef0c | |||
841960b670 | |||
617cf03656 | |||
7a68afaac5 | |||
34bb332ca1 | |||
f0e9351cce | |||
5ccbd6ed8c | |||
c3d0c2d7d8 | |||
d0d2292e1a | |||
03d1219055 | |||
d55d447c9a | |||
e4cbcdd2b5 | |||
924e7ca654 | |||
0fa0ea5488 | |||
29cc95ce4c | |||
a30f219016 | |||
66b3ce239e | |||
54e61a3864 | |||
b4533debd9 | |||
b9d2f9cd3b | |||
ec178f2c7f | |||
26139c7398 | |||
13b8281609 | |||
88b6a396f1 | |||
6f49654024 | |||
4074acf873 | |||
db25f1b4ed | |||
6e8a4126f2 | |||
faf219684c | |||
480cd51de6 | |||
1b0c15db02 | |||
17bade381a | |||
a80954a1d9 | |||
ec497b7532 | |||
e4886716d3 | |||
e3cb052ca5 | |||
a510fedb9a |
240
.cmake-format.py
Normal file
240
.cmake-format.py
Normal file
@ -0,0 +1,240 @@
|
||||
# ----------------------------------
|
||||
# Options affecting listfile parsing
|
||||
# ----------------------------------
|
||||
with section("parse"):
|
||||
|
||||
# Specify structure for custom cmake functions
|
||||
additional_commands = { 'foo': { 'flags': ['BAR', 'BAZ'],
|
||||
'kwargs': {'DEPENDS': '*', 'HEADERS': '*', 'SOURCES': '*'}}}
|
||||
|
||||
# Override configurations per-command where available
|
||||
override_spec = {}
|
||||
|
||||
# Specify variable tags.
|
||||
vartags = []
|
||||
|
||||
# Specify property tags.
|
||||
proptags = []
|
||||
|
||||
# -----------------------------
|
||||
# Options affecting formatting.
|
||||
# -----------------------------
|
||||
with section("format"):
|
||||
|
||||
# Disable formatting entirely, making cmake-format a no-op
|
||||
disable = False
|
||||
|
||||
# How wide to allow formatted cmake files
|
||||
line_width = 80
|
||||
|
||||
# How many spaces to tab for indent
|
||||
tab_size = 2
|
||||
|
||||
# If true, lines are indented using tab characters (utf-8 0x09) instead of
|
||||
# <tab_size> space characters (utf-8 0x20). In cases where the layout would
|
||||
# require a fractional tab character, the behavior of the fractional
|
||||
# indentation is governed by <fractional_tab_policy>
|
||||
use_tabchars = False
|
||||
|
||||
# If <use_tabchars> is True, then the value of this variable indicates how
|
||||
# fractional indentions are handled during whitespace replacement. If set to
|
||||
# 'use-space', fractional indentation is left as spaces (utf-8 0x20). If set
|
||||
# to `round-up` fractional indentation is replaced with a single tab character
|
||||
# (utf-8 0x09) effectively shifting the column to the next tabstop
|
||||
fractional_tab_policy = 'use-space'
|
||||
|
||||
# If an argument group contains more than this many sub-groups (parg or kwarg
|
||||
# groups) then force it to a vertical layout.
|
||||
max_subgroups_hwrap = 3
|
||||
|
||||
# If a positional argument group contains more than this many arguments, then
|
||||
# force it to a vertical layout.
|
||||
max_pargs_hwrap = 6
|
||||
|
||||
# If a cmdline positional group consumes more than this many lines without
|
||||
# nesting, then invalidate the layout (and nest)
|
||||
max_rows_cmdline = 2
|
||||
|
||||
# If true, separate flow control names from their parentheses with a space
|
||||
separate_ctrl_name_with_space = False
|
||||
|
||||
# If true, separate function names from parentheses with a space
|
||||
separate_fn_name_with_space = False
|
||||
|
||||
# If a statement is wrapped to more than one line, than dangle the closing
|
||||
# parenthesis on its own line.
|
||||
dangle_parens = False
|
||||
|
||||
# If the trailing parenthesis must be 'dangled' on its on line, then align it
|
||||
# to this reference: `prefix`: the start of the statement, `prefix-indent`:
|
||||
# the start of the statement, plus one indentation level, `child`: align to
|
||||
# the column of the arguments
|
||||
dangle_align = 'prefix'
|
||||
|
||||
# If the statement spelling length (including space and parenthesis) is
|
||||
# smaller than this amount, then force reject nested layouts.
|
||||
min_prefix_chars = 4
|
||||
|
||||
# If the statement spelling length (including space and parenthesis) is larger
|
||||
# than the tab width by more than this amount, then force reject un-nested
|
||||
# layouts.
|
||||
max_prefix_chars = 10
|
||||
|
||||
# If a candidate layout is wrapped horizontally but it exceeds this many
|
||||
# lines, then reject the layout.
|
||||
max_lines_hwrap = 2
|
||||
|
||||
# What style line endings to use in the output.
|
||||
line_ending = 'unix'
|
||||
|
||||
# Format command names consistently as 'lower' or 'upper' case
|
||||
command_case = 'canonical'
|
||||
|
||||
# Format keywords consistently as 'lower' or 'upper' case
|
||||
keyword_case = 'unchanged'
|
||||
|
||||
# A list of command names which should always be wrapped
|
||||
always_wrap = []
|
||||
|
||||
# If true, the argument lists which are known to be sortable will be sorted
|
||||
# lexicographicall
|
||||
enable_sort = True
|
||||
|
||||
# If true, the parsers may infer whether or not an argument list is sortable
|
||||
# (without annotation).
|
||||
autosort = False
|
||||
|
||||
# By default, if cmake-format cannot successfully fit everything into the
|
||||
# desired linewidth it will apply the last, most agressive attempt that it
|
||||
# made. If this flag is True, however, cmake-format will print error, exit
|
||||
# with non-zero status code, and write-out nothing
|
||||
require_valid_layout = False
|
||||
|
||||
# A dictionary mapping layout nodes to a list of wrap decisions. See the
|
||||
# documentation for more information.
|
||||
layout_passes = {}
|
||||
|
||||
# ------------------------------------------------
|
||||
# Options affecting comment reflow and formatting.
|
||||
# ------------------------------------------------
|
||||
with section("markup"):
|
||||
|
||||
# What character to use for bulleted lists
|
||||
bullet_char = '*'
|
||||
|
||||
# What character to use as punctuation after numerals in an enumerated list
|
||||
enum_char = '.'
|
||||
|
||||
# If comment markup is enabled, don't reflow the first comment block in each
|
||||
# listfile. Use this to preserve formatting of your copyright/license
|
||||
# statements.
|
||||
first_comment_is_literal = True
|
||||
|
||||
# If comment markup is enabled, don't reflow any comment block which matches
|
||||
# this (regex) pattern. Default is `None` (disabled).
|
||||
literal_comment_pattern = None
|
||||
|
||||
# Regular expression to match preformat fences in comments default=
|
||||
# ``r'^\s*([`~]{3}[`~]*)(.*)$'``
|
||||
fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$'
|
||||
|
||||
# Regular expression to match rulers in comments default=
|
||||
# ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'``
|
||||
ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$'
|
||||
|
||||
# If a comment line matches starts with this pattern then it is explicitly a
|
||||
# trailing comment for the preceeding argument. Default is '#<'
|
||||
explicit_trailing_pattern = '#<'
|
||||
|
||||
# If a comment line starts with at least this many consecutive hash
|
||||
# characters, then don't lstrip() them off. This allows for lazy hash rulers
|
||||
# where the first hash char is not separated by space
|
||||
hashruler_min_length = 10
|
||||
|
||||
# If true, then insert a space between the first hash char and remaining hash
|
||||
# chars in a hash ruler, and normalize its length to fill the column
|
||||
canonicalize_hashrulers = True
|
||||
|
||||
# enable comment markup parsing and reflow
|
||||
enable_markup = True
|
||||
|
||||
# ----------------------------
|
||||
# Options affecting the linter
|
||||
# ----------------------------
|
||||
with section("lint"):
|
||||
|
||||
# a list of lint codes to disable
|
||||
disabled_codes = []
|
||||
|
||||
# regular expression pattern describing valid function names
|
||||
function_pattern = '[0-9a-z_]+'
|
||||
|
||||
# regular expression pattern describing valid macro names
|
||||
macro_pattern = '[0-9A-Z_]+'
|
||||
|
||||
# regular expression pattern describing valid names for variables with global
|
||||
# (cache) scope
|
||||
global_var_pattern = '[A-Z][0-9A-Z_]+'
|
||||
|
||||
# regular expression pattern describing valid names for variables with global
|
||||
# scope (but internal semantic)
|
||||
internal_var_pattern = '_[A-Z][0-9A-Z_]+'
|
||||
|
||||
# regular expression pattern describing valid names for variables with local
|
||||
# scope
|
||||
local_var_pattern = '[a-z][a-z0-9_]+'
|
||||
|
||||
# regular expression pattern describing valid names for privatedirectory
|
||||
# variables
|
||||
private_var_pattern = '_[0-9a-z_]+'
|
||||
|
||||
# regular expression pattern describing valid names for public directory
|
||||
# variables
|
||||
public_var_pattern = '[A-Z][0-9A-Z_]+'
|
||||
|
||||
# regular expression pattern describing valid names for function/macro
|
||||
# arguments and loop variables.
|
||||
argument_var_pattern = '[a-z][a-z0-9_]+'
|
||||
|
||||
# regular expression pattern describing valid names for keywords used in
|
||||
# functions or macros
|
||||
keyword_pattern = '[A-Z][0-9A-Z_]+'
|
||||
|
||||
# In the heuristic for C0201, how many conditionals to match within a loop in
|
||||
# before considering the loop a parser.
|
||||
max_conditionals_custom_parser = 2
|
||||
|
||||
# Require at least this many newlines between statements
|
||||
min_statement_spacing = 1
|
||||
|
||||
# Require no more than this many newlines between statements
|
||||
max_statement_spacing = 2
|
||||
max_returns = 6
|
||||
max_branches = 12
|
||||
max_arguments = 5
|
||||
max_localvars = 15
|
||||
max_statements = 50
|
||||
|
||||
# -------------------------------
|
||||
# Options affecting file encoding
|
||||
# -------------------------------
|
||||
with section("encode"):
|
||||
|
||||
# If true, emit the unicode byte-order mark (BOM) at the start of the file
|
||||
emit_byteorder_mark = False
|
||||
|
||||
# Specify the encoding of the input file. Defaults to utf-8
|
||||
input_encoding = 'utf-8'
|
||||
|
||||
# Specify the encoding of the output file. Defaults to utf-8. Note that cmake
|
||||
# only claims to support utf-8 so be careful when using anything else
|
||||
output_encoding = 'utf-8'
|
||||
|
||||
# -------------------------------------
|
||||
# Miscellaneous configurations options.
|
||||
# -------------------------------------
|
||||
with section("misc"):
|
||||
|
||||
# A dictionary containing any per-command configuration overrides. Currently
|
||||
# only `command_case` is supported.
|
||||
per_command = {}
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,7 +3,9 @@
|
||||
*.pc
|
||||
.DS_Store
|
||||
.deps
|
||||
.idea
|
||||
.libs
|
||||
.vscode
|
||||
/aclocal.m4
|
||||
/ar-lib
|
||||
/autom4te.cache
|
||||
@ -50,5 +52,6 @@ tests/fuzzer/animdecoder_fuzzer
|
||||
tests/fuzzer/animencoder_fuzzer
|
||||
tests/fuzzer/demux_api_fuzzer
|
||||
tests/fuzzer/enc_dec_fuzzer
|
||||
tests/fuzzer/huffman_fuzzer
|
||||
tests/fuzzer/mux_demux_api_fuzzer
|
||||
tests/fuzzer/simple_api_fuzzer
|
||||
|
4
.mailmap
4
.mailmap
@ -8,8 +8,12 @@ Vikas Arora <vikasa@google.com>
|
||||
<vikasa@google.com> <vikaas.arora@gmail.com>
|
||||
<slobodan.prijic@imgtec.com> <Slobodan.Prijic@imgtec.com>
|
||||
<vrabaud@google.com> <vincent.rabaud@gmail.com>
|
||||
Vincent Rabaud <vrabaud@google.com>
|
||||
Tamar Levy <tamar.levy@intel.com>
|
||||
<qrczak@google.com> <qrczak>
|
||||
Hui Su <huisu@google.com>
|
||||
James Zern <jzern@google.com>
|
||||
Roberto Alanis <alanisbaez@google.com>
|
||||
Brian Ledger <brianpl@google.com>
|
||||
Maryla Ustarroz-Calonge <maryla@google.com>
|
||||
Yannis Guyon <yguyon@google.com>
|
||||
|
@ -1,2 +1,2 @@
|
||||
[style]
|
||||
based_on_style = chromium
|
||||
based_on_style = yapf
|
15
AUTHORS
15
AUTHORS
@ -1,19 +1,28 @@
|
||||
Contributors:
|
||||
- Aidan O'Loan (aidanol at gmail dot com)
|
||||
- Alan Browning (browning at google dot com)
|
||||
- Alexandru Ardelean (ardeleanalex at gmail dot com)
|
||||
- Anuraag Agrawal (anuraaga at gmail dot com)
|
||||
- Arthur Eubanks (aeubanks at google dot com)
|
||||
- Brian Ledger (brianpl at google dot com)
|
||||
- Charles Munger (clm at google dot com)
|
||||
- Cheng Yi (cyi at google dot com)
|
||||
- Christian Duvivier (cduvivier at google dot com)
|
||||
- Christopher Degawa (ccom at randomderp dot com)
|
||||
- Clement Courbet (courbet at google dot com)
|
||||
- Djordje Pesut (djordje dot pesut at imgtec dot com)
|
||||
- Frank Barchard (fbarchard at google dot com)
|
||||
- Hui Su (huisu at google dot com)
|
||||
- H. Vetinari (h dot vetinari at gmx dot com)
|
||||
- Ilya Kurdyukov (jpegqs at gmail dot com)
|
||||
- Ingvar Stepanyan (rreverser at google dot com)
|
||||
- James Zern (jzern at google dot com)
|
||||
- Jan Engelhardt (jengelh at medozas dot de)
|
||||
- Jehan (jehan at girinstud dot io)
|
||||
- Jeremy Maitin-Shepard (jbms at google dot com)
|
||||
- Johann Koenig (johann dot koenig at duck dot com)
|
||||
- Jonathan Grant (jgrantinfotech at gmail dot com)
|
||||
- Jonliu1993 (13720414433 at 163 dot com)
|
||||
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
|
||||
- Jyrki Alakuijala (jyrki at google dot com)
|
||||
- Konstantin Ivlev (tomskside at gmail dot com)
|
||||
@ -22,12 +31,17 @@ Contributors:
|
||||
- Mans Rullgard (mans at mansr dot com)
|
||||
- Marcin Kowalczyk (qrczak at google dot com)
|
||||
- Martin Olsson (mnemo at minimum dot se)
|
||||
- Maryla Ustarroz-Calonge (maryla at google dot com)
|
||||
- Masahiro Hanada (hanada at atmark-techno dot com)
|
||||
- Mikołaj Zalewski (mikolajz at google dot com)
|
||||
- Mislav Bradac (mislavm at google dot com)
|
||||
- natewood (natewood at fb dot com)
|
||||
- Nico Weber (thakis at chromium dot org)
|
||||
- Noel Chromium (noel at chromium dot org)
|
||||
- Nozomi Isozaki (nontan at pixiv dot co dot jp)
|
||||
- Oliver Wolff (oliver dot wolff at qt dot io)
|
||||
- Owen Rodley (orodley at google dot com)
|
||||
- Ozkan Sezer (sezeroz at gmail dot com)
|
||||
- Parag Salasakar (img dot mips1 at gmail dot com)
|
||||
- Pascal Massimino (pascal dot massimino at gmail dot com)
|
||||
- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org)
|
||||
@ -41,6 +55,7 @@ Contributors:
|
||||
- Somnath Banerjee (somnath dot banerjee at gmail dot com)
|
||||
- Sriraman Tallam (tmsriram at google dot com)
|
||||
- Tamar Levy (tamar dot levy at intel dot com)
|
||||
- Thiago Perrotta (tperrotta at google dot com)
|
||||
- Timothy Gu (timothygu99 at gmail dot com)
|
||||
- Urvang Joshi (urvang at google dot com)
|
||||
- Vikas Arora (vikasa at google dot com)
|
||||
|
16
Android.mk
16
Android.mk
@ -1,3 +1,5 @@
|
||||
# Ignore this file during non-NDK builds.
|
||||
ifdef NDK_ROOT
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
WEBP_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD
|
||||
@ -33,6 +35,15 @@ else
|
||||
NEON := c
|
||||
endif
|
||||
|
||||
sharpyuv_srcs := \
|
||||
sharpyuv/sharpyuv.c \
|
||||
sharpyuv/sharpyuv_cpu.c \
|
||||
sharpyuv/sharpyuv_csp.c \
|
||||
sharpyuv/sharpyuv_dsp.c \
|
||||
sharpyuv/sharpyuv_gamma.c \
|
||||
sharpyuv/sharpyuv_neon.$(NEON) \
|
||||
sharpyuv/sharpyuv_sse2.c \
|
||||
|
||||
dec_srcs := \
|
||||
src/dec/alpha_dec.c \
|
||||
src/dec/buffer_dec.c \
|
||||
@ -153,6 +164,7 @@ utils_dec_srcs := \
|
||||
src/utils/color_cache_utils.c \
|
||||
src/utils/filters_utils.c \
|
||||
src/utils/huffman_utils.c \
|
||||
src/utils/palette.c \
|
||||
src/utils/quant_levels_dec_utils.c \
|
||||
src/utils/random_utils.c \
|
||||
src/utils/rescaler_utils.c \
|
||||
@ -204,12 +216,13 @@ endif # ENABLE_SHARED=1
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
$(sharpyuv_srcs) \
|
||||
$(dsp_enc_srcs) \
|
||||
$(enc_srcs) \
|
||||
$(utils_enc_srcs) \
|
||||
|
||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
|
||||
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src $(LOCAL_PATH)
|
||||
|
||||
# prefer arm over thumb mode for performance gains
|
||||
LOCAL_ARM_MODE := arm
|
||||
@ -279,3 +292,4 @@ include $(WEBP_SRC_PATH)/examples/Android.mk
|
||||
ifeq ($(USE_CPUFEATURES),yes)
|
||||
$(call import-module,android/cpufeatures)
|
||||
endif
|
||||
endif # NDK_ROOT
|
||||
|
720
CMakeLists.txt
720
CMakeLists.txt
@ -6,7 +6,11 @@
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
cmake_minimum_required(VERSION 3.7)
|
||||
if(APPLE)
|
||||
cmake_minimum_required(VERSION 3.17)
|
||||
else()
|
||||
cmake_minimum_required(VERSION 3.7)
|
||||
endif()
|
||||
|
||||
if(POLICY CMP0072)
|
||||
cmake_policy(SET CMP0072 NEW)
|
||||
@ -15,6 +19,14 @@ endif()
|
||||
project(WebP C)
|
||||
|
||||
# Options for coder / decoder executables.
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(WEBP_LINK_STATIC_DEFAULT OFF)
|
||||
else()
|
||||
set(WEBP_LINK_STATIC_DEFAULT ON)
|
||||
endif()
|
||||
option(WEBP_LINK_STATIC
|
||||
"Link using static libraries. If OFF, use dynamic libraries."
|
||||
${WEBP_LINK_STATIC_DEFAULT})
|
||||
if(NOT EMSCRIPTEN)
|
||||
# Disable SIMD on Emscripten by default, as it's a new unstable Wasm feature.
|
||||
# Users can still explicitly opt-in to make a SIMD-enabled build.
|
||||
@ -33,12 +45,27 @@ option(WEBP_BUILD_LIBWEBPMUX "Build the libwebpmux library." ON)
|
||||
option(WEBP_BUILD_WEBPMUX "Build the webpmux command line tool." ON)
|
||||
option(WEBP_BUILD_EXTRAS "Build extras." ON)
|
||||
option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF)
|
||||
option(WEBP_BUILD_FUZZTEST "Build the fuzztest tests." OFF)
|
||||
option(WEBP_USE_THREAD "Enable threading support" ON)
|
||||
option(WEBP_NEAR_LOSSLESS "Enable near-lossless encoding" ON)
|
||||
option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces."
|
||||
OFF)
|
||||
set(WEBP_BITTRACE "0" CACHE STRING "Bit trace mode (0=none, 1=bit, 2=bytes)")
|
||||
set_property(CACHE WEBP_BITTRACE PROPERTY STRINGS 0 1 2)
|
||||
option(WEBP_ENABLE_WUNUSED_RESULT "Add [[nodiscard]] to some functions. \
|
||||
CMake must be at least 3.21 to force C23" OFF)
|
||||
|
||||
if(WEBP_LINK_STATIC)
|
||||
if(WIN32)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
else()
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
endif()
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
# vwebp does not compile on Ubuntu with static libraries so disabling it for
|
||||
# now.
|
||||
set(WEBP_BUILD_VWEBP OFF)
|
||||
endif()
|
||||
|
||||
# Option needed for handling Unicode file names on Windows.
|
||||
if(WIN32)
|
||||
@ -58,23 +85,42 @@ if(WEBP_BUILD_WEBP_JS)
|
||||
set(WEBP_USE_THREAD OFF)
|
||||
|
||||
if(WEBP_ENABLE_SIMD)
|
||||
message("wasm2js does not support SIMD, disabling webp.js generation.")
|
||||
message(NOTICE
|
||||
"wasm2js does not support SIMD, disabling webp.js generation.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(SHARPYUV_DEP_LIBRARIES)
|
||||
set(SHARPYUV_DEP_INCLUDE_DIRS)
|
||||
set(WEBP_DEP_LIBRARIES)
|
||||
set(WEBP_DEP_INCLUDE_DIRS)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release"
|
||||
CACHE STRING "Build type: Release, Debug, MinSizeRel or RelWithDebInfo"
|
||||
FORCE)
|
||||
FORCE)
|
||||
endif()
|
||||
|
||||
# Include dependencies.
|
||||
if(WEBP_BUILD_ANIM_UTILS
|
||||
OR WEBP_BUILD_CWEBP
|
||||
OR WEBP_BUILD_DWEBP
|
||||
OR WEBP_BUILD_EXTRAS
|
||||
OR WEBP_BUILD_GIF2WEBP
|
||||
OR WEBP_BUILD_IMG2WEBP)
|
||||
set(WEBP_FIND_IMG_LIBS TRUE)
|
||||
else()
|
||||
set(WEBP_FIND_IMG_LIBS FALSE)
|
||||
endif()
|
||||
include(cmake/deps.cmake)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(BUILD_SHARED_LIBS AND NOT DEFINED CMAKE_INSTALL_RPATH)
|
||||
# Set the rpath to match autoconf/libtool behavior. Note this must be set
|
||||
# before target creation.
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
|
||||
# ##############################################################################
|
||||
# Options.
|
||||
if(WEBP_ENABLE_SWAP_16BIT_CSP)
|
||||
@ -90,24 +136,63 @@ if(WEBP_UNICODE)
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
endif()
|
||||
|
||||
if(WIN32 AND BUILD_SHARED_LIBS)
|
||||
add_definitions(-DWEBP_DLL)
|
||||
endif()
|
||||
|
||||
# pkg-config variables used by *.pc.in.
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(exec_prefix "\$\{prefix\}")
|
||||
set(libdir "\$\{prefix\}/lib")
|
||||
set(includedir "\$\{prefix\}/include")
|
||||
set(exec_prefix "\${prefix}")
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
|
||||
set(libdir "${CMAKE_INSTALL_LIBDIR}")
|
||||
else()
|
||||
set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(includedir "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
else()
|
||||
set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
endif()
|
||||
set(PTHREAD_LIBS ${CMAKE_THREAD_LIBS_INIT})
|
||||
set(INSTALLED_LIBRARIES)
|
||||
|
||||
if(MSVC)
|
||||
# match the naming convention used by nmake
|
||||
set(webp_libname_prefix "lib")
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "${webp_libname_prefix}")
|
||||
set(CMAKE_IMPORT_LIBRARY_PREFIX "${webp_libname_prefix}")
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "${webp_libname_prefix}")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||
endif()
|
||||
|
||||
if(WEBP_ENABLE_WUNUSED_RESULT)
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21.0)
|
||||
set(CMAKE_C_STANDARD 23)
|
||||
else()
|
||||
unset(CMAKE_C_STANDARD)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:C>:-std=gnu2x>)
|
||||
endif()
|
||||
add_compile_options(-Wunused-result)
|
||||
add_definitions(-DWEBP_ENABLE_NODISCARD=1)
|
||||
endif()
|
||||
|
||||
# ##############################################################################
|
||||
# Android only.
|
||||
if(ANDROID)
|
||||
include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
|
||||
add_library(cpufeatures STATIC
|
||||
add_library(cpufeatures-webp STATIC
|
||||
${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
|
||||
list(APPEND INSTALLED_LIBRARIES cpufeatures)
|
||||
target_link_libraries(cpufeatures dl)
|
||||
set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures)
|
||||
set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS}
|
||||
${ANDROID_NDK}/sources/android/cpufeatures)
|
||||
list(APPEND INSTALLED_LIBRARIES cpufeatures-webp)
|
||||
target_link_libraries(cpufeatures-webp dl)
|
||||
set(SHARPYUV_DEP_LIBRARIES ${SHARPYUV_DEP_LIBRARIES} cpufeatures-webp)
|
||||
set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures-webp)
|
||||
set(cpufeatures_include_dir ${ANDROID_NDK}/sources/android/cpufeatures)
|
||||
set(SHARPYUV_DEP_INCLUDE_DIRS ${SHARPYUV_DEP_INCLUDE_DIRS}
|
||||
${cpufeatures_include_dir})
|
||||
set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS} ${cpufeatures_include_dir})
|
||||
add_definitions(-DHAVE_CPU_FEATURES_H=1)
|
||||
set(HAVE_CPU_FEATURES_H 1)
|
||||
else()
|
||||
@ -116,7 +201,7 @@ endif()
|
||||
|
||||
function(configure_pkg_config FILE)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FILE}")
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${FILE}" @ONLY)
|
||||
|
||||
if(HAVE_MATH_LIBRARY)
|
||||
# MSVC doesn't have libm
|
||||
@ -125,10 +210,8 @@ function(configure_pkg_config FILE)
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${FILE} ${data})
|
||||
endif()
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/${FILE}"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||
)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${FILE}"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
endfunction()
|
||||
|
||||
# ##############################################################################
|
||||
@ -138,23 +221,15 @@ endfunction()
|
||||
# E.g.: libimagedec_la_SOURCES = image_dec.c image_dec.h
|
||||
function(parse_Makefile_am FOLDER VAR SRC_REGEX)
|
||||
file(READ ${FOLDER}/Makefile.am MAKEFILE_AM)
|
||||
string(REGEX MATCHALL
|
||||
"${SRC_REGEX}_SOURCES[ ]*\\+?=[ ]+[0-9a-z\\._ ]*"
|
||||
FILES_PER_LINE
|
||||
${MAKEFILE_AM})
|
||||
string(REGEX MATCHALL "${SRC_REGEX}_SOURCES[ ]*\\+?=[ ]+[0-9a-z\\._ ]*"
|
||||
FILES_PER_LINE ${MAKEFILE_AM})
|
||||
set(SRCS ${${VAR}})
|
||||
foreach(FILES ${FILES_PER_LINE})
|
||||
string(FIND ${FILES} "=" OFFSET)
|
||||
math(EXPR OFFSET "${OFFSET} + 2")
|
||||
string(SUBSTRING ${FILES}
|
||||
${OFFSET}
|
||||
-1
|
||||
FILES)
|
||||
string(SUBSTRING ${FILES} ${OFFSET} -1 FILES)
|
||||
if(FILES)
|
||||
string(REGEX MATCHALL
|
||||
"[0-9a-z\\._]+"
|
||||
FILES
|
||||
${FILES})
|
||||
string(REGEX MATCHALL "[0-9a-z\\._]+" FILES ${FILES})
|
||||
foreach(FILE ${FILES})
|
||||
list(APPEND SRCS ${FOLDER}/${FILE})
|
||||
endforeach()
|
||||
@ -183,161 +258,17 @@ endforeach()
|
||||
|
||||
# Generate the config.h file.
|
||||
configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/webp/config.h)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/webp/config.h @ONLY)
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
|
||||
# ##############################################################################
|
||||
# Build the webpdecoder library.
|
||||
|
||||
# Creates a source file with an unused stub function in $CMAKE_BINARY_DIR and
|
||||
# adds it to the specified target. Currently used only with Xcode.
|
||||
#
|
||||
# See also:
|
||||
# https://cmake.org/cmake/help/v3.18/command/add_library.html#object-libraries
|
||||
# "Some native build systems (such as Xcode) may not like targets that have
|
||||
# only object files, so consider adding at least one real source file to any
|
||||
# target that references $<TARGET_OBJECTS:objlib>."
|
||||
function(libwebp_add_stub_file TARGET)
|
||||
set(stub_source_dir "${CMAKE_BINARY_DIR}")
|
||||
set(stub_source_file
|
||||
"${stub_source_dir}/libwebp_${TARGET}_stub.c")
|
||||
set(stub_source_code
|
||||
"// Generated file. DO NOT EDIT!\n"
|
||||
"// C source file created for target ${TARGET}.\n"
|
||||
"void libwebp_${TARGET}_stub_function(void)\;\n"
|
||||
"void libwebp_${TARGET}_stub_function(void) {}\n")
|
||||
file(WRITE "${stub_source_file}" ${stub_source_code})
|
||||
|
||||
target_sources(${TARGET} PRIVATE ${stub_source_file})
|
||||
endfunction()
|
||||
|
||||
if(MSVC)
|
||||
# avoid security warnings for e.g., fopen() used in the examples.
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
else()
|
||||
add_definitions(-Wall)
|
||||
endif()
|
||||
include_directories(${WEBP_DEP_INCLUDE_DIRS})
|
||||
add_library(webpdecode OBJECT ${WEBP_DEC_SRCS})
|
||||
target_include_directories(webpdecode
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS})
|
||||
target_include_directories(webpdspdecode
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webputilsdecode
|
||||
OBJECT
|
||||
${WEBP_UTILS_COMMON_SRCS}
|
||||
${WEBP_UTILS_DEC_SRCS})
|
||||
target_include_directories(webputilsdecode
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webpdecoder
|
||||
$<TARGET_OBJECTS:webpdecode>
|
||||
$<TARGET_OBJECTS:webpdspdecode>
|
||||
$<TARGET_OBJECTS:webputilsdecode>)
|
||||
if(XCODE)
|
||||
libwebp_add_stub_file(webpdecoder)
|
||||
endif()
|
||||
target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES})
|
||||
target_include_directories(
|
||||
webpdecoder
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
set_target_properties(
|
||||
webpdecoder
|
||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||
|
||||
configure_pkg_config("src/libwebpdecoder.pc")
|
||||
|
||||
# Build the webp library.
|
||||
add_library(webpencode OBJECT ${WEBP_ENC_SRCS})
|
||||
target_include_directories(webpencode
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webpdsp
|
||||
OBJECT
|
||||
${WEBP_DSP_COMMON_SRCS}
|
||||
${WEBP_DSP_DEC_SRCS}
|
||||
${WEBP_DSP_ENC_SRCS})
|
||||
target_include_directories(webpdsp
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webputils
|
||||
OBJECT
|
||||
${WEBP_UTILS_COMMON_SRCS}
|
||||
${WEBP_UTILS_DEC_SRCS}
|
||||
${WEBP_UTILS_ENC_SRCS})
|
||||
target_include_directories(webputils
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webp
|
||||
$<TARGET_OBJECTS:webpdecode>
|
||||
$<TARGET_OBJECTS:webpdsp>
|
||||
$<TARGET_OBJECTS:webpencode>
|
||||
$<TARGET_OBJECTS:webputils>)
|
||||
if(XCODE)
|
||||
libwebp_add_stub_file(webp)
|
||||
endif()
|
||||
target_link_libraries(webp ${WEBP_DEP_LIBRARIES})
|
||||
target_include_directories(
|
||||
webp
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
set_target_properties(
|
||||
webp
|
||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/encode.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||
|
||||
# Make sure the OBJECT libraries are built with position independent code (it is
|
||||
# not ON by default).
|
||||
set_target_properties(webpdecode
|
||||
webpdspdecode
|
||||
webputilsdecode
|
||||
webpencode
|
||||
webpdsp
|
||||
webputils
|
||||
PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
configure_pkg_config("src/libwebp.pc")
|
||||
|
||||
# Build the webp demux library.
|
||||
add_library(webpdemux ${WEBP_DEMUX_SRCS})
|
||||
target_link_libraries(webpdemux webp)
|
||||
target_include_directories(webpdemux
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
PUBLIC $<INSTALL_INTERFACE:include>)
|
||||
set_target_properties(
|
||||
webpdemux
|
||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||
|
||||
configure_pkg_config("src/demux/libwebpdemux.pc")
|
||||
|
||||
# Set the version numbers.
|
||||
macro(set_version FILE TARGET_NAME NAME_IN_MAKEFILE)
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/src/${FILE} SOURCE_FILE)
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} SOURCE_FILE)
|
||||
string(REGEX MATCH
|
||||
"${NAME_IN_MAKEFILE}_la_LDFLAGS[^\n]* -version-info [0-9:]+"
|
||||
TMP
|
||||
"${NAME_IN_MAKEFILE}_la_LDFLAGS[^\n]* -version-info [0-9:]+" TMP
|
||||
${SOURCE_FILE})
|
||||
string(REGEX MATCH
|
||||
"[0-9:]+"
|
||||
TMP
|
||||
${TMP})
|
||||
string(REGEX
|
||||
REPLACE ":"
|
||||
" "
|
||||
LT_VERSION
|
||||
${TMP})
|
||||
string(REGEX MATCH "[0-9:]+" TMP ${TMP})
|
||||
string(REGEX REPLACE ":" " " LT_VERSION ${TMP})
|
||||
|
||||
# See the libtool docs for more information:
|
||||
# https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
|
||||
@ -356,23 +287,166 @@ macro(set_version FILE TARGET_NAME NAME_IN_MAKEFILE)
|
||||
|
||||
set_target_properties(
|
||||
${TARGET_NAME}
|
||||
PROPERTIES VERSION
|
||||
${LT_CURRENT_MINUS_AGE}.${LT_AGE}.${LT_REVISION}
|
||||
SOVERSION
|
||||
${LT_CURRENT_MINUS_AGE})
|
||||
PROPERTIES VERSION ${LT_CURRENT_MINUS_AGE}.${LT_AGE}.${LT_REVISION}
|
||||
SOVERSION ${LT_CURRENT_MINUS_AGE})
|
||||
if(APPLE)
|
||||
# For compatibility, set MACHO_COMPATIBILITY_VERSION and
|
||||
# MACHO_CURRENT_VERSION to match libtool. These properties were introduced
|
||||
# in 3.17:
|
||||
# https://cmake.org/cmake/help/latest/prop_tgt/MACHO_COMPATIBILITY_VERSION.html
|
||||
math(EXPR LIBWEBP_MACHO_COMPATIBILITY_VERSION "${LT_CURRENT} + 1")
|
||||
set_target_properties(
|
||||
${TARGET_NAME}
|
||||
PROPERTIES MACHO_COMPATIBILITY_VERSION
|
||||
${LIBWEBP_MACHO_COMPATIBILITY_VERSION}
|
||||
MACHO_CURRENT_VERSION
|
||||
${LIBWEBP_MACHO_COMPATIBILITY_VERSION}.${LT_REVISION})
|
||||
endif()
|
||||
endmacro()
|
||||
set_version(Makefile.am webp webp)
|
||||
set_version(Makefile.am webpdecoder webpdecoder)
|
||||
set_version(demux/Makefile.am webpdemux webpdemux)
|
||||
|
||||
# ##############################################################################
|
||||
# Build the webpdecoder library.
|
||||
|
||||
# Creates a source file with an unused stub function in $CMAKE_BINARY_DIR and
|
||||
# adds it to the specified target. Currently used only with Xcode.
|
||||
#
|
||||
# See also:
|
||||
# https://cmake.org/cmake/help/v3.18/command/add_library.html#object-libraries
|
||||
# "Some native build systems (such as Xcode) may not like targets that have only
|
||||
# object files, so consider adding at least one real source file to any target
|
||||
# that references $<TARGET_OBJECTS:objlib>."
|
||||
function(libwebp_add_stub_file TARGET)
|
||||
set(stub_source_dir "${CMAKE_BINARY_DIR}")
|
||||
set(stub_source_file "${stub_source_dir}/libwebp_${TARGET}_stub.c")
|
||||
set(stub_source_code
|
||||
"// Generated file. DO NOT EDIT!\n"
|
||||
"// C source file created for target ${TARGET}.\n"
|
||||
"void libwebp_${TARGET}_stub_function(void)\;\n"
|
||||
"void libwebp_${TARGET}_stub_function(void) {}\n")
|
||||
file(WRITE "${stub_source_file}" ${stub_source_code})
|
||||
|
||||
target_sources(${TARGET} PRIVATE ${stub_source_file})
|
||||
endfunction()
|
||||
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv "WEBP_SHARPYUV_SRCS" "")
|
||||
add_library(sharpyuv ${WEBP_SHARPYUV_SRCS})
|
||||
target_link_libraries(sharpyuv ${SHARPYUV_DEP_LIBRARIES})
|
||||
set_version(sharpyuv/Makefile.am sharpyuv sharpyuv)
|
||||
target_include_directories(
|
||||
sharpyuv PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
set_target_properties(
|
||||
sharpyuv
|
||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sharpyuv/sharpyuv_csp.h")
|
||||
configure_pkg_config("sharpyuv/libsharpyuv.pc")
|
||||
install(
|
||||
TARGETS sharpyuv
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp/sharpyuv
|
||||
INCLUDES
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
${CMAKE_INSTALL_INCLUDEDIR}/webp
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
if(MSVC)
|
||||
# avoid security warnings for e.g., fopen() used in the examples.
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
else()
|
||||
add_compile_options(-Wall)
|
||||
endif()
|
||||
include_directories(${WEBP_DEP_INCLUDE_DIRS})
|
||||
add_library(webpdecode OBJECT ${WEBP_DEC_SRCS})
|
||||
target_include_directories(webpdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webpdspdecode OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS})
|
||||
target_include_directories(webpdspdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webputilsdecode OBJECT ${WEBP_UTILS_COMMON_SRCS}
|
||||
${WEBP_UTILS_DEC_SRCS})
|
||||
target_include_directories(webputilsdecode PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(
|
||||
webpdecoder $<TARGET_OBJECTS:webpdecode> $<TARGET_OBJECTS:webpdspdecode>
|
||||
$<TARGET_OBJECTS:webputilsdecode>)
|
||||
if(XCODE)
|
||||
libwebp_add_stub_file(webpdecoder)
|
||||
endif()
|
||||
target_link_libraries(webpdecoder ${WEBP_DEP_LIBRARIES})
|
||||
target_include_directories(
|
||||
webpdecoder
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
INTERFACE
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR}>"
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
set_target_properties(
|
||||
webpdecoder
|
||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||
|
||||
configure_pkg_config("src/libwebpdecoder.pc")
|
||||
|
||||
# Build the webp library.
|
||||
add_library(webpencode OBJECT ${WEBP_ENC_SRCS})
|
||||
target_include_directories(
|
||||
webpencode PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
add_library(webpdsp OBJECT ${WEBP_DSP_COMMON_SRCS} ${WEBP_DSP_DEC_SRCS}
|
||||
${WEBP_DSP_ENC_SRCS})
|
||||
target_include_directories(webpdsp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webputils OBJECT ${WEBP_UTILS_COMMON_SRCS} ${WEBP_UTILS_DEC_SRCS}
|
||||
${WEBP_UTILS_ENC_SRCS})
|
||||
target_include_directories(webputils PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_library(webp $<TARGET_OBJECTS:webpdecode> $<TARGET_OBJECTS:webpdsp>
|
||||
$<TARGET_OBJECTS:webpencode> $<TARGET_OBJECTS:webputils>)
|
||||
target_link_libraries(webp sharpyuv)
|
||||
if(XCODE)
|
||||
libwebp_add_stub_file(webp)
|
||||
endif()
|
||||
target_link_libraries(webp ${WEBP_DEP_LIBRARIES})
|
||||
target_include_directories(
|
||||
webp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
set_target_properties(
|
||||
webp
|
||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/encode.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||
|
||||
# Make sure the OBJECT libraries are built with position independent code (it is
|
||||
# not ON by default).
|
||||
set_target_properties(webpdecode webpdspdecode webputilsdecode webpencode
|
||||
webpdsp webputils PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
configure_pkg_config("src/libwebp.pc")
|
||||
|
||||
# Build the webp demux library.
|
||||
add_library(webpdemux ${WEBP_DEMUX_SRCS})
|
||||
target_link_libraries(webpdemux webp)
|
||||
target_include_directories(
|
||||
webpdemux PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
PUBLIC $<INSTALL_INTERFACE:include>)
|
||||
set_target_properties(
|
||||
webpdemux
|
||||
PROPERTIES
|
||||
PUBLIC_HEADER
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/webp/decode.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/demux.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h")
|
||||
|
||||
configure_pkg_config("src/demux/libwebpdemux.pc")
|
||||
|
||||
set_version(src/Makefile.am webp webp)
|
||||
set_version(src/Makefile.am webpdecoder webpdecoder)
|
||||
set_version(src/demux/Makefile.am webpdemux webpdemux)
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_FILE)
|
||||
string(REGEX MATCH
|
||||
"AC_INIT\\([^\n]*\\[[0-9\\.]+\\]"
|
||||
TMP
|
||||
${CONFIGURE_FILE})
|
||||
string(REGEX MATCH
|
||||
"[0-9\\.]+"
|
||||
PROJECT_VERSION
|
||||
${TMP})
|
||||
string(REGEX MATCH "AC_INIT\\([^\n]*\\[[0-9\\.]+\\]" TMP ${CONFIGURE_FILE})
|
||||
string(REGEX MATCH "[0-9\\.]+" PROJECT_VERSION ${TMP})
|
||||
|
||||
# Define the libraries to install.
|
||||
list(APPEND INSTALLED_LIBRARIES webpdecoder webp webpdemux)
|
||||
@ -385,10 +459,8 @@ math(EXPR WEBP_SIMD_FILES_TO_INCLUDE_RANGE
|
||||
foreach(I_FILE RANGE ${WEBP_SIMD_FILES_TO_INCLUDE_RANGE})
|
||||
list(GET WEBP_SIMD_FILES_TO_INCLUDE ${I_FILE} FILE)
|
||||
list(GET WEBP_SIMD_FLAGS_TO_INCLUDE ${I_FILE} SIMD_COMPILE_FLAG)
|
||||
set_source_files_properties(${FILE}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
${SIMD_COMPILE_FLAG})
|
||||
set_source_files_properties(${FILE} PROPERTIES COMPILE_FLAGS
|
||||
${SIMD_COMPILE_FLAG})
|
||||
endforeach()
|
||||
|
||||
if(NOT WEBP_BUILD_LIBWEBPMUX)
|
||||
@ -409,32 +481,32 @@ endif()
|
||||
if(WEBP_BUILD_ANIM_UTILS
|
||||
OR WEBP_BUILD_CWEBP
|
||||
OR WEBP_BUILD_DWEBP
|
||||
OR WEBP_BUILD_EXTRAS
|
||||
OR WEBP_BUILD_FUZZTEST
|
||||
OR WEBP_BUILD_GIF2WEBP
|
||||
OR WEBP_BUILD_IMG2WEBP
|
||||
OR WEBP_BUILD_VWEBP)
|
||||
OR WEBP_BUILD_VWEBP
|
||||
OR WEBP_BUILD_WEBPMUX
|
||||
OR WEBP_BUILD_WEBPINFO)
|
||||
# Example utility library.
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "EXAMPLEUTIL_SRCS"
|
||||
"example_util_[^ ]*")
|
||||
list(APPEND EXAMPLEUTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/examples/stopwatch.h)
|
||||
add_library(exampleutil STATIC ${EXAMPLEUTIL_SRCS})
|
||||
target_link_libraries(exampleutil imageioutil)
|
||||
target_include_directories(
|
||||
exampleutil
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
|
||||
exampleutil PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
|
||||
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEIOUTILS_SRCS"
|
||||
"imageio_util_[^ ]*")
|
||||
add_library(imageioutil STATIC ${IMAGEIOUTILS_SRCS})
|
||||
target_link_libraries(imageioutil webp)
|
||||
target_link_libraries(exampleutil imageioutil)
|
||||
|
||||
# Image-decoding utility library.
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS"
|
||||
"imagedec_[^ ]*")
|
||||
add_library(imagedec STATIC ${IMAGEDEC_SRCS})
|
||||
target_link_libraries(imagedec
|
||||
imageioutil
|
||||
webpdemux
|
||||
webp
|
||||
target_link_libraries(imagedec imageioutil webpdemux webp
|
||||
${WEBP_DEP_IMG_LIBRARIES})
|
||||
|
||||
# Image-encoding utility library.
|
||||
@ -443,12 +515,12 @@ if(WEBP_BUILD_ANIM_UTILS
|
||||
add_library(imageenc STATIC ${IMAGEENC_SRCS})
|
||||
target_link_libraries(imageenc imageioutil webp)
|
||||
|
||||
set_property(TARGET exampleutil
|
||||
imageioutil
|
||||
imagedec
|
||||
imageenc
|
||||
PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
set_property(
|
||||
TARGET exampleutil imageioutil imagedec imageenc
|
||||
PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
target_include_directories(imagedec PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS})
|
||||
target_include_directories(imageenc PRIVATE ${WEBP_DEP_IMG_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(WEBP_BUILD_DWEBP)
|
||||
@ -465,7 +537,8 @@ if(WEBP_BUILD_CWEBP)
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "CWEBP_SRCS" "cwebp")
|
||||
add_executable(cwebp ${CWEBP_SRCS})
|
||||
target_link_libraries(cwebp exampleutil imagedec webp)
|
||||
target_include_directories(cwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
target_include_directories(cwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
install(TARGETS cwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
@ -473,13 +546,12 @@ if(WEBP_BUILD_LIBWEBPMUX)
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/src/mux "WEBP_MUX_SRCS" "")
|
||||
add_library(libwebpmux ${WEBP_MUX_SRCS})
|
||||
target_link_libraries(libwebpmux webp)
|
||||
target_include_directories(libwebpmux
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set_version(mux/Makefile.am libwebpmux webpmux)
|
||||
set_target_properties(libwebpmux
|
||||
PROPERTIES PUBLIC_HEADER
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux.h;\
|
||||
target_include_directories(libwebpmux PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set_version(src/mux/Makefile.am libwebpmux webpmux)
|
||||
set_target_properties(
|
||||
libwebpmux
|
||||
PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/mux_types.h;\
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/webp/types.h;")
|
||||
set_target_properties(libwebpmux PROPERTIES OUTPUT_NAME webpmux)
|
||||
@ -493,11 +565,7 @@ if(WEBP_BUILD_GIF2WEBP)
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "GIF2WEBP_SRCS"
|
||||
"gif2webp")
|
||||
add_executable(gif2webp ${GIF2WEBP_SRCS})
|
||||
target_link_libraries(gif2webp
|
||||
exampleutil
|
||||
imageioutil
|
||||
webp
|
||||
libwebpmux
|
||||
target_link_libraries(gif2webp exampleutil imageioutil webp libwebpmux
|
||||
${WEBP_DEP_GIF_LIBRARIES})
|
||||
target_include_directories(gif2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
install(TARGETS gif2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
@ -509,13 +577,10 @@ if(WEBP_BUILD_IMG2WEBP)
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "IMG2WEBP_SRCS"
|
||||
"img2webp")
|
||||
add_executable(img2webp ${IMG2WEBP_SRCS})
|
||||
target_link_libraries(img2webp
|
||||
exampleutil
|
||||
imagedec
|
||||
imageioutil
|
||||
webp
|
||||
target_link_libraries(img2webp exampleutil imagedec imageioutil webp
|
||||
libwebpmux)
|
||||
target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
install(TARGETS img2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
@ -526,17 +591,17 @@ if(WEBP_BUILD_VWEBP)
|
||||
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "VWEBP_SRCS" "vwebp")
|
||||
add_executable(vwebp ${VWEBP_SRCS})
|
||||
target_link_libraries(vwebp
|
||||
${OPENGL_LIBRARIES}
|
||||
exampleutil
|
||||
${GLUT_glut_LIBRARY}
|
||||
imageioutil
|
||||
webp
|
||||
webpdemux)
|
||||
target_include_directories(vwebp
|
||||
PRIVATE ${GLUT_INCLUDE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src
|
||||
${OPENGL_INCLUDE_DIR})
|
||||
target_link_libraries(
|
||||
vwebp
|
||||
${OPENGL_LIBRARIES}
|
||||
exampleutil
|
||||
GLUT::GLUT
|
||||
imageioutil
|
||||
webp
|
||||
webpdemux)
|
||||
target_include_directories(
|
||||
vwebp PRIVATE ${GLUT_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/src
|
||||
${OPENGL_INCLUDE_DIR})
|
||||
install(TARGETS vwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
check_c_compiler_flag("-Wno-deprecated-declarations" HAS_NO_DEPRECATED)
|
||||
@ -554,7 +619,8 @@ if(WEBP_BUILD_WEBPINFO)
|
||||
"webpinfo")
|
||||
add_executable(webpinfo ${WEBPINFO_SRCS})
|
||||
target_link_libraries(webpinfo exampleutil imageioutil)
|
||||
target_include_directories(webpinfo PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
target_include_directories(webpinfo PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
install(TARGETS webpinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
@ -575,61 +641,101 @@ if(WEBP_BUILD_EXTRAS)
|
||||
parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_QUALITY_SRCS" "webp_quality")
|
||||
parse_makefile_am(${EXTRAS_MAKEFILE} "VWEBP_SDL_SRCS" "vwebp_sdl")
|
||||
|
||||
# libextras
|
||||
add_library(extras STATIC ${WEBP_EXTRAS_SRCS})
|
||||
target_include_directories(
|
||||
extras PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
|
||||
# get_disto
|
||||
add_executable(get_disto ${GET_DISTO_SRCS})
|
||||
target_link_libraries(get_disto imagedec)
|
||||
target_include_directories(get_disto
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
target_include_directories(get_disto PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
|
||||
# webp_quality
|
||||
add_executable(webp_quality ${WEBP_QUALITY_SRCS} ${WEBP_EXTRAS_SRCS})
|
||||
target_link_libraries(webp_quality exampleutil imagedec)
|
||||
target_include_directories(webp_quality
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_executable(webp_quality ${WEBP_QUALITY_SRCS})
|
||||
target_link_libraries(webp_quality exampleutil imagedec extras)
|
||||
target_include_directories(webp_quality PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# vwebp_sdl
|
||||
find_package(SDL)
|
||||
if(SDL_FOUND)
|
||||
find_package(SDL2 QUIET)
|
||||
if(WEBP_BUILD_VWEBP AND SDL2_FOUND)
|
||||
add_executable(vwebp_sdl ${VWEBP_SDL_SRCS})
|
||||
target_link_libraries(vwebp_sdl ${SDL_LIBRARY} imageioutil webp)
|
||||
target_include_directories(vwebp_sdl
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src
|
||||
${SDL_INCLUDE_DIR})
|
||||
target_link_libraries(vwebp_sdl ${SDL2_LIBRARIES} imageioutil webp)
|
||||
target_include_directories(
|
||||
vwebp_sdl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src ${SDL2_INCLUDE_DIRS})
|
||||
set(WEBP_HAVE_SDL 1)
|
||||
target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES "${SDL2_INCLUDE_DIRS}")
|
||||
check_c_source_compiles(
|
||||
"
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include \"SDL.h\"
|
||||
int main(void) {
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
HAVE_JUST_SDL_H)
|
||||
set(CMAKE_REQUIRED_INCLUDES)
|
||||
if(HAVE_JUST_SDL_H)
|
||||
target_compile_definitions(vwebp_sdl PRIVATE WEBP_HAVE_JUST_SDL_H)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WEBP_BUILD_WEBP_JS)
|
||||
# The default stack size changed from 5MB to 64KB in 3.1.27. See
|
||||
# https://crbug.com/webp/614.
|
||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.27")
|
||||
# TOTAL_STACK size was renamed to STACK_SIZE in 3.1.27. The old name was
|
||||
# kept for compatibility, but prefer the new one in case it is removed in
|
||||
# the future.
|
||||
set(emscripten_stack_size "-sSTACK_SIZE=5MB")
|
||||
else()
|
||||
set(emscripten_stack_size "-sTOTAL_STACK=5MB")
|
||||
endif()
|
||||
find_package(SDL2 REQUIRED)
|
||||
# wasm2js does not support SIMD.
|
||||
if(NOT WEBP_ENABLE_SIMD)
|
||||
# JavaScript version
|
||||
add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
|
||||
target_link_libraries(webp_js webpdecoder SDL)
|
||||
target_link_libraries(webp_js webpdecoder SDL2)
|
||||
target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(WEBP_HAVE_SDL 1)
|
||||
set_target_properties(
|
||||
webp_js
|
||||
PROPERTIES LINK_FLAGS "-s WASM=0 \
|
||||
-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
|
||||
-s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
|
||||
PROPERTIES
|
||||
# Emscripten puts -sUSE_SDL2=1 in this variable, though it's needed at
|
||||
# compile time to ensure the headers are downloaded.
|
||||
COMPILE_OPTIONS "${SDL2_LIBRARIES}"
|
||||
LINK_FLAGS
|
||||
"-sWASM=0 ${emscripten_stack_size} \
|
||||
-sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \
|
||||
-sEXPORTED_RUNTIME_METHODS=cwrap ${SDL2_LIBRARIES} \
|
||||
-sALLOW_MEMORY_GROWTH")
|
||||
set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp)
|
||||
target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
|
||||
endif()
|
||||
|
||||
# WASM version
|
||||
add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
|
||||
target_link_libraries(webp_wasm webpdecoder SDL)
|
||||
target_link_libraries(webp_wasm webpdecoder SDL2)
|
||||
target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_target_properties(
|
||||
webp_wasm
|
||||
PROPERTIES LINK_FLAGS "-s WASM=1 \
|
||||
-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
|
||||
-s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
|
||||
PROPERTIES
|
||||
# Emscripten puts -sUSE_SDL2=1 in this variable, though it's needed at
|
||||
# compile time to ensure the headers are downloaded.
|
||||
COMPILE_OPTIONS "${SDL2_LIBRARIES}"
|
||||
LINK_FLAGS
|
||||
"-sWASM=1 ${emscripten_stack_size} \
|
||||
-sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \
|
||||
-sEXPORTED_RUNTIME_METHODS=cwrap ${SDL2_LIBRARIES} \
|
||||
-sALLOW_MEMORY_GROWTH")
|
||||
target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
|
||||
|
||||
target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN)
|
||||
@ -641,14 +747,15 @@ if(WEBP_BUILD_ANIM_UTILS)
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DIFF_SRCS"
|
||||
"anim_diff")
|
||||
add_executable(anim_diff ${ANIM_DIFF_SRCS})
|
||||
target_link_libraries(anim_diff
|
||||
exampleutil
|
||||
imagedec
|
||||
imageenc
|
||||
imageioutil
|
||||
webp
|
||||
webpdemux
|
||||
${WEBP_DEP_GIF_LIBRARIES})
|
||||
target_link_libraries(
|
||||
anim_diff
|
||||
exampleutil
|
||||
imagedec
|
||||
imageenc
|
||||
imageioutil
|
||||
webp
|
||||
webpdemux
|
||||
${WEBP_DEP_GIF_LIBRARIES})
|
||||
target_include_directories(anim_diff PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
|
||||
# anim_dump
|
||||
@ -656,45 +763,63 @@ if(WEBP_BUILD_ANIM_UTILS)
|
||||
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "ANIM_DUMP_SRCS"
|
||||
"anim_dump")
|
||||
add_executable(anim_dump ${ANIM_DUMP_SRCS})
|
||||
target_link_libraries(anim_dump
|
||||
exampleutil
|
||||
imagedec
|
||||
imageenc
|
||||
imageioutil
|
||||
webp
|
||||
webpdemux
|
||||
${WEBP_DEP_GIF_LIBRARIES})
|
||||
target_link_libraries(
|
||||
anim_dump
|
||||
exampleutil
|
||||
imagedec
|
||||
imageenc
|
||||
imageioutil
|
||||
webp
|
||||
webpdemux
|
||||
${WEBP_DEP_GIF_LIBRARIES})
|
||||
target_include_directories(anim_dump PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
endif()
|
||||
|
||||
if(WEBP_BUILD_FUZZTEST)
|
||||
add_subdirectory(tests/fuzzer)
|
||||
endif()
|
||||
|
||||
# Install the different headers and libraries.
|
||||
install(TARGETS ${INSTALLED_LIBRARIES}
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp
|
||||
INCLUDES
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(
|
||||
TARGETS ${INSTALLED_LIBRARIES}
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webp
|
||||
INCLUDES
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
set(ConfigPackageLocation ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake/)
|
||||
install(EXPORT ${PROJECT_NAME}Targets
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
install(EXPORT ${PROJECT_NAME}Targets NAMESPACE ${PROJECT_NAME}::
|
||||
DESTINATION ${ConfigPackageLocation})
|
||||
|
||||
# Create the CMake version file.
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"
|
||||
VERSION ${PACKAGE_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion)
|
||||
|
||||
# Create the Config file.
|
||||
include(CMakePackageConfigHelpers)
|
||||
# Fix libwebpmux reference. The target name libwebpmux is used for compatibility
|
||||
# purposes, but the library mentioned in WebPConfig.cmake should be the
|
||||
# unprefixed version. Note string(...) can be replaced with list(TRANSFORM ...)
|
||||
# if cmake_minimum_required is >= 3.12.
|
||||
string(REGEX REPLACE "libwebpmux" "webpmux" INSTALLED_LIBRARIES
|
||||
"${INSTALLED_LIBRARIES}")
|
||||
|
||||
if(MSVC)
|
||||
# For compatibility with nmake, MSVC builds use a custom prefix (lib) that
|
||||
# needs to be included in the library name.
|
||||
string(REGEX REPLACE "[A-Za-z0-9_]+" "${CMAKE_STATIC_LIBRARY_PREFIX}\\0"
|
||||
INSTALLED_LIBRARIES "${INSTALLED_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
configure_package_config_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/WebPConfig.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake
|
||||
INSTALL_DESTINATION
|
||||
${ConfigPackageLocation})
|
||||
INSTALL_DESTINATION ${ConfigPackageLocation}
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR)
|
||||
|
||||
# Install the generated CMake files.
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"
|
||||
@ -726,7 +851,6 @@ foreach(I_MAN RANGE ${MAN_PAGES_RANGE})
|
||||
if(WEBP_BUILD_${EXEC_BUILD})
|
||||
list(GET MAN_PAGES ${I_MAN} MAN_PAGE)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man/${MAN_PAGE}
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
|
||||
COMPONENT doc)
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 COMPONENT doc)
|
||||
endif()
|
||||
endforeach()
|
||||
|
@ -19,10 +19,59 @@ again.
|
||||
|
||||
All submissions, including submissions by project members, require review. We
|
||||
use a [Gerrit](https://www.gerritcodereview.com) instance hosted at
|
||||
https://chromium-review.googlesource.com for this purpose. See the
|
||||
https://chromium-review.googlesource.com for this purpose.
|
||||
|
||||
## Sending patches
|
||||
|
||||
The basic git workflow for modifying libwebp code and sending for review is:
|
||||
|
||||
1. Get the latest version of the repository locally:
|
||||
|
||||
```sh
|
||||
git clone https://chromium.googlesource.com/webm/libwebp && cd libwebp
|
||||
```
|
||||
|
||||
2. Copy the commit-msg script into ./git/hooks (this will add an ID to all of
|
||||
your commits):
|
||||
|
||||
```sh
|
||||
curl -Lo .git/hooks/commit-msg https://chromium-review.googlesource.com/tools/hooks/commit-msg && chmod u+x .git/hooks/commit-msg
|
||||
```
|
||||
|
||||
3. Modify the local copy of libwebp. Make sure the code
|
||||
[builds successfully](https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/building.md#cmake).
|
||||
|
||||
4. Choose a short and representative commit message:
|
||||
|
||||
```sh
|
||||
git commit -a -m "Set commit message here"
|
||||
```
|
||||
|
||||
5. Send the patch for review:
|
||||
|
||||
```sh
|
||||
git push https://chromium-review.googlesource.com/webm/libwebp HEAD:refs/for/main
|
||||
```
|
||||
|
||||
Go to https://chromium-review.googlesource.com to view your patch and
|
||||
request a review from the maintainers.
|
||||
|
||||
See the
|
||||
[WebM Project page](https://www.webmproject.org/code/contribute/submitting-patches/)
|
||||
for additional details.
|
||||
|
||||
## Code Style
|
||||
|
||||
The C code style is based on the
|
||||
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) and
|
||||
`clang-format --style=Google`, though this project doesn't use the tool to
|
||||
enforce the formatting.
|
||||
|
||||
CMake files are formatted with
|
||||
[cmake-format](https://cmake-format.readthedocs.io/en/latest/). `cmake-format
|
||||
-i` can be used to format individual files, it will use the settings from
|
||||
`.cmake-format.py`.
|
||||
|
||||
## Community Guidelines
|
||||
|
||||
This project follows
|
||||
|
502
ChangeLog
502
ChangeLog
@ -1,12 +1,506 @@
|
||||
8a6a55bb update NEWS
|
||||
cf7c5a5d provide a way to opt-out/override WEBP_NODISCARD
|
||||
cc34288a update ChangeLog (tag: v1.4.0-rc1)
|
||||
f13c0886 NEWS: fix date
|
||||
74555950 Merge "vwebp: fix window title when options are given" into 1.4.0
|
||||
d781646c vwebp: fix window title when options are given
|
||||
c2e394de update NEWS
|
||||
f6d15cb7 bump version to 1.4.0
|
||||
57c388b8 update AUTHORS
|
||||
b3d1b2cb Merge changes I26f4aa22,I83386b6c,I320ed1a2 into main
|
||||
07216886 webp-container-spec: fix VP8 chunk ref ('VP8'->'VP8 ')
|
||||
f88666eb webp_js/*.html: fix canvas mapping
|
||||
e2c8f233 cmake,wasm: simplify SDL2 related flags
|
||||
d537cd37 cmake: fix vwebp_sdl compile w/libsdl-org release
|
||||
6c484cbf CMakeLists.txt: add missing WEBP_BUILD_EXTRAS check
|
||||
7b0bc235 man/cwebp.1: add more detail to -partition_limit
|
||||
3c0011bb WebPMuxGetChunk: add an assert
|
||||
955a3d14 Merge "muxread,MuxGet: add an assert" into main
|
||||
00abc000 muxread,MuxGet: add an assert
|
||||
40e85a0b Have the window title reflect the filename.
|
||||
1bf46358 man/cwebp.1: clarify -pass > 1 behavior w/o -size/-psnr
|
||||
eba03acb webp-container-spec: replace 'above' with 'earlier'
|
||||
a16d30cb webp-container-spec: clarify chunk order requirements
|
||||
8a7e9112 Merge "CMakeLists.txt: apply cmake-format" into main
|
||||
7fac6c1b Merge "Copy C code to not have multiplication overflow" into main
|
||||
e2922e43 Merge "Check for the presence of the ANDROID_ABI variable" into main
|
||||
501d9274 Copy C code to not have multiplication overflow
|
||||
fba7d62e CMakeLists.txt: apply cmake-format
|
||||
661c1b66 Merge "windows exports: use dllexport attribute, instead of visibility." into main
|
||||
8487860a windows exports: use dllexport attribute, instead of visibility.
|
||||
8ea678b9 webp/mux.h: data lifetime note w/copy_data=0
|
||||
79e05c7f Check for the presence of the ANDROID_ABI variable
|
||||
45f995a3 Expose functions for managing non-image chunks on WebPAnimEncoder
|
||||
1fb9f3dc gifdec: fix ErrorGIFNotAvailable() declaration
|
||||
4723db65 cosmetics: s/SANITY_CHECK/DCHECK/
|
||||
f4b9bc9e clear -Wextra-semi-stmt warnings
|
||||
713982b8 Limit animdecoder_fuzzer to 320MB
|
||||
cbe825e4 cmake: fix sharpyuv simd files' build
|
||||
f99305e9 Makefile.vc: add ARM64 support
|
||||
5efd6300 mv SharpYuvEstimate420Risk to extras/
|
||||
e78e924f Makefile.vc: add sharpyuv_risk_table.obj
|
||||
d7a0506d Add YUV420 riskiness metric.
|
||||
89c5b917 Merge "BuildHuffmanTable check sorted[] array bounds before writing" into main
|
||||
34c80749 Remove alpha encoding pessimization.
|
||||
13d9c30b Add a WEBP_NODISCARD
|
||||
24d7f9cb Switch code to SDL2.
|
||||
0b56dedc BuildHuffmanTable check sorted[] array bounds before writing
|
||||
a429c0de sharpyuv: convert some for() to do/while
|
||||
f0cd7861 DoSharpArgbToYuv: remove constant from loop
|
||||
339231cc SharpYuvConvertWithOptions,cosmetics: fix formatting
|
||||
307071f1 Remove medium/large code model-specific inline asm
|
||||
deadc339 Fix transfer functions where toGamma and toLinear are swapped.
|
||||
e7b78d43 Merge "Fix bug in FromLinearLog100." into main
|
||||
15a1309e Merge "webp-lossless-bitstream-spec: delete extra blank line" into main
|
||||
54ca9752 Fix bug in FromLinearLog100.
|
||||
d2cb2d8c Dereference after NULL check.
|
||||
e9d50107 webp-lossless-bitstream-spec: delete extra blank line
|
||||
78657971 Merge changes Ief442c90,Ie6e9c9a5 into main
|
||||
e30a5884 webp-lossless-bitstream-spec: update variable names
|
||||
09ca1368 Merge "webp-container-spec: change assert to MUST be TRUE" into main
|
||||
38cb4fc0 iosbuild,xcframeworkbuild: add SharpYuv framework
|
||||
40afa926 webp-lossless-bitstream-spec: simplify abstract
|
||||
9db21143 webp-container-spec: change assert to MUST be TRUE
|
||||
cdbf88ae Fix typo in API docs for incremental decoding
|
||||
05c46984 Reformat vcpkg build instructions.
|
||||
8534f539 Merge "Never send VP8_STATUS_SUSPENDED back in non-incremental." into main
|
||||
35e197bd Never send VP8_STATUS_SUSPENDED back in non-incremental.
|
||||
61441425 Add vcpkg installation instructions
|
||||
dce8397f Fix next is invalid pointer when WebPSafeMalloc fails
|
||||
57c58105 Cmake: wrong public macro WEBP_INCLUDE_DIRS
|
||||
c1ffd9ac Merge "vp8l_enc: fix non-C90 code" into main
|
||||
a3965948 Merge changes If628bb93,Ic79f6309,I45f0db23 into main
|
||||
f80e9b7e vp8l_enc: fix non-C90 code
|
||||
accd141d Update lossless spec for two simple codes.
|
||||
ac17ffff Fix non-C90 code.
|
||||
433c7dca Fix static analyzer warnings.
|
||||
5fac76cf Merge tag 'v1.3.2'
|
||||
ca332209 update ChangeLog (tag: v1.3.2)
|
||||
1ace578c update NEWS
|
||||
63234c42 bump version to 1.3.2
|
||||
a35ea50d Add a fuzzer for ReadHuffmanCodes
|
||||
95ea5226 Fix invalid incremental decoding check.
|
||||
2af26267 Fix OOB write in BuildHuffmanTable.
|
||||
902bc919 Fix OOB write in BuildHuffmanTable.
|
||||
7ba44f80 Homogenize "__asm__ volatile" vs "asm volatile"
|
||||
68e27135 webp-container-spec: reorder example chunk layout
|
||||
943b932a Merge changes I6a4d0a04,Ibc37b91e into main
|
||||
1cc94f95 decode.h: wrap idec example in /* */
|
||||
63acdd1e decode.h: fix decode example
|
||||
aac5c5d0 ReadHuffmanCode: rm redundant num code lengths check
|
||||
a2de25f6 webp-lossless-bitstream-spec: normalize list item case
|
||||
68820f0e webp-lossless-bitstream-spec: normalize pixel ref
|
||||
cdb31aa8 webp-lossless-bitstream-spec: add missing periods
|
||||
0535a8cf webp-lossless-bitstream-spec: fix grammar
|
||||
b6c4ce26 normalize numbered list item format
|
||||
dd7364c3 Merge "palette.c: fix msvc warnings" into main
|
||||
c63c5df6 palette.c: fix msvc warnings
|
||||
0a2cad51 webp-container-spec: move terms from intro section
|
||||
dd88d2ff webp-lossless-bitstream-spec: color_cache -> color cache
|
||||
6e750547 Merge changes I644d7d39,Icf05491e,Ic02e6652,I63b11258 into main
|
||||
67a7cc2b webp-lossless-bitstream-spec: fix code blocks
|
||||
1432ebba Refactor palette sorting computation.
|
||||
cd436142 webp-lossless-bitstream-spec: block -> chunk
|
||||
3cb66f64 webp-lossless-bitstream-spec: add some missing commas
|
||||
56471a53 webp-lossless-bitstream-spec: normalize item text in 5.1
|
||||
af7fbfd2 vp8l_dec,ReadTransform: improve error status reporting
|
||||
7d8e0896 vp8l_dec: add VP8LSetError()
|
||||
a71ce1cf animencoder_fuzzer: fix error check w/Nallocfuzz
|
||||
e94b36d6 webp-lossless-bitstream-spec: relocate details from 5.1
|
||||
84628e56 webp-lossless-bitstream-spec: clarify image width changes
|
||||
ee722997 alpha_dec: add missing VP8SetError()
|
||||
0081693d enc_dec_fuzzer: use WebPDecode()
|
||||
0fcb311c enc_dec_fuzzer: fix WebPEncode/pic.error_code check
|
||||
982c177c webp-lossless-bitstream-spec: fix struct member refs
|
||||
56cf5625 webp-lossless-bitstream-spec: use RFC 7405 for ABNF
|
||||
6c6b3fd3 webp-lossless-bitstream-spec,cosmetics: delete blank lines
|
||||
29b9eb15 Merge changes Id56ca4fd,I662bd1d7 into main
|
||||
47c0af8d ReadHuffmanCodes: rm max_alphabet_size calc
|
||||
b92deba3 animencoder_fuzzer: no WebPAnimEncoderAssemble check w/nallocfuzz
|
||||
6be9bf8b animencoder_fuzzer: fix leak on alloc failure
|
||||
5c965e55 vp8l_dec,cosmetics: add some /*param=*/ comments
|
||||
e4fc2f78 webp-lossless-bitstream-spec: add validity note for max_symbol
|
||||
71916726 webp-lossless-bitstream-spec: fix max_symbol definition
|
||||
eac3bd5c Have the palette code be in its own file.
|
||||
e2c85878 Add an initializer for the SharpYuvOptions struct.
|
||||
4222b006 Merge tag 'v1.3.1'
|
||||
25d94f47 Implement more transfer functions in libsharpyuv
|
||||
2153a679 Merge changes Id0300937,I5dba5ccf,I57bb68e0,I2dba7b4e,I172aca36, ... into main
|
||||
4298e976 webp-lossless-bitstream-spec: add PredictorTransformOutput
|
||||
cd7e02be webp-lossless-bitstream-spec: fix RIFF-header ABNF
|
||||
6c3845f9 webp-lossless-bitstream-spec: split LZ77 Backward Ref section
|
||||
7f1b6799 webp-lossless-bitstream-spec: split Meta Prefix Codes section
|
||||
7b634d8f webp-lossless-bitstream-spec: note transform order
|
||||
6d6d4915 webp-lossless-bitstream-spec: update transformations text
|
||||
fd7bb21c update ChangeLog (tag: v1.3.1-rc2, tag: v1.3.1)
|
||||
e1adea50 update NEWS
|
||||
6b1c722a lossless_common.h,cosmetics: fix a typo
|
||||
08d60d60 webp-lossless-bitstream-spec: split code length section
|
||||
7a12afcc webp-lossless-bitstream-spec: rm unused anchor
|
||||
43393320 enc/*: normalize WebPEncodingSetError() calls
|
||||
287fdefe enc/*: add missing WebPEncodingSetError() calls
|
||||
c3bd7cff EncodeAlphaInternal: add missing error check
|
||||
14a9dbfb webp-lossless-bitstream-spec: refine single node text
|
||||
64819c7c Implement ExtractGreen_SSE2
|
||||
d49cfbb3 vp8l_enc,WriteImage: add missing error check
|
||||
2e5a9ec3 muxread,MuxImageParse: add missing error checks
|
||||
ebb6f949 cmake,emscripten: explicitly set stack size
|
||||
59a2b1f9 WebPDecodeYUV: check u/v/stride/uv_stride ptrs
|
||||
8e965ccb Call png_get_channels() to see if image has alpha
|
||||
fe80fbbd webp-container-spec: add some missing commas
|
||||
e8ed3176 Merge "treat FILTER_NONE as a regular Unfilter[] call" into main
|
||||
03a7a048 webp-lossless-bitstream-spec: rm redundant statement
|
||||
c437c7aa webp-lossless-bitstream-spec: mv up prefix code group def
|
||||
e4f17a31 webp-lossless-bitstream-spec: fix section reference
|
||||
e2ecd5e9 webp-lossless-bitstream-spec: clarify ABNF syntax
|
||||
8b55425a webp-lossless-bitstream-spec: refine pixel copy text
|
||||
29c9f2d4 webp-lossless-bitstream-spec: minor wording updates
|
||||
6b02f660 treat FILTER_NONE as a regular Unfilter[] call
|
||||
7f75c91c webp-container-spec: fix location of informative msg
|
||||
f6499943 webp-container-spec: consistently quote FourCCs
|
||||
49918af3 webp-container-spec: minor wording updates
|
||||
7f0a3419 update ChangeLog (tag: v1.3.1-rc1)
|
||||
bab7efbe update NEWS
|
||||
7138bf8f bump version to 1.3.1
|
||||
435b4ded update AUTHORS
|
||||
47351229 update .mailmap
|
||||
46bc4fc9 Merge "Switch ExtraCost to ints and implement it in SSE." into main
|
||||
828b4ce0 Switch ExtraCost to ints and implement it in SSE.
|
||||
ff6c7f4e CONTRIBUTING.md: add C style / cmake-format notes
|
||||
dd530437 add .cmake-format.py
|
||||
adbe2cb1 cmake,cosmetics: apply cmake-format
|
||||
15b36508 doc/webp-container-spec: rm future codec comment
|
||||
c369c4bf doc/webp-lossless-bitstream-spec: improve link text
|
||||
1de35f47 doc/webp-container-spec: don't use 'currently'
|
||||
bb06a16e doc/webp-container-spec: prefer present tense
|
||||
9f38b71e doc/webp-lossless-bitstream-spec: prefer present tense
|
||||
7acb6b82 doc/webp-container-spec: avoid i.e. & e.g.
|
||||
4967e7cd doc/webp-lossless-bitstream-spec: avoid i.e. & e.g.
|
||||
e3366659 Merge "Do not find_package image libraries if not needed." into main
|
||||
428588ef clarify single leaf node trees and use of canonical prefix coding
|
||||
709ec152 Do not find_package image libraries if not needed.
|
||||
8dd80ef8 fuzz_utils.h: lower kFuzzPxLimit w/ASan
|
||||
8f187b9f Clean message calls in CMake
|
||||
cba30078 WebPConfig.cmake.in: use calculated include path
|
||||
6cf9a76a Merge "webp-lossless-bitstream-spec: remove use of 'dynamics'" into main
|
||||
740943b2 Merge "Specialize and optimize ITransform_SSE2 using do_two" into main
|
||||
2d547e24 Compare kFuzzPxLimit to max_num_operations
|
||||
ac42dde1 Specialize and optimize ITransform_SSE2 using do_two
|
||||
17e0ef1d webp-lossless-bitstream-spec: remove use of 'dynamics'
|
||||
ed274371 neon.h,cosmetics: clear a couple lint warnings
|
||||
3fb82947 cpu.h,cosmetics: segment defines
|
||||
0c496a4f cpu.h: add WEBP_AARCH64
|
||||
8151f388 move VP8GetCPUInfo declaration to cpu.c
|
||||
916548c2 Make kFuzzPxLimit sanitizer dependent
|
||||
4070b271 advanced_api_fuzzer: reduce scaling limit
|
||||
761f49c3 Merge "webp-lossless-bitstream-spec: add missing bits to ABNF" into main
|
||||
84d04c48 webp-lossless-bitstream-spec: add missing bits to ABNF
|
||||
0696e1a7 advanced_api_fuzzer: reduce scaling limit
|
||||
93d88aa2 Merge "deps.cmake: remove unneeded header checks" into main
|
||||
118e0035 deps.cmake: remove unneeded header checks
|
||||
4c3d7018 webp-lossless-bitstream-spec: condense normal-prefix-code
|
||||
a6a09b32 webp-lossless-bitstream-spec: fix 2 code typos
|
||||
50ac4f7c Merge "cpu.h: enable NEON w/_M_ARM64EC" into main
|
||||
4b7d7b4f Add contribution instructions
|
||||
0afbd97b cpu.h: enable NEON w/_M_ARM64EC
|
||||
349f4353 Merge changes Ibd89e56b,Ic57e7f84,I89096614 into main
|
||||
8f7513b7 upsampling_neon.c: fix WEBP_SWAP_16BIT_CSP check
|
||||
cbf624b5 advanced_api_fuzzer: reduce scaling limit
|
||||
89edfdd1 Skip slow scaling in libwebp advanced_api_fuzzer
|
||||
859f19f7 Reduce libwebp advanced_api_fuzzer threshold
|
||||
a4f04835 Merge changes Ic389aaa2,I329ccd79 into main
|
||||
1275fac8 Makefile.vc: fix img2webp link w/dynamic cfg
|
||||
2fe27bb9 img2webp: normalize help output
|
||||
24bed3d9 cwebp: reflow -near_lossless help text
|
||||
0825faa4 img2webp: add -sharp_yuv/-near_lossless
|
||||
d64e6d7d Merge "PaletteSortModifiedZeng: fix leak on error" into main
|
||||
0e12a22d Merge "EncodeAlphaInternal: clear result->bw on error" into main
|
||||
0edbb6ea PaletteSortModifiedZeng: fix leak on error
|
||||
41ffe04e Merge "Update yapf style from "chromium" to "yapf"" into main
|
||||
2d9d9265 Update yapf style from "chromium" to "yapf"
|
||||
a486d800 EncodeAlphaInternal: clear result->bw on error
|
||||
1347a32d Skip big scaled advanced_api_fuzzer
|
||||
52b6f067 Fix scaling limit in advanced_api_fuzzer.c
|
||||
73618428 Limit scaling in libwebp advanced_api_fuzzer.c
|
||||
b54d21a0 Merge "CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty" into main
|
||||
31c28db5 libwebp{,demux,mux}.pc.in: Requires -> Requires.private
|
||||
d9a505ff CMakeLists.txt: allow CMAKE_INSTALL_RPATH to be set empty
|
||||
bdf33d03 Merge tag 'v1.3.0'
|
||||
b5577769 update ChangeLog (tag: v1.3.0-rc1, tag: v1.3.0)
|
||||
0ba77244 update NEWS
|
||||
e763eb1e bump version to 1.3.0
|
||||
2a8686fc update AUTHORS
|
||||
106a57c1 Merge "*/Android.mk: add a check for NDK_ROOT" into main
|
||||
c5e841c4 Merge "extras: WebpToSDL -> WebPToSDL" into main
|
||||
dbc30715 Merge "xcframeworkbuild.sh: bump MACOSX_CATALYST_MIN_VERSION" into main
|
||||
6fc1a9f9 */Android.mk: add a check for NDK_ROOT
|
||||
d3e151fc doc/api.md,webp_js/README.md: Webp -> WebP
|
||||
ed92a626 extras: WebpToSDL -> WebPToSDL
|
||||
6eb0189b xcframeworkbuild.sh: bump MACOSX_CATALYST_MIN_VERSION
|
||||
1d58575b CMake: align .pc variables with autoconf
|
||||
e5fe2cfc webp-lossless-bitstream-spec,cosmetics: reflow paragraphs
|
||||
0ceeeab9 webp-lossless-bitstream-spec: add amendment note
|
||||
607611cd Merge "webp-container-spec: normalize section title case" into main
|
||||
f853685e lossless: SUBTRACT_GREEN -> SUBTRACT_GREEN_TRANSFORM
|
||||
786497e4 webp-lossless-bitstream-spec: fix inv color txfm description
|
||||
c6ac672d webp-lossless-bitstream-spec: fix num_code_lengths check
|
||||
b5700efb webp-lossless-bitstream-spec,cosmetics: grammar/capitalization
|
||||
d8ed8c11 webp-container-spec: normalize section title case
|
||||
52ec0b8f Merge changes Ie975dbb5,Ifc8c93af,I6ca7c5d6,I2e8d66f5,I152477b8 into main
|
||||
5097ef62 webp-container-spec,cosmetics: grammar/capitalization
|
||||
e3ba2b1f webp-lossless-bitstream-spec,cosmetics: reflow abstract
|
||||
1e8e3ded webp-lossless-bitstream-spec: reword abstract re alpha
|
||||
017cb6fa webp-container-spec,cosmetics: normalize range syntax
|
||||
f6a4684b webp-lossless-bitstream-spec,cosmetics: normalize range syntax
|
||||
54ebd5a3 webp-lossless-bitstream-spec: limit dist map lut to 69 cols
|
||||
44741f9c webp-lossless-bitstream-spec: fix dist mapping example
|
||||
fad0ece7 pnmdec.c: use snprintf instead of sprintf
|
||||
3f73e8f7 sharpyuv: add SharpYuvGetVersion()
|
||||
ce2f2d66 SharpYuvConvert: fix a race on SharpYuvGetCPUInfo
|
||||
a458e308 sharpyuv_dsp.h: restore sharpyuv_cpu.h include
|
||||
9ba800a7 Merge changes Id72fbf3b,Ic59d23a2 into main
|
||||
979c0ebb sharpyuv: add SharpYuvGetCPUInfo
|
||||
8bab09a4 Merge "*.pc.in: rename lib_prefix to webp_libname_prefix" into main
|
||||
769387c5 cpu.c,cosmetics: fix a typo
|
||||
a02978c2 sharpyuv/Makefile.am+cmake: add missing -lm
|
||||
28aedcb9 *.pc.in: rename lib_prefix to webp_libname_prefix
|
||||
c42e6d5a configure.ac: export an empty lib_prefix variable
|
||||
dfc843aa Merge "*.pc.in: add lib prefix to lib names w/MSVC" into main
|
||||
2498209b *.pc.in: add lib prefix to lib names w/MSVC
|
||||
ac252b61 Merge "analysis_enc.c: fix a dead store warning" into main
|
||||
56944762 analysis_enc.c: fix a dead store warning
|
||||
d34f9b99 Merge "webp-lossless-bitstream-spec: convert BNF to ABNF" into main
|
||||
dc05b4db Merge changes I96bc063c,I45880467,If9e18e5a,I6ee938e4,I0a410b28, ... into main
|
||||
83270c7f webp-container-spec: add prose for rendering process
|
||||
73b19b64 webp-container-spec: note reserved fields MUST be ignored
|
||||
57101d3f webp-lossless-bitstream-spec: improve 'small' color table stmt
|
||||
dfd32e45 webp-container-spec: remove redundant sentence
|
||||
8a6185dd doc/webp-*: fix some punctuation, grammar
|
||||
72776530 webp-lossless-bitstream-spec: convert BNF to ABNF
|
||||
d992bb08 cmake: rename cpufeatures target to cpufeatures-webp
|
||||
3ed2b275 webp-container-spec: clarify background color note
|
||||
951c292d webp-container-spec: come too late -> out of order
|
||||
902dd787 webp-container-spec: prefer hex literals
|
||||
a8f6b5ee webp-container-spec: change SHOULD to MUST w/ANIM chunk
|
||||
1dc59435 webp-container-spec: add unknown fields MUST be ignored
|
||||
280a810f webp-container-spec: make padding byte=0 a MUST
|
||||
41f0bf68 webp-container-spec: update note on trailing data
|
||||
6bdd36db webp-container-spec: clarify Chunk Size is in bytes
|
||||
87e36c48 Merge "webp_js/README.md,cosmetics: reflow some lines" into main
|
||||
5b01f321 Merge "Update Windows makefile to build libsharpyuv library." into main
|
||||
19b1a71c webp_js/README.md,cosmetics: reflow some lines
|
||||
780db756 Update Windows makefile to build libsharpyuv library.
|
||||
e407d4b3 CMakeLists.txt: replace GLUT_glut_LIBRARY w/GLUT::GLUT
|
||||
abf73d62 Merge "WebPConfig.cmake.in: add find_dependency(Threads)" into main
|
||||
25807fb4 Merge "cmake: restore compatibility with cmake < 3.12" into main
|
||||
5dbc4bfa WebPConfig.cmake.in: add find_dependency(Threads)
|
||||
b2a175dd Merge "Update wasm instructions." into main
|
||||
cb90f76b Update wasm instructions.
|
||||
02d15258 cmake: restore compatibility with cmake < 3.12
|
||||
5ba046e2 CMake: add_definitions -> add_compile_options
|
||||
e68765af dsp,neon: use vaddv in a few more places
|
||||
e8f83de2 Set libsharpyuv include dir to 'webp' subdirectory.
|
||||
15a91ab1 cmake,cosmetics: apply cmake-format
|
||||
0dd49d1a CMakeLists.txt: set @ONLY in configure_file() calls
|
||||
62b1bfe8 Merge changes I2877e7bb,I777cad70,I15af7d1a,I686e6740,If10538a9, ... into main
|
||||
95c8fe5f Merge changes Iecea3603,I9dc228ab into main
|
||||
e7c805cf picture_csp_enc.c: remove SafeInitSharpYuv
|
||||
6af8845a sharpyuv: prefer webp/types.h
|
||||
639619ce cmake: fix dll exports
|
||||
782ed48c sharpyuv,SharpYuvInit: add mutex protection when available
|
||||
cad0d5ad sharyuv_{neon,sse2}.c: merge WEBP_USE_* sections
|
||||
ef70ee06 add a few missing <stddef.h> includes for NULL
|
||||
f0f9eda4 sharpyuv.h: remove <inttypes.h>
|
||||
9b902cba Merge "picture_csp_enc.c,CheckNonOpaque: rm unneeded local" into main
|
||||
9c1d457c cmake/cpu.cmake: remove unused variable
|
||||
9ac25bcb CMakeLists.txt,win32: match naming convention used by nmake
|
||||
76c353ba picture_csp_enc.c,CheckNonOpaque: rm unneeded local
|
||||
5000de54 Merge "cwebp: fix WebPPictureHasTransparency call" into main
|
||||
e1729309 Merge "WebPPictureHasTransparency: add missing pointer check" into main
|
||||
00ff988a vp8l_enc,AddSingleSubGreen: clear int sanitizer warnings
|
||||
e2fecc22 dsp/lossless_enc.c: clear int sanitizer warnings
|
||||
129cf9e9 dsp/lossless.c: clear int sanitizer warnings
|
||||
ad7d1753 dsp/lossless_enc.c: clear int sanitizer warnings
|
||||
5037220e VP8LSubtractGreenFromBlueAndRed_C: clear int sanitizer warnings
|
||||
2ee786c7 upsampling_sse2.c: clear int sanitizer warnings
|
||||
4cc157d4 ParseOptionalChunks: clear int sanitizer warning
|
||||
892cf033 BuildHuffmanTable: clear int sanitizer warning
|
||||
3a9a4d45 VP8GetSigned: clear int sanitizer warnings
|
||||
704a3d0a dsp/lossless.c: quiet int sanitizer warnings
|
||||
1a6c109c WebPPictureHasTransparency: add missing pointer check
|
||||
c626e7d5 cwebp: fix WebPPictureHasTransparency call
|
||||
866e349c Merge tag 'v1.2.4'
|
||||
c170df38 Merge "Create libsharpyuv.a in makefile.unix." into main
|
||||
9d7ff74a Create libsharpyuv.a in makefile.unix.
|
||||
0d1f1254 update ChangeLog (tag: v1.2.4)
|
||||
fcbc2d78 Merge "doc/*.txt: restrict code to 69 columns" into main
|
||||
4ad0e189 Merge "webp-container-spec.txt: normalize fourcc spelling" into main
|
||||
980d2488 update NEWS
|
||||
9fde8127 bump version to 1.2.4
|
||||
7a0a9935 doc/*.txt: restrict code to 69 columns
|
||||
c040a615 webp-container-spec.txt: normalize fourcc spelling
|
||||
aff1c546 dsp,x86: normalize types w/_mm_cvtsi128_si32 calls
|
||||
ab540ae0 dsp,x86: normalize types w/_mm_cvtsi32_si128 calls
|
||||
8980362e dsp,x86: normalize types w/_mm_set* calls (2)
|
||||
e626925c lossless: fix crunch mode w/WEBP_REDUCE_SIZE
|
||||
83539239 dsp,x86: normalize types w/_mm_set* calls
|
||||
8a4576ce webp-container-spec.txt: replace & with &
|
||||
db870881 Merge "webp-container-spec.txt: make reserved 0 values a MUST" into main
|
||||
01d7d378 webp-lossless-bitstream-spec: number all sections
|
||||
337cf69f webp-lossless-bitstream-spec: mv Nomenclature after Intro
|
||||
79be856e Merge changes I7111d1f7,I872cd62c into main
|
||||
5b87983a webp-container-spec.txt: make reserved 0 values a MUST
|
||||
bd939123 Merge changes I7a25b1a6,I51b2c2a0,I87d0cbcf,I6ec60af6,I0a3fe9dc into main
|
||||
04764b56 libwebp.pc: add libsharpyuv to requires
|
||||
7deee810 libsharpyuv: add pkg-config file
|
||||
1a64a7e6 webp-container-spec.txt: clarify some SHOULDs
|
||||
bec2c88a webp-container-spec.txt: move ChunkHeader to terminology
|
||||
c9359332 webp-container-spec.txt: clarify 'VP8 '/'XMP ' fourccs
|
||||
70fe3063 webp-container-spec.txt: rightsize table entries
|
||||
ddbf3f3f webp-container-spec.txt: update 'key words' text
|
||||
c151e95b utils.h,WEBP_ALIGN: make bitmask unsigned
|
||||
748e92bb add WebPInt32ToMem
|
||||
3fe15b67 Merge "Build libsharpyuv as a full installable library." into main
|
||||
4f402f34 add WebPMemToInt32
|
||||
a3b68c19 Build libsharpyuv as a full installable library.
|
||||
b4994eaa CMake: set rpath for shared objects
|
||||
94cd7117 Merge "CMake: fix dylib versioning" into main
|
||||
e91451b6 Fix the lossless specs a bit more.
|
||||
231bdfb7 CMake: fix dylib versioning
|
||||
bfad7ab5 CMakeLists.txt: correct libwebpmux name in WebPConfig.cmake
|
||||
c2e3fd30 Revert "cmake: fix webpmux lib name for cmake linking"
|
||||
7366f7f3 Merge "lossless: fix crunch mode w/WEBP_REDUCE_SIZE" into main
|
||||
84163d9d lossless: fix crunch mode w/WEBP_REDUCE_SIZE
|
||||
d01c1eb3 webp-lossless-bitstream-spec,cosmetics: normalize capitalization
|
||||
8813ca8e Merge tag 'v1.2.3'
|
||||
3c4a0fbf update ChangeLog (tag: v1.2.3)
|
||||
56a480e8 dsp/cpu.h: add missing extern "C"
|
||||
62b45bdd update ChangeLog (tag: v1.2.3-rc1)
|
||||
8764ec7a Merge changes Idb037953,Id582e395 into 1.2.3
|
||||
bcb872c3 vwebp: fix file name display in windows unicode build
|
||||
67c44ac5 webpmux: fix -frame option in windows unicode build
|
||||
8278825a makefile.unix: add sharpyuv objects to clean target
|
||||
14a49e01 update NEWS
|
||||
34b1dc33 bump version to 1.2.3
|
||||
0b397fda update AUTHORS
|
||||
c16488ac update .mailmap
|
||||
5a2d929c Merge "unicode.h: set console mode before using wprintf" into main
|
||||
169f867f unicode.h: set console mode before using wprintf
|
||||
a94b855c Merge "libsharpyuv: add version defines" into main
|
||||
f83bdb52 libsharpyuv: add version defines
|
||||
bef0d797 unicode_gif.h: fix -Wdeclaration-after-statement
|
||||
404c1622 Rename Huffman coding to prefix coding in the bitstream spec
|
||||
8895f8a3 Merge "run_static_analysis.sh: fix scan-build archive path" into main
|
||||
92a673d2 Merge "Add -fvisibility=hidden flag in CMakeLists." into main
|
||||
67c1d722 Merge "add WEBP_MSAN" into main
|
||||
1124ff66 Add -fvisibility=hidden flag in CMakeLists.
|
||||
e15b3560 add WEBP_MSAN
|
||||
ec9e782a sharpyuv: remove minimum image size from sharpyuv library
|
||||
7bd07f3b run_static_analysis.sh: fix scan-build archive path
|
||||
5ecee06f Merge "sharpyuv: increase precision of gamma<->linear conversion" into main
|
||||
f81dd7d6 Merge changes I3d17d529,I53026880,I1bd61639,I6bd4b25d,Icfec8fba into main
|
||||
2d607ee6 sharpyuv: increase precision of gamma<->linear conversion
|
||||
266cbbc5 sharpyuv: add 32bit version of SharpYuvFilterRow.
|
||||
9fc12274 CMake: add src to webpinfo includes
|
||||
7d18f40a CMake: add WEBP_BUILD_WEBPINFO to list of checks for exampleutil
|
||||
11309aa5 CMake: add WEBP_BUILD_WEBPMUX to list of checks for exampleutil
|
||||
4bc762f7 CMake: link imageioutil to exampleutil after defined
|
||||
0d1b9bc4 WEBP_DEP_LIBRARIES: use Threads::Threads
|
||||
20ef48f0 Merge "sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv." into main
|
||||
93c54371 sharpyuv: add support for 10/12/16 bit rgb and 10/12 bit yuv.
|
||||
53cf2b49 normalize WebPValidatePicture declaration w/definition
|
||||
d3006f4b sharpyuv: slightly improve precision
|
||||
ea967098 Merge changes Ia01bd397,Ibf3771af into main
|
||||
11bc8410 Merge changes I2d317c4b,I9e77f6db into main
|
||||
30453ea4 Add an internal WebPValidatePicture.
|
||||
6c43219a Some renamings for consistency.
|
||||
4f59fa73 update .mailmap
|
||||
e74f8a62 webp-lossless-bitstream-spec,cosmetics: normalize range syntax
|
||||
5a709ec0 webp-lossless-bitstream-spec,cosmetics: fix code typo
|
||||
a2093acc webp-lossless-bitstream-spec: add amendment note
|
||||
86c66930 webp-lossless-bitstream-spec: fix BNF
|
||||
232f22da webp-lossless-bitstream-spec: fix 'simple code' snippet
|
||||
44dd765d webp-lossless-bitstream-spec: fix ColorTransform impl
|
||||
7a7e33e9 webp-lossless-bitstream-spec: fix TR-pixel right border note
|
||||
86f94ee0 Update lossless spec with Huffman codes.
|
||||
a3927cc8 sharpyuv.c,cosmetics: fix indent
|
||||
6c45cef7 Make sure the stride has a minimum value in the importer.
|
||||
0c8b0e67 sharpyuv: cleanup/cosmetic changes
|
||||
dc3841e0 {histogram,predictor}_enc: quiet int -> float warnings
|
||||
a19a25bb Replace doubles by floats in lossless misc cost estimations.
|
||||
42888f6c Add an option to enable static builds.
|
||||
7efcf3cc Merge "Fix typo in color constants: Marix -> Matrix" into main
|
||||
8f4b5c62 Fix typo in color constants: Marix -> Matrix
|
||||
90084d84 Merge "demux,IsValidExtendedFormat: remove unused variable" into main
|
||||
ed643f61 Merge changes I452d2485,Ic6d75475 into main
|
||||
8fa053d1 Rename SharpYUV to SharpYuv for consistency.
|
||||
99a87562 SharpYuvComputeConversionMatrix: quiet int->float warnings
|
||||
deb426be Makefile.vc: add sharpyuv_csp.obj to SHARPYUV_OBJS
|
||||
779597d4 demux,IsValidExtendedFormat: remove unused variable
|
||||
40e8aa57 Merge "libsharpyuv: add colorspace utilities" into main
|
||||
01a05de1 libsharpyuv: add colorspace utilities
|
||||
2de4b05a Merge changes Id9890a60,I376d81e6,I1c958838 into main
|
||||
b8bca81f Merge "configure.ac: use LT_INIT if available" into main
|
||||
e8e77b9c Merge changes I479bc487,I39864691,I5d486c2c,I186d13be into main
|
||||
7e7d5d50 Merge ".gitignore: add Android Studio & VS code dirs" into main
|
||||
10c50848 normalize label indent
|
||||
89f774e6 mux{edit,internal}: fix leaks on error
|
||||
2d3293ad ExUtilInitCommandLineArguments: fix leak on error
|
||||
ec34fd70 anim_util: fix leaks on error
|
||||
e4717287 gif2webp: fix segfault on OOM
|
||||
e3cfafaf GetBackwardReferences: fail on alloc error
|
||||
a828a59b BackwardReferencesHashChainDistanceOnly: fix segfault on OOM
|
||||
fe153fae VP8LEncodeStream: fix segfault on OOM
|
||||
919acc0e .gitignore: add Android Studio & VS code dirs
|
||||
efa0731b configure.ac: use LT_INIT if available
|
||||
0957fd69 tiffdec: add grayscale support
|
||||
e685feef Merge "Make libsharpyuv self-contained by removing dependency on cpu.c" into main
|
||||
841960b6 Make libsharpyuv self-contained by removing dependency on cpu.c
|
||||
617cf036 image_dec: add WebPGetEnabledInputFileFormats()
|
||||
7a68afaa Let SharpArgbToYuv caller pass in an RGB>YUV conversion matrix.
|
||||
34bb332c man/cwebp.1: add note about crop/resize order
|
||||
f0e9351c webp-lossless-bitstream-spec,cosmetics: fix some typos
|
||||
5ccbd6ed vp8l_dec.c,cosmetics: fix a few typos
|
||||
c3d0c2d7 fix ios build scripts after sharpyuv dep added
|
||||
d0d2292e Merge "Make libwebp depend on libsharpyuv." into main
|
||||
03d12190 alpha_processing_neon.c: fix 0x01... typo
|
||||
d55d447c Make libwebp depend on libsharpyuv.
|
||||
e4cbcdd2 Fix lossless encoding for MIPS.
|
||||
924e7ca6 alpha_processing_neon.c: fix Dispatch/ExtractAlpha_NEON
|
||||
0fa0ea54 Makefile.vc: use /MANIFEST:EMBED
|
||||
29cc95ce Basic version of libsharpyuv in libwebp, in C.
|
||||
a30f2190 examples/webpmux.c: fix a couple of typos
|
||||
66b3ce23 Fix bad overflow check in ReadTIFF()
|
||||
54e61a38 Markdownify libwebp docs and reorganize them.
|
||||
b4533deb CMakeLists.txt,cosmetics: break long line
|
||||
b9d2f9cd quant_enc.c: use WEBP_RESTRICT qualifier
|
||||
ec178f2c Add progress hook granularity in lossless
|
||||
26139c73 Rename MAX_COST to MAX_BIT_COST in histogram_enc.c
|
||||
13b82816 cmake: fix webpmux lib name for cmake linking
|
||||
88b6a396 webp-container-spec.txt,cosmetics: normalize formatting
|
||||
6f496540 Merge tag 'v1.2.2'
|
||||
4074acf8 dsp.h: bump msvc arm64 version requirement to 16.6
|
||||
b0a86089 update ChangeLog (tag: v1.2.2)
|
||||
6db8248c libwebp: Fix VP8EncTokenLoop() progress
|
||||
827a307f BMP enc: fix the transparency case
|
||||
db25f1b4 libwebp: Fix VP8EncTokenLoop() progress
|
||||
286e7fce libwebp: do not destroy jpeg codec twice on error
|
||||
6e8a4126 libwebp: do not destroy jpeg codec twice on error
|
||||
faf21968 Merge "BMP enc: fix the transparency case" into main
|
||||
480cd51d BMP enc: fix the transparency case
|
||||
9195ea05 update ChangeLog (tag: v1.2.2-rc2)
|
||||
4acae017 update NEWS
|
||||
883f0633 man/img2webp.1: update date
|
||||
567e1f44 Reword img2webp synopsis command line
|
||||
1b0c15db man/img2webp.1: update date
|
||||
17bade38 Merge "Reword img2webp synopsis command line" into main
|
||||
a80954a1 Reword img2webp synopsis command line
|
||||
f084244d anim_decode: fix alpha blending with big-endian
|
||||
b217b4ff webpinfo: fix fourcc comparison w/big-endian
|
||||
ec497b75 Merge "anim_decode: fix alpha blending with big-endian" into main
|
||||
e4886716 anim_decode: fix alpha blending with big-endian
|
||||
e3cb052c webpinfo: fix fourcc comparison w/big-endian
|
||||
a510fedb patch-check: detect duplicated files
|
||||
f035d2e4 update ChangeLog (tag: v1.2.2-rc1)
|
||||
7031946a update NEWS
|
||||
973390b6 bump version to 1.2.2
|
||||
@ -45,7 +539,7 @@ e23cd548 dsp.h: enable NEON w/VS2019+ ARM64 targets
|
||||
42592af8 webp,cmake: Remove unnecessary include dirs
|
||||
e298e05f Add patch-check steps in PRESUBMIT.py
|
||||
29148919 Merge tag 'v1.2.1'
|
||||
9ce5843d update ChangeLog (tag: v1.2.1, origin/1.2.1)
|
||||
9ce5843d update ChangeLog (tag: v1.2.1)
|
||||
d9191588 fuzzer/*: normalize src/ includes
|
||||
c5bc3624 fuzzer/*: normalize src/ includes
|
||||
53b6f762 fix indent
|
||||
@ -224,7 +718,7 @@ a99078c1 remove call to MBAnalyzeBestIntra4Mode for method >= 5
|
||||
6a0ff358 Enc: add a qmin / qmax range for quality factor
|
||||
0fa56f30 Merge tag 'v1.1.0'
|
||||
6cf504d0 PNM decoding: handle max_value != 255
|
||||
d7844e97 update ChangeLog (tag: v1.1.0-rc2, tag: v1.1.0, origin/1.1.0)
|
||||
d7844e97 update ChangeLog (tag: v1.1.0-rc2, tag: v1.1.0)
|
||||
7f006436 Makefile.vc: fix webp_quality.exe link
|
||||
cf047e83 Makefile.vc: fix webp_quality.exe link
|
||||
c074c653 update NEWS
|
||||
@ -869,7 +1363,7 @@ b016cb91 NEON: faster fancy upsampling
|
||||
f04eb376 Merge tag 'v0.5.2'
|
||||
341d711c NEON: 5% faster conversion to RGB565 and RGBA4444
|
||||
abb54827 remove Clang warnings with unused arch arguments.
|
||||
ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2, origin/0.5.2)
|
||||
ece9684f update ChangeLog (tag: v0.5.2-rc2, tag: v0.5.2)
|
||||
aa7744ca anim_util: quiet implicit conv warnings in 32-bit
|
||||
d9120271 jpegdec: correct ContextFill signature
|
||||
24eb3940 Remove some errors when compiling the code as C++.
|
||||
@ -1156,7 +1650,7 @@ bbb6ecd9 Merge "Add MSA optimized distortion functions"
|
||||
c0991a14 io,EmitRescaledAlphaYUV: factor out a common expr
|
||||
48bf5ed1 build.gradle: remove tab
|
||||
bfef6c9f Merge tag 'v0.5.1'
|
||||
3d97bb75 update ChangeLog (tag: v0.5.1, origin/0.5.1)
|
||||
3d97bb75 update ChangeLog (tag: v0.5.1)
|
||||
deb54d91 Clarify the expected 'config' lifespan in WebPIDecode()
|
||||
435308e0 Add MSA optimized encoder transform functions
|
||||
dce64bfa Add MSA optimized alpha filter functions
|
||||
|
@ -1,5 +1,5 @@
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
SUBDIRS = src imageio man
|
||||
SUBDIRS = sharpyuv src imageio man
|
||||
EXTRA_DIST = COPYING autogen.sh
|
||||
|
||||
if BUILD_EXTRAS
|
||||
|
70
Makefile.vc
70
Makefile.vc
@ -5,12 +5,15 @@ LIBWEBPDECODER_BASENAME = libwebpdecoder
|
||||
LIBWEBP_BASENAME = libwebp
|
||||
LIBWEBPMUX_BASENAME = libwebpmux
|
||||
LIBWEBPDEMUX_BASENAME = libwebpdemux
|
||||
LIBSHARPYUV_BASENAME = libsharpyuv
|
||||
|
||||
!IFNDEF ARCH
|
||||
!IF ! [ cl 2>&1 | find "x86" > NUL ]
|
||||
ARCH = x86
|
||||
!ELSE IF ! [ cl 2>&1 | find "x64" > NUL ]
|
||||
ARCH = x64
|
||||
!ELSE IF ! [ cl 2>&1 | find "ARM64" > NUL ]
|
||||
ARCH = ARM64
|
||||
!ELSE IF ! [ cl 2>&1 | find "ARM" > NUL ]
|
||||
ARCH = ARM
|
||||
!ELSE
|
||||
@ -31,12 +34,11 @@ CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
|
||||
CCDEBUG = cl.exe $(NOLOGO) /Od /Zi /D_DEBUG /RTC1
|
||||
CFLAGS = /I. /Isrc $(NOLOGO) /W3 /EHsc /c
|
||||
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
|
||||
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
|
||||
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST:EMBED /NXCOMPAT /DYNAMICBASE
|
||||
LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS)
|
||||
LNKDLL = link.exe /DLL $(NOLOGO)
|
||||
LNKEXE = link.exe $(NOLOGO)
|
||||
LNKLIB = lib.exe $(NOLOGO)
|
||||
MT = mt.exe $(NOLOGO)
|
||||
RCNODBG = rc.exe $(NOLOGO) /l"0x0409" # 0x409 = U.S. English
|
||||
RCDEBUG = $(RCNODBG) /D_DEBUG
|
||||
|
||||
@ -82,6 +84,7 @@ OUTPUT_DIRS = $(DIRBIN) $(DIRINC) $(DIRLIB) \
|
||||
$(DIROBJ)\extras \
|
||||
$(DIROBJ)\imageio \
|
||||
$(DIROBJ)\mux \
|
||||
$(DIROBJ)\sharpyuv \
|
||||
$(DIROBJ)\utils \
|
||||
|
||||
# Target configuration
|
||||
@ -96,6 +99,7 @@ LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
|
||||
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
|
||||
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
|
||||
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
||||
LIBSHARPYUV_BASENAME = $(LIBSHARPYUV_BASENAME)_debug
|
||||
!ELSE IF "$(CFG)" == "release-dynamic"
|
||||
CC = $(CCNODBG)
|
||||
RC = $(RCNODBG)
|
||||
@ -109,6 +113,7 @@ LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
|
||||
LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug
|
||||
LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
|
||||
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
||||
LIBSHARPYUV_BASENAME = $(LIBSHARPYUV_BASENAME)_debug
|
||||
!ENDIF
|
||||
|
||||
!IF "$(STATICLIBBUILD)" == "TRUE"
|
||||
@ -118,13 +123,14 @@ LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME).lib
|
||||
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib
|
||||
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME).lib
|
||||
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib
|
||||
LIBSHARPYUV = $(DIRLIB)\$(LIBSHARPYUV_BASENAME).lib
|
||||
!ELSE IF "$(DLLBUILD)" == "TRUE"
|
||||
DLLINC = webp_dll.h
|
||||
CC = $(CC) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL
|
||||
CC = $(CC) /I$(DIROBJ) $(RTLIB) /DWEBP_DLL
|
||||
LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib
|
||||
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib
|
||||
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib
|
||||
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME)_dll.lib
|
||||
LIBSHARPYUV = $(DIRLIB)\$(LIBSHARPYUV_BASENAME)_dll.lib
|
||||
LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
|
||||
CFGSET = TRUE
|
||||
!ENDIF
|
||||
@ -174,6 +180,15 @@ CFLAGS = $(CFLAGS) /D_UNICODE /DUNICODE
|
||||
# A config was provided, so the library can be built.
|
||||
#
|
||||
|
||||
SHARPYUV_OBJS = \
|
||||
$(DIROBJ)\sharpyuv\sharpyuv.obj \
|
||||
$(DIROBJ)\sharpyuv\sharpyuv_cpu.obj \
|
||||
$(DIROBJ)\sharpyuv\sharpyuv_csp.obj \
|
||||
$(DIROBJ)\sharpyuv\sharpyuv_dsp.obj \
|
||||
$(DIROBJ)\sharpyuv\sharpyuv_gamma.obj \
|
||||
$(DIROBJ)\sharpyuv\sharpyuv_neon.obj \
|
||||
$(DIROBJ)\sharpyuv\sharpyuv_sse2.obj \
|
||||
|
||||
DEC_OBJS = \
|
||||
$(DIROBJ)\dec\alpha_dec.obj \
|
||||
$(DIROBJ)\dec\buffer_dec.obj \
|
||||
@ -308,6 +323,7 @@ ENC_OBJS = \
|
||||
EXTRAS_OBJS = \
|
||||
$(DIROBJ)\extras\extras.obj \
|
||||
$(DIROBJ)\extras\quality_estimate.obj \
|
||||
$(DIROBJ)\extras\sharpyuv_risk_table.obj \
|
||||
|
||||
IMAGEIO_UTIL_OBJS = \
|
||||
$(DIROBJ)\imageio\imageio_util.obj \
|
||||
@ -323,6 +339,7 @@ UTILS_DEC_OBJS = \
|
||||
$(DIROBJ)\utils\color_cache_utils.obj \
|
||||
$(DIROBJ)\utils\filters_utils.obj \
|
||||
$(DIROBJ)\utils\huffman_utils.obj \
|
||||
$(DIROBJ)\utils\palette.obj \
|
||||
$(DIROBJ)\utils\quant_levels_dec_utils.obj \
|
||||
$(DIROBJ)\utils\rescaler_utils.obj \
|
||||
$(DIROBJ)\utils\random_utils.obj \
|
||||
@ -335,12 +352,13 @@ UTILS_ENC_OBJS = \
|
||||
$(DIROBJ)\utils\quant_levels_utils.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)
|
||||
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)
|
||||
LIBSHARPYUV_OBJS = $(SHARPYUV_OBJS)
|
||||
|
||||
OUT_LIBS = $(LIBWEBPDECODER) $(LIBWEBP)
|
||||
OUT_LIBS = $(LIBWEBPDECODER) $(LIBWEBP) $(LIBSHARPYUV)
|
||||
!IF "$(ARCH)" == "ARM"
|
||||
ex: $(OUT_LIBS)
|
||||
all: ex
|
||||
@ -368,7 +386,7 @@ $(DIRBIN)\anim_dump.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
|
||||
$(DIRBIN)\anim_dump.exe: $(IMAGEIO_ENC_OBJS)
|
||||
$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(IMAGEIO_DEC_OBJS)
|
||||
$(DIRBIN)\cwebp.exe: $(IMAGEIO_UTIL_OBJS)
|
||||
$(DIRBIN)\cwebp.exe: $(LIBWEBPDEMUX)
|
||||
$(DIRBIN)\cwebp.exe: $(LIBWEBPDEMUX) $(LIBSHARPYUV)
|
||||
$(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS)
|
||||
$(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS)
|
||||
$(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_OBJS)
|
||||
@ -386,7 +404,7 @@ $(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
|
||||
$(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX)
|
||||
$(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS)
|
||||
$(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
|
||||
$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
|
||||
$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP) $(LIBSHARPYUV)
|
||||
$(DIRBIN)\get_disto.exe: $(DIROBJ)\extras\get_disto.obj
|
||||
$(DIRBIN)\get_disto.exe: $(IMAGEIO_DEC_OBJS) $(IMAGEIO_UTIL_OBJS)
|
||||
$(DIRBIN)\get_disto.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
|
||||
@ -409,17 +427,16 @@ $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS): $(OUTPUT_DIRS)
|
||||
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(EXTRAS_OBJS): $(OUTPUT_DIRS)
|
||||
!ENDIF # ARCH == ARM
|
||||
|
||||
$(LIBSHARPYUV): $(LIBSHARPYUV_OBJS)
|
||||
$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS)
|
||||
$(LIBWEBP): $(LIBWEBP_OBJS)
|
||||
$(LIBWEBP): $(LIBWEBP_OBJS) $(LIBSHARPYUV)
|
||||
$(LIBWEBPMUX): $(LIBWEBPMUX_OBJS)
|
||||
$(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS)
|
||||
|
||||
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): $(OUTPUT_DIRS)
|
||||
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS) $(LIBSHARPYUV_OBJS): \
|
||||
$(OUTPUT_DIRS)
|
||||
|
||||
!IF "$(DLLBUILD)" == "TRUE"
|
||||
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): \
|
||||
$(DIROBJ)\$(DLLINC)
|
||||
|
||||
{$(DIROBJ)}.c{$(DIROBJ)}.obj:
|
||||
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
|
||||
|
||||
@ -429,20 +446,20 @@ $(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): \
|
||||
$(RC) /fo$@ $<
|
||||
{src\mux}.rc{$(DIROBJ)\mux}.res:
|
||||
$(RC) /fo$@ $<
|
||||
{sharpyuv}.rc{$(DIROBJ)\sharpyuv}.res:
|
||||
$(RC) /fo$@ $<
|
||||
|
||||
$(LIBWEBP): $(DIROBJ)\$(LIBWEBP_BASENAME:_debug=).res
|
||||
$(LIBSHARPYUV): $(DIROBJ)\sharpyuv\$(LIBSHARPYUV_BASENAME:_debug=).res
|
||||
$(LIBWEBP): $(LIBSHARPYUV) $(DIROBJ)\$(LIBWEBP_BASENAME:_debug=).res
|
||||
$(LIBWEBPDECODER): $(DIROBJ)\$(LIBWEBPDECODER_BASENAME:_debug=).res
|
||||
$(LIBWEBPMUX): $(LIBWEBP) $(DIROBJ)\mux\$(LIBWEBPMUX_BASENAME:_debug=).res
|
||||
$(LIBWEBPDEMUX): $(LIBWEBP) $(DIROBJ)\demux\$(LIBWEBPDEMUX_BASENAME:_debug=).res
|
||||
|
||||
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
||||
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX) $(LIBSHARPYUV):
|
||||
$(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $**
|
||||
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
|
||||
|
||||
clean::
|
||||
@-erase /s $(DIROBJ)\$(DLLINC) 2> NUL
|
||||
!ELSE
|
||||
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
||||
$(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX) $(LIBSHARPYUV):
|
||||
$(LNKLIB) /out:$@ $**
|
||||
-xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y
|
||||
!ENDIF
|
||||
@ -450,13 +467,6 @@ $(LIBWEBPDECODER) $(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX):
|
||||
$(OUTPUT_DIRS):
|
||||
@if not exist "$(@)" mkdir "$(@)"
|
||||
|
||||
# generate a helper include to define WEBP_EXTERN suitable for the DLL build
|
||||
$(DIROBJ)\$(DLLINC):
|
||||
@echo #ifndef WEBP_DLL_H_ > $@
|
||||
@echo #define WEBP_DLL_H_ >> $@
|
||||
@echo #define WEBP_EXTERN __declspec(dllexport) >> $@
|
||||
@echo #endif /* WEBP_DLL_H_ */ >> $@
|
||||
|
||||
.SUFFIXES: .c .obj .res .exe
|
||||
# File-specific flag builds. Note batch rules take precedence over wildcards,
|
||||
# so for now name each file individually.
|
||||
@ -482,6 +492,8 @@ $(DIROBJ)\examples\gifdec.obj: examples\gifdec.c
|
||||
$(CC) $(CFLAGS) /Fd$(DIROBJ)\extras\ /Fo$(DIROBJ)\extras\ $<
|
||||
{imageio}.c{$(DIROBJ)\imageio}.obj::
|
||||
$(CC) $(CFLAGS) /Fd$(DIROBJ)\imageio\ /Fo$(DIROBJ)\imageio\ $<
|
||||
{sharpyuv}.c{$(DIROBJ)\sharpyuv}.obj::
|
||||
$(CC) $(CFLAGS) /Fd$(DIROBJ)\sharpyuv\ /Fo$(DIROBJ)\sharpyuv\ $<
|
||||
{src\dec}.c{$(DIROBJ)\dec}.obj::
|
||||
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $<
|
||||
{src\demux}.c{$(DIROBJ)\demux}.obj::
|
||||
@ -502,13 +514,9 @@ LNKLIBS = $(LNKLIBS) Shell32.lib
|
||||
|
||||
{$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe:
|
||||
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
|
||||
$(MT) -manifest $@.manifest -outputresource:$@;1
|
||||
del $@.manifest
|
||||
|
||||
{$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe:
|
||||
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
|
||||
$(MT) -manifest $@.manifest -outputresource:$@;1
|
||||
del $@.manifest
|
||||
|
||||
clean::
|
||||
@-erase /s $(DIROBJ)\*.dll 2> NUL
|
||||
|
56
NEWS
56
NEWS
@ -1,3 +1,59 @@
|
||||
- 4/12/2024: version 1.4.0
|
||||
This is a binary compatible release.
|
||||
* API changes:
|
||||
- libwebpmux: WebPAnimEncoderSetChunk, WebPAnimEncoderGetChunk,
|
||||
WebPAnimEncoderDeleteChunk
|
||||
- libsharpyuv: SharpYuvOptionsInit, SharpYuvConvertWithOptions
|
||||
- extras: SharpYuvEstimate420Risk
|
||||
* further security related hardening in libwebp & examples
|
||||
* some minor optimizations in the lossless encoder
|
||||
* added WEBP_NODISCARD to report unused result warnings; enable with
|
||||
-DWEBP_ENABLE_NODISCARD=1
|
||||
* improvements and corrections in webp-container-spec.txt and
|
||||
webp-lossless-bitstream-spec.txt (#611)
|
||||
* miscellaneous warning, bug & build fixes (#615, #619, #632, #635)
|
||||
|
||||
- 9/13/2023: version 1.3.2
|
||||
This is a binary compatible release.
|
||||
* security fix for lossless decoder (chromium: #1479274, CVE-2023-4863)
|
||||
|
||||
- 6/23/2023: version 1.3.1
|
||||
This is a binary compatible release.
|
||||
* security fixes for lossless encoder (#603, chromium: #1420107, #1455619,
|
||||
CVE-2023-1999)
|
||||
* improve error reporting through WebPPicture error codes
|
||||
* fix upsampling for RGB565 and RGBA4444 in NEON builds
|
||||
* img2webp: add -sharp_yuv & -near_lossless
|
||||
* Windows builds:
|
||||
- fix compatibility with clang-cl (#607)
|
||||
- improve Arm64 performance with cl.exe
|
||||
- add Arm64EC support
|
||||
* fix webp_js with emcc >= 3.1.27 (stack size change, #614)
|
||||
* CMake fixes (#592, #610, #612)
|
||||
* further updates to the container and lossless bitstream docs (#581, #611)
|
||||
|
||||
- 12/16/2022: version 1.3.0
|
||||
This is a binary compatible release.
|
||||
* add libsharpyuv, which exposes -sharp_yuv/config.use_sharp_yuv
|
||||
functionality to other libraries; libwebp now depends on this library
|
||||
* major updates to the container and lossless bitstream docs (#448, #546,
|
||||
#551)
|
||||
* miscellaneous warning, bug & build fixes (#576, #583, #584)
|
||||
|
||||
- 8/4/2022: version 1.2.4
|
||||
This is a binary compatible release.
|
||||
* restore CMake libwebpmux target name for compatibility with 1.2.2 (#575)
|
||||
* fix lossless crunch mode encoding with WEBP_REDUCE_SIZE
|
||||
(chromium: #1345547, #1345595, #1345772, #1345804)
|
||||
|
||||
- 6/30/2022: version 1.2.3
|
||||
This is a binary compatible release.
|
||||
* security fix for lossless encoder (#565, chromium:1313709)
|
||||
* improved progress granularity in WebPReportProgress() when using lossless
|
||||
* improved precision in Sharp YUV (-sharp_yuv) conversion
|
||||
* many corrections to webp-lossless-bitstream-spec.txt (#551)
|
||||
* crash/leak fixes on error/OOM and other bug fixes (#558, #563, #569, #573)
|
||||
|
||||
- 1/11/2022: version 1.2.2
|
||||
This is a binary compatible release.
|
||||
* webpmux: add "-set bgcolor A,R,G,B"
|
||||
|
31
PRESUBMIT.py
31
PRESUBMIT.py
@ -41,6 +41,7 @@ _BASH_INDENTATION = "2"
|
||||
_GIT_COMMIT_SUBJECT_LENGTH = 65
|
||||
_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"]
|
||||
_INCLUDE_MAN_FILES_ONLY = [r"man/.+\.1$"]
|
||||
_INCLUDE_SOURCE_FILES_ONLY = [r".*\.[ch]$"]
|
||||
_LIBWEBP_MAX_LINE_LENGTH = 80
|
||||
|
||||
|
||||
@ -72,6 +73,35 @@ def _CheckCommitSubjectLength(input_api, output_api):
|
||||
return output_api.PresubmitResult("%s\n (%4.2fs) success" % (name, duration))
|
||||
|
||||
|
||||
def _CheckDuplicateFiles(input_api, output_api):
|
||||
"""Ensures there are not repeated filenames."""
|
||||
all_files = []
|
||||
for f in input_api.change.AllFiles():
|
||||
for include_file in _INCLUDE_SOURCE_FILES_ONLY:
|
||||
if re.match(include_file, f):
|
||||
all_files.append(f)
|
||||
break
|
||||
|
||||
basename_to_path = {}
|
||||
for f in all_files:
|
||||
basename_file = input_api.basename(f)
|
||||
if basename_file in basename_to_path:
|
||||
basename_to_path[basename_file].append(f)
|
||||
else:
|
||||
basename_to_path[basename_file] = [f]
|
||||
|
||||
dupes = []
|
||||
for files in basename_to_path.values():
|
||||
if len(files) > 1:
|
||||
dupes.extend(files)
|
||||
|
||||
if dupes:
|
||||
return output_api.PresubmitError(
|
||||
"Duplicate source files, rebase or rename some to make them unique:\n%s"
|
||||
% dupes)
|
||||
return output_api.PresubmitResult("No duplicates, success\n")
|
||||
|
||||
|
||||
def _GetFilesToSkip(input_api):
|
||||
return list(input_api.DEFAULT_FILES_TO_SKIP) + [
|
||||
r"swig/.*\.py$",
|
||||
@ -154,6 +184,7 @@ def _CommonChecks(input_api, output_api):
|
||||
input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
|
||||
input_api, output_api))
|
||||
results.append(_CheckCommitSubjectLength(input_api, output_api))
|
||||
results.append(_CheckDuplicateFiles(input_api, output_api))
|
||||
|
||||
source_file_filter = lambda x: input_api.FilterSourceFile(
|
||||
x, files_to_skip=_GetFilesToSkip(input_api))
|
||||
|
795
README
795
README
@ -1,795 +0,0 @@
|
||||
__ __ ____ ____ ____
|
||||
/ \\/ \/ _ \/ _ )/ _ \
|
||||
\ / __/ _ \ __/
|
||||
\__\__/\____/\_____/__/ ____ ___
|
||||
/ _/ / \ \ / _ \/ _/
|
||||
/ \_/ / / \ \ __/ \__
|
||||
\____/____/\_____/_____/____/v1.2.2
|
||||
|
||||
Description:
|
||||
============
|
||||
|
||||
WebP codec: library to encode and decode images in WebP format. This package
|
||||
contains the library that can be used in other programs to add WebP support,
|
||||
as well as the command line tools 'cwebp' and 'dwebp'.
|
||||
|
||||
See https://developers.google.com/speed/webp
|
||||
|
||||
The latest source tree is available at
|
||||
https://chromium.googlesource.com/webm/libwebp
|
||||
|
||||
It is released under the same license as the WebM project.
|
||||
See https://www.webmproject.org/license/software/ or the
|
||||
"COPYING" file for details. An additional intellectual
|
||||
property rights grant can be found in the file PATENTS.
|
||||
|
||||
Building:
|
||||
=========
|
||||
|
||||
Windows build:
|
||||
--------------
|
||||
|
||||
By running:
|
||||
|
||||
nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output
|
||||
|
||||
the directory output\release-static\(x64|x86)\bin will contain the tools
|
||||
cwebp.exe and dwebp.exe. The directory output\release-static\(x64|x86)\lib will
|
||||
contain the libwebp static library.
|
||||
The target architecture (x86/x64) is detected by Makefile.vc from the Visual
|
||||
Studio compiler (cl.exe) available in the system path.
|
||||
|
||||
Unix build using makefile.unix:
|
||||
-------------------------------
|
||||
|
||||
On platforms with GNU tools installed (gcc and make), running
|
||||
|
||||
make -f makefile.unix
|
||||
|
||||
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 makefile.unix for additional details and customizations.
|
||||
|
||||
Using autoconf tools:
|
||||
---------------------
|
||||
Prerequisites:
|
||||
A compiler (e.g., gcc), make, autoconf, automake, libtool.
|
||||
On a Debian-like system the following should install everything you need for a
|
||||
minimal build:
|
||||
$ sudo apt-get install gcc make autoconf automake libtool
|
||||
|
||||
When building from git sources, you will need to run autogen.sh to generate the
|
||||
configure script.
|
||||
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
should be all you need to have the following files
|
||||
|
||||
/usr/local/include/webp/decode.h
|
||||
/usr/local/include/webp/encode.h
|
||||
/usr/local/include/webp/types.h
|
||||
/usr/local/lib/libwebp.*
|
||||
/usr/local/bin/cwebp
|
||||
/usr/local/bin/dwebp
|
||||
|
||||
installed.
|
||||
|
||||
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.
|
||||
|
||||
Building for MIPS Linux:
|
||||
------------------------
|
||||
MIPS Linux toolchain stable available releases can be found at:
|
||||
https://community.imgtec.com/developers/mips/tools/codescape-mips-sdk/available-releases/
|
||||
|
||||
# Add toolchain to PATH
|
||||
export PATH=$PATH:/path/to/toolchain/bin
|
||||
|
||||
# 32-bit build for mips32r5 (p5600)
|
||||
HOST=mips-mti-linux-gnu
|
||||
MIPS_CFLAGS="-O3 -mips32r5 -mabi=32 -mtune=p5600 -mmsa -mfp64 \
|
||||
-msched-weight -mload-store-pairs -fPIE"
|
||||
MIPS_LDFLAGS="-mips32r5 -mabi=32 -mmsa -mfp64 -pie"
|
||||
|
||||
# 64-bit build for mips64r6 (i6400)
|
||||
HOST=mips-img-linux-gnu
|
||||
MIPS_CFLAGS="-O3 -mips64r6 -mabi=64 -mtune=i6400 -mmsa -mfp64 \
|
||||
-msched-weight -mload-store-pairs -fPIE"
|
||||
MIPS_LDFLAGS="-mips64r6 -mabi=64 -mmsa -mfp64 -pie"
|
||||
|
||||
./configure --host=${HOST} --build=`config.guess` \
|
||||
CC="${HOST}-gcc -EL" \
|
||||
CFLAGS="$MIPS_CFLAGS" \
|
||||
LDFLAGS="$MIPS_LDFLAGS"
|
||||
make
|
||||
make install
|
||||
|
||||
CMake:
|
||||
------
|
||||
With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo
|
||||
and the JS bindings.
|
||||
|
||||
Prerequisites:
|
||||
A compiler (e.g., gcc with autotools) and CMake.
|
||||
On a Debian-like system the following should install everything you need for a
|
||||
minimal build:
|
||||
$ sudo apt-get install build-essential cmake
|
||||
|
||||
When building from git sources, you will need to run cmake to generate the
|
||||
makefiles.
|
||||
|
||||
mkdir build && cd build && cmake ../
|
||||
make
|
||||
make install
|
||||
|
||||
If you also want any of the executables, you will need to enable them through
|
||||
CMake, e.g.:
|
||||
|
||||
cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../
|
||||
|
||||
or through your favorite interface (like ccmake or cmake-qt-gui).
|
||||
|
||||
Use option -DWEBP_UNICODE=ON for Unicode support on Windows (with chcp 65001).
|
||||
|
||||
Finally, once installed, you can also use WebP in your CMake project by doing:
|
||||
|
||||
find_package(WebP)
|
||||
|
||||
which will define the CMake variables WebP_INCLUDE_DIRS and WebP_LIBRARIES.
|
||||
|
||||
Gradle:
|
||||
-------
|
||||
The support for Gradle is minimal: it only helps you compile libwebp, cwebp and
|
||||
dwebp and webpmux_example.
|
||||
|
||||
Prerequisites:
|
||||
A compiler (e.g., gcc with autotools) and gradle.
|
||||
On a Debian-like system the following should install everything you need for a
|
||||
minimal build:
|
||||
$ sudo apt-get install build-essential gradle
|
||||
|
||||
When building from git sources, you will need to run the Gradle wrapper with the
|
||||
appropriate target, e.g. :
|
||||
|
||||
./gradlew buildAllExecutables
|
||||
|
||||
SWIG bindings:
|
||||
--------------
|
||||
|
||||
To generate language bindings from swig/libwebp.swig at least swig-1.3
|
||||
(http://www.swig.org) is required.
|
||||
|
||||
Currently the following functions are mapped:
|
||||
Decode:
|
||||
WebPGetDecoderVersion
|
||||
WebPGetInfo
|
||||
WebPDecodeRGBA
|
||||
WebPDecodeARGB
|
||||
WebPDecodeBGRA
|
||||
WebPDecodeBGR
|
||||
WebPDecodeRGB
|
||||
|
||||
Encode:
|
||||
WebPGetEncoderVersion
|
||||
WebPEncodeRGBA
|
||||
WebPEncodeBGRA
|
||||
WebPEncodeRGB
|
||||
WebPEncodeBGR
|
||||
WebPEncodeLosslessRGBA
|
||||
WebPEncodeLosslessBGRA
|
||||
WebPEncodeLosslessRGB
|
||||
WebPEncodeLosslessBGR
|
||||
|
||||
See swig/README for more detailed build instructions.
|
||||
|
||||
Java bindings:
|
||||
|
||||
To build the swig-generated JNI wrapper code at least JDK-1.5 (or equivalent)
|
||||
is necessary for enum support. The output is intended to be a shared object /
|
||||
DLL that can be loaded via System.loadLibrary("webp_jni").
|
||||
|
||||
Python bindings:
|
||||
|
||||
To build the swig-generated Python extension code at least Python 2.6 is
|
||||
required. Python < 2.6 may build with some minor changes to libwebp.swig or the
|
||||
generated code, but is untested.
|
||||
|
||||
Encoding tool:
|
||||
==============
|
||||
|
||||
The examples/ directory contains tools for encoding (cwebp) and
|
||||
decoding (dwebp) images.
|
||||
|
||||
The easiest use should look like:
|
||||
cwebp input.png -q 80 -o output.webp
|
||||
which will convert the input file to a WebP file using a quality factor of 80
|
||||
on a 0->100 scale (0 being the lowest quality, 100 being the best. Default
|
||||
value is 75).
|
||||
You might want to try the -lossless flag too, which will compress the source
|
||||
(in RGBA format) without any loss. The -q quality parameter will in this case
|
||||
control the amount of processing time spent trying to make the output file as
|
||||
small as possible.
|
||||
|
||||
A longer list of options is available using the -longhelp command line flag:
|
||||
|
||||
> cwebp -longhelp
|
||||
Usage:
|
||||
cwebp [-preset <...>] [options] in_file [-o out_file]
|
||||
|
||||
If input size (-s) for an image is not specified, it is
|
||||
assumed to be a PNG, JPEG, TIFF or WebP file.
|
||||
Note: Animated PNG and WebP files are not supported.
|
||||
|
||||
Options:
|
||||
-h / -help ............. short help
|
||||
-H / -longhelp ......... long help
|
||||
-q <float> ............. quality factor (0:small..100:big), default=75
|
||||
-alpha_q <int> ......... transparency-compression quality (0..100),
|
||||
default=100
|
||||
-preset <string> ....... preset setting, one of:
|
||||
default, photo, picture,
|
||||
drawing, icon, text
|
||||
-preset must come first, as it overwrites other parameters
|
||||
-z <int> ............... activates lossless preset with given
|
||||
level in [0:fast, ..., 9:slowest]
|
||||
|
||||
-m <int> ............... compression method (0=fast, 6=slowest), default=4
|
||||
-segments <int> ........ number of segments to use (1..4), default=4
|
||||
-size <int> ............ target size (in bytes)
|
||||
-psnr <float> .......... target PSNR (in dB. typically: 42)
|
||||
|
||||
-s <int> <int> ......... input size (width x height) for YUV
|
||||
-sns <int> ............. spatial noise shaping (0:off, 100:max), default=50
|
||||
-f <int> ............... filter strength (0=off..100), default=60
|
||||
-sharpness <int> ....... filter sharpness (0:most .. 7:least sharp), default=0
|
||||
-strong ................ use strong filter instead of simple (default)
|
||||
-nostrong .............. use simple filter instead of strong
|
||||
-sharp_yuv ............. use sharper (and slower) RGB->YUV conversion
|
||||
-partition_limit <int> . limit quality to fit the 512k limit on
|
||||
the first partition (0=no degradation ... 100=full)
|
||||
-pass <int> ............ analysis pass number (1..10)
|
||||
-qrange <min> <max> .... specifies the permissible quality range
|
||||
(default: 0 100)
|
||||
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
|
||||
-resize <w> <h> ........ resize picture (after any cropping)
|
||||
-mt .................... use multi-threading if available
|
||||
-low_memory ............ reduce memory usage (slower encoding)
|
||||
-map <int> ............. print map of extra info
|
||||
-print_psnr ............ prints averaged PSNR distortion
|
||||
-print_ssim ............ prints averaged SSIM distortion
|
||||
-print_lsim ............ prints local-similarity distortion
|
||||
-d <file.pgm> .......... dump the compressed output (PGM file)
|
||||
-alpha_method <int> .... transparency-compression method (0..1), default=1
|
||||
-alpha_filter <string> . predictive filtering for alpha plane,
|
||||
one of: none, fast (default) or best
|
||||
-exact ................. preserve RGB values in transparent area, default=off
|
||||
-blend_alpha <hex> ..... blend colors against background color
|
||||
expressed as RGB values written in
|
||||
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
|
||||
green=0xe0 and blue=0xd0
|
||||
-noalpha ............... discard any transparency information
|
||||
-lossless .............. encode image losslessly, default=off
|
||||
-near_lossless <int> ... use near-lossless image
|
||||
preprocessing (0..100=off), default=100
|
||||
-hint <string> ......... specify image characteristics hint,
|
||||
one of: photo, picture or graph
|
||||
|
||||
-metadata <string> ..... comma separated list of metadata to
|
||||
copy from the input to the output if present.
|
||||
Valid values: all, none (default), exif, icc, xmp
|
||||
|
||||
-short ................. condense printed message
|
||||
-quiet ................. don't print anything
|
||||
-version ............... print version number and exit
|
||||
-noasm ................. disable all assembly optimizations
|
||||
-v ..................... verbose, e.g. print encoding/decoding times
|
||||
-progress .............. report encoding progress
|
||||
|
||||
Experimental Options:
|
||||
-jpeg_like ............. roughly match expected JPEG size
|
||||
-af .................... auto-adjust filter strength
|
||||
-pre <int> ............. pre-processing filter
|
||||
|
||||
|
||||
The main options you might want to try in order to further tune the
|
||||
visual quality are:
|
||||
-preset
|
||||
-sns
|
||||
-f
|
||||
-m
|
||||
|
||||
Namely:
|
||||
* 'preset' will set up a default encoding configuration targeting a
|
||||
particular type of input. It should appear first in the list of options,
|
||||
so that subsequent options can take effect on top of this preset.
|
||||
Default value is 'default'.
|
||||
* 'sns' will progressively turn on (when going from 0 to 100) some additional
|
||||
visual optimizations (like: segmentation map re-enforcement). This option
|
||||
will balance the bit allocation differently. It tries to take bits from the
|
||||
"easy" parts of the picture and use them in the "difficult" ones instead.
|
||||
Usually, raising the sns value (at fixed -q value) leads to larger files,
|
||||
but with better quality.
|
||||
Typical value is around '75'.
|
||||
* 'f' option directly links to the filtering strength used by the codec's
|
||||
in-loop processing. The higher the value, the smoother the
|
||||
highly-compressed area will look. This is particularly useful when aiming
|
||||
at very small files. Typical values are around 20-30. Note that using the
|
||||
option -strong/-nostrong will change the type of filtering. Use "-f 0" to
|
||||
turn filtering off.
|
||||
* 'm' controls the trade-off between encoding speed and quality. Default is 4.
|
||||
You can try -m 5 or -m 6 to explore more (time-consuming) encoding
|
||||
possibilities. A lower value will result in faster encoding at the expense
|
||||
of quality.
|
||||
|
||||
Decoding tool:
|
||||
==============
|
||||
|
||||
There is a decoding sample in examples/dwebp.c which will take
|
||||
a .webp file and decode it to a PNG image file (amongst other formats).
|
||||
This is simply to demonstrate the use of the API. You can verify the
|
||||
file test.webp decodes to exactly the same as test_ref.ppm by using:
|
||||
|
||||
cd examples
|
||||
./dwebp test.webp -ppm -o test.ppm
|
||||
diff test.ppm test_ref.ppm
|
||||
|
||||
The full list of options is available using -h:
|
||||
|
||||
> dwebp -h
|
||||
Usage: dwebp in_file [options] [-o out_file]
|
||||
|
||||
Decodes the WebP image file to PNG format [Default].
|
||||
Note: Animated WebP files are not supported.
|
||||
|
||||
Use following options to convert into alternate image formats:
|
||||
-pam ......... save the raw RGBA samples as a color PAM
|
||||
-ppm ......... save the raw RGB samples as a color PPM
|
||||
-bmp ......... save as uncompressed BMP format
|
||||
-tiff ........ save as uncompressed TIFF format
|
||||
-pgm ......... save the raw YUV samples as a grayscale PGM
|
||||
file with IMC4 layout
|
||||
-yuv ......... save the raw YUV samples in flat layout
|
||||
|
||||
Other options are:
|
||||
-version ..... print version number and exit
|
||||
-nofancy ..... don't use the fancy YUV420 upscaler
|
||||
-nofilter .... disable in-loop filtering
|
||||
-nodither .... disable dithering
|
||||
-dither <d> .. dithering strength (in 0..100)
|
||||
-alpha_dither use alpha-plane dithering if needed
|
||||
-mt .......... use multi-threading
|
||||
-crop <x> <y> <w> <h> ... crop output with the given rectangle
|
||||
-resize <w> <h> ......... scale the output (*after* any cropping)
|
||||
-flip ........ flip the output vertically
|
||||
-alpha ....... only save the alpha plane
|
||||
-incremental . use incremental decoding (useful for tests)
|
||||
-h ........... this help message
|
||||
-v ........... verbose (e.g. print encoding/decoding times)
|
||||
-quiet ....... quiet mode, don't print anything
|
||||
-noasm ....... disable all assembly optimizations
|
||||
|
||||
WebP file analysis tool:
|
||||
========================
|
||||
|
||||
'webpinfo' can be used to print out the chunk level structure and bitstream
|
||||
header information of WebP files. It can also check if the files are of valid
|
||||
WebP format.
|
||||
|
||||
Usage: webpinfo [options] in_files
|
||||
Note: there could be multiple input files;
|
||||
options must come before input files.
|
||||
Options:
|
||||
-version ........... Print version number and exit.
|
||||
-quiet ............. Do not show chunk parsing information.
|
||||
-diag .............. Show parsing error diagnosis.
|
||||
-summary ........... Show chunk stats summary.
|
||||
-bitstream_info .... Parse bitstream header.
|
||||
|
||||
Visualization tool:
|
||||
===================
|
||||
|
||||
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 build system, but
|
||||
you can try to manually compile it using the recommendations below.
|
||||
|
||||
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
|
||||
-dither <int> dithering strength (0..100), default=50
|
||||
-noalphadither disable alpha plane dithering
|
||||
-usebgcolor .. display background color
|
||||
-mt .......... use multi-threading
|
||||
-info ........ print info
|
||||
-h ........... this help message
|
||||
|
||||
Keyboard shortcuts:
|
||||
'c' ................ toggle use of color profile
|
||||
'b' ................ toggle background color display
|
||||
'i' ................ overlay file information
|
||||
'd' ................ disable blending & disposal (debug)
|
||||
'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:
|
||||
https://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms
|
||||
https://source.chromium.org/chromium/chromium/src/+/main:third_party/qcms/;drc=d4a2f8e1ed461d8fc05ed88d1ae2dc94c9773825
|
||||
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
|
||||
|
||||
Animation creation tool:
|
||||
========================
|
||||
The utility 'img2webp' can turn a sequence of input images (PNG, JPEG, ...)
|
||||
into an animated WebP file. It offers fine control over duration, encoding
|
||||
modes, etc.
|
||||
|
||||
Usage:
|
||||
|
||||
img2webp [file_options] [[frame_options] frame_file]...
|
||||
|
||||
File-level options (only used at the start of compression):
|
||||
-min_size ............ minimize size
|
||||
-loop <int> .......... loop count (default: 0, = infinite loop)
|
||||
-kmax <int> .......... maximum number of frame between key-frames
|
||||
(0=only keyframes)
|
||||
-kmin <int> .......... minimum number of frame between key-frames
|
||||
(0=disable key-frames altogether)
|
||||
-mixed ............... use mixed lossy/lossless automatic mode
|
||||
-v ................... verbose mode
|
||||
-h ................... this help
|
||||
-version ............. print version number and exit
|
||||
|
||||
Per-frame options (only used for subsequent images input):
|
||||
-d <int> ............. frame duration in ms (default: 100)
|
||||
-lossless ........... use lossless mode (default)
|
||||
-lossy ... ........... use lossy mode
|
||||
-q <float> ........... quality
|
||||
-m <int> ............. method to use
|
||||
|
||||
example: img2webp -loop 2 in0.png -lossy in1.jpg
|
||||
-d 80 in2.tiff -o out.webp
|
||||
|
||||
Note: if a single file name is passed as the argument, the arguments will be
|
||||
tokenized from this file. The file name must not start with the character '-'.
|
||||
|
||||
Animated GIF conversion:
|
||||
========================
|
||||
Animated GIF files can be converted to WebP files with animation using the
|
||||
gif2webp utility available under examples/. The files can then be viewed using
|
||||
vwebp.
|
||||
|
||||
Usage:
|
||||
gif2webp [options] gif_file -o webp_file
|
||||
Options:
|
||||
-h / -help ............. this help
|
||||
-lossy ................. encode image using lossy compression
|
||||
-mixed ................. for each frame in the image, pick lossy
|
||||
or lossless compression heuristically
|
||||
-q <float> ............. quality factor (0:small..100:big)
|
||||
-m <int> ............... compression method (0=fast, 6=slowest)
|
||||
-min_size .............. minimize output size (default:off)
|
||||
lossless compression by default; can be
|
||||
combined with -q, -m, -lossy or -mixed
|
||||
options
|
||||
-kmin <int> ............ min distance between key frames
|
||||
-kmax <int> ............ max distance between key frames
|
||||
-f <int> ............... filter strength (0=off..100)
|
||||
-metadata <string> ..... comma separated list of metadata to
|
||||
copy from the input to the output if present
|
||||
Valid values: all, none, icc, xmp (default)
|
||||
-loop_compatibility .... use compatibility mode for Chrome
|
||||
version prior to M62 (inclusive)
|
||||
-mt .................... use multi-threading if available
|
||||
|
||||
-version ............... print version number and exit
|
||||
-v ..................... verbose
|
||||
-quiet ................. don't print anything
|
||||
|
||||
Building:
|
||||
---------
|
||||
With the libgif development files installed, gif2webp can be built using
|
||||
makefile.unix:
|
||||
$ make -f makefile.unix examples/gif2webp
|
||||
|
||||
or using autoconf:
|
||||
$ ./configure --enable-everything
|
||||
$ make
|
||||
|
||||
Comparison of animated images:
|
||||
==============================
|
||||
Test utility anim_diff under examples/ can be used to compare two animated
|
||||
images (each can be GIF or WebP).
|
||||
|
||||
Usage: anim_diff <image1> <image2> [options]
|
||||
|
||||
Options:
|
||||
-dump_frames <folder> dump decoded frames in PAM format
|
||||
-min_psnr <float> ... minimum per-frame PSNR
|
||||
-raw_comparison ..... if this flag is not used, RGB is
|
||||
premultiplied before comparison
|
||||
-max_diff <int> ..... maximum allowed difference per channel
|
||||
between corresponding pixels in subsequent
|
||||
frames
|
||||
-h .................. this help
|
||||
-version ............ print version number and exit
|
||||
|
||||
Building:
|
||||
---------
|
||||
With the libgif development files and a C++ compiler installed, anim_diff can
|
||||
be built using makefile.unix:
|
||||
$ make -f makefile.unix examples/anim_diff
|
||||
|
||||
or using autoconf:
|
||||
$ ./configure --enable-everything
|
||||
$ make
|
||||
|
||||
Encoding API:
|
||||
=============
|
||||
|
||||
The main encoding functions are available in the header src/webp/encode.h
|
||||
The ready-to-use ones are:
|
||||
size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride,
|
||||
float quality_factor, uint8_t** output);
|
||||
size_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride,
|
||||
float quality_factor, uint8_t** output);
|
||||
size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride,
|
||||
float quality_factor, uint8_t** output);
|
||||
size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride,
|
||||
float quality_factor, uint8_t** output);
|
||||
|
||||
They will convert raw RGB samples to a WebP data. The only control supplied
|
||||
is the quality factor.
|
||||
|
||||
There are some variants for using the lossless format:
|
||||
|
||||
size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height,
|
||||
int stride, uint8_t** output);
|
||||
size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height,
|
||||
int stride, uint8_t** output);
|
||||
size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height,
|
||||
int stride, uint8_t** output);
|
||||
size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height,
|
||||
int stride, uint8_t** output);
|
||||
|
||||
Of course in this case, no quality factor is needed since the compression
|
||||
occurs without loss of the input values, at the expense of larger output sizes.
|
||||
|
||||
Advanced encoding API:
|
||||
----------------------
|
||||
|
||||
A more advanced API is based on the WebPConfig and WebPPicture structures.
|
||||
|
||||
WebPConfig contains the encoding settings and is not tied to a particular
|
||||
picture.
|
||||
WebPPicture contains input data, on which some WebPConfig will be used for
|
||||
compression.
|
||||
The encoding flow looks like:
|
||||
|
||||
-------------------------------------- BEGIN PSEUDO EXAMPLE
|
||||
|
||||
#include <webp/encode.h>
|
||||
|
||||
// Setup a config, starting form a preset and tuning some additional
|
||||
// parameters
|
||||
WebPConfig config;
|
||||
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) {
|
||||
return 0; // version error
|
||||
}
|
||||
// ... additional tuning
|
||||
config.sns_strength = 90;
|
||||
config.filter_sharpness = 6;
|
||||
config_error = WebPValidateConfig(&config); // not mandatory, but useful
|
||||
|
||||
// Setup the input data
|
||||
WebPPicture pic;
|
||||
if (!WebPPictureInit(&pic)) {
|
||||
return 0; // version error
|
||||
}
|
||||
pic.width = width;
|
||||
pic.height = height;
|
||||
// allocated picture of dimension width x height
|
||||
if (!WebPPictureAlloc(&pic)) {
|
||||
return 0; // memory error
|
||||
}
|
||||
// at this point, 'pic' has been initialized as a container,
|
||||
// and can receive the Y/U/V samples.
|
||||
// Alternatively, one could use ready-made import functions like
|
||||
// WebPPictureImportRGB(), which will take care of memory allocation.
|
||||
// In any case, past this point, one will have to call
|
||||
// WebPPictureFree(&pic) to reclaim memory.
|
||||
|
||||
// Set up a byte-output write method. WebPMemoryWriter, for instance.
|
||||
WebPMemoryWriter wrt;
|
||||
WebPMemoryWriterInit(&wrt); // initialize 'wrt'
|
||||
|
||||
pic.writer = MyFileWriter;
|
||||
pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work;
|
||||
|
||||
// Compress!
|
||||
int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred!
|
||||
WebPPictureFree(&pic); // must be called independently of the 'ok' result.
|
||||
|
||||
// output data should have been handled by the writer at that point.
|
||||
// -> compressed data is the memory buffer described by wrt.mem / wrt.size
|
||||
|
||||
// deallocate the memory used by compressed data
|
||||
WebPMemoryWriterClear(&wrt);
|
||||
|
||||
-------------------------------------- END PSEUDO EXAMPLE
|
||||
|
||||
Decoding API:
|
||||
=============
|
||||
|
||||
This is mainly just one function to call:
|
||||
|
||||
#include "webp/decode.h"
|
||||
uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
|
||||
int* width, int* height);
|
||||
|
||||
Please have a look at the file src/webp/decode.h for the details.
|
||||
There are variants for decoding in BGR/RGBA/ARGB/BGRA order, along with
|
||||
decoding to raw Y'CbCr samples. One can also decode the image directly into a
|
||||
pre-allocated buffer.
|
||||
|
||||
To detect a WebP file and gather the picture's dimensions, the function:
|
||||
int WebPGetInfo(const uint8_t* data, size_t data_size,
|
||||
int* width, int* height);
|
||||
is supplied. No decoding is involved when using it.
|
||||
|
||||
Incremental decoding API:
|
||||
=========================
|
||||
|
||||
In the case when data is being progressively transmitted, pictures can still
|
||||
be incrementally decoded using a slightly more complicated API. Decoder state
|
||||
is stored into an instance of the WebPIDecoder object. This object can be
|
||||
created with the purpose of decoding either RGB or Y'CbCr samples.
|
||||
For instance:
|
||||
|
||||
WebPDecBuffer buffer;
|
||||
WebPInitDecBuffer(&buffer);
|
||||
buffer.colorspace = MODE_BGR;
|
||||
...
|
||||
WebPIDecoder* idec = WebPINewDecoder(&buffer);
|
||||
|
||||
As data is made progressively available, this incremental-decoder object
|
||||
can be used to decode the picture further. There are two (mutually exclusive)
|
||||
ways to pass freshly arrived data:
|
||||
|
||||
either by appending the fresh bytes:
|
||||
|
||||
WebPIAppend(idec, fresh_data, size_of_fresh_data);
|
||||
|
||||
or by just mentioning the new size of the transmitted data:
|
||||
|
||||
WebPIUpdate(idec, buffer, size_of_transmitted_buffer);
|
||||
|
||||
Note that 'buffer' can be modified between each call to WebPIUpdate, in
|
||||
particular when the buffer is resized to accommodate larger data.
|
||||
|
||||
These functions will return the decoding status: either VP8_STATUS_SUSPENDED if
|
||||
decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other
|
||||
status is an error condition.
|
||||
|
||||
The 'idec' object must always be released (even upon an error condition) by
|
||||
calling: WebPDelete(idec).
|
||||
|
||||
To retrieve partially decoded picture samples, one must use the corresponding
|
||||
method: WebPIDecGetRGB or WebPIDecGetYUVA.
|
||||
It will return the last displayable pixel row.
|
||||
|
||||
Lastly, note that decoding can also be performed into a pre-allocated pixel
|
||||
buffer. This buffer must be passed when creating a WebPIDecoder, calling
|
||||
WebPINewRGB() or WebPINewYUVA().
|
||||
|
||||
Please have a look at the src/webp/decode.h header for further details.
|
||||
|
||||
Advanced Decoding API:
|
||||
======================
|
||||
|
||||
WebP decoding supports an advanced API which provides on-the-fly cropping and
|
||||
rescaling, something of great usefulness on memory-constrained environments like
|
||||
mobile phones. Basically, the memory usage will scale with the output's size,
|
||||
not the input's, when one only needs a quick preview or a zoomed in portion of
|
||||
an otherwise too-large picture. Some CPU can be saved too, incidentally.
|
||||
|
||||
-------------------------------------- BEGIN PSEUDO EXAMPLE
|
||||
// A) Init a configuration object
|
||||
WebPDecoderConfig config;
|
||||
CHECK(WebPInitDecoderConfig(&config));
|
||||
|
||||
// B) optional: retrieve the bitstream's features.
|
||||
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
|
||||
|
||||
// C) Adjust 'config' options, if needed
|
||||
config.options.no_fancy_upsampling = 1;
|
||||
config.options.use_scaling = 1;
|
||||
config.options.scaled_width = scaledWidth();
|
||||
config.options.scaled_height = scaledHeight();
|
||||
// etc.
|
||||
|
||||
// D) Specify 'config' output options for specifying output colorspace.
|
||||
// Optionally the external image decode buffer can also be specified.
|
||||
config.output.colorspace = MODE_BGRA;
|
||||
// Optionally, the config.output can be pointed to an external buffer as
|
||||
// well for decoding the image. This externally supplied memory buffer
|
||||
// should be big enough to store the decoded picture.
|
||||
config.output.u.RGBA.rgba = (uint8_t*) memory_buffer;
|
||||
config.output.u.RGBA.stride = scanline_stride;
|
||||
config.output.u.RGBA.size = total_size_of_the_memory_buffer;
|
||||
config.output.is_external_memory = 1;
|
||||
|
||||
// E) Decode the WebP image. There are two variants w.r.t decoding image.
|
||||
// The first one (E.1) decodes the full image and the second one (E.2) is
|
||||
// used to incrementally decode the image using small input buffers.
|
||||
// Any one of these steps can be used to decode the WebP image.
|
||||
|
||||
// E.1) Decode full image.
|
||||
CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
|
||||
|
||||
// E.2) Decode image incrementally.
|
||||
WebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config);
|
||||
CHECK(idec != NULL);
|
||||
while (bytes_remaining > 0) {
|
||||
VP8StatusCode status = WebPIAppend(idec, input, bytes_read);
|
||||
if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
|
||||
bytes_remaining -= bytes_read;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
WebPIDelete(idec);
|
||||
|
||||
// F) Decoded image is now in config.output (and config.output.u.RGBA).
|
||||
// It can be saved, displayed or otherwise processed.
|
||||
|
||||
// G) Reclaim memory allocated in config's object. It's safe to call
|
||||
// this function even if the memory is external and wasn't allocated
|
||||
// by WebPDecode().
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
|
||||
-------------------------------------- END PSEUDO EXAMPLE
|
||||
|
||||
Bugs:
|
||||
=====
|
||||
|
||||
Please report all bugs to the issue tracker:
|
||||
https://bugs.chromium.org/p/webp
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting-patches/
|
||||
|
||||
Discuss:
|
||||
========
|
||||
|
||||
Email: webp-discuss@webmproject.org
|
||||
Web: https://groups.google.com/a/webmproject.org/group/webp-discuss
|
54
README.md
Normal file
54
README.md
Normal file
@ -0,0 +1,54 @@
|
||||
# WebP Codec
|
||||
|
||||
```
|
||||
__ __ ____ ____ ____
|
||||
/ \\/ \/ _ \/ _ )/ _ \
|
||||
\ / __/ _ \ __/
|
||||
\__\__/\____/\_____/__/ ____ ___
|
||||
/ _/ / \ \ / _ \/ _/
|
||||
/ \_/ / / \ \ __/ \__
|
||||
\____/____/\_____/_____/____/v1.4.0
|
||||
```
|
||||
|
||||
WebP codec is a library to encode and decode images in WebP format. This package
|
||||
contains the library that can be used in other programs to add WebP support, as
|
||||
well as the command line tools 'cwebp' and 'dwebp' to compress and decompress
|
||||
images respectively.
|
||||
|
||||
See https://developers.google.com/speed/webp for details on the image format.
|
||||
|
||||
The latest source tree is available at
|
||||
https://chromium.googlesource.com/webm/libwebp
|
||||
|
||||
It is released under the same license as the WebM project. See
|
||||
https://www.webmproject.org/license/software/ or the "COPYING" file for details.
|
||||
An additional intellectual property rights grant can be found in the file
|
||||
PATENTS.
|
||||
|
||||
## Building
|
||||
|
||||
See the [building documentation](doc/building.md).
|
||||
|
||||
## Encoding and Decoding Tools
|
||||
|
||||
The examples/ directory contains tools to encode and decode images and
|
||||
animations, view information about WebP images, and more. See the
|
||||
[tools documentation](doc/tools.md).
|
||||
|
||||
## APIs
|
||||
|
||||
See the [APIs documentation](doc/api.md), and API usage examples in the
|
||||
`examples/` directory.
|
||||
|
||||
## Bugs
|
||||
|
||||
Please report all bugs to the [issue tracker](https://issues.webmproject.org).
|
||||
For security reports, select 'Security report' from the Template dropdown.
|
||||
|
||||
Patches welcome! See [how to contribute](CONTRIBUTING.md).
|
||||
|
||||
## Discuss
|
||||
|
||||
Email: webp-discuss@webmproject.org
|
||||
|
||||
Web: https://groups.google.com/a/webmproject.org/group/webp-discuss
|
258
README.mux
258
README.mux
@ -1,258 +0,0 @@
|
||||
__ __ ____ ____ ____ __ __ _ __ __
|
||||
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
|
||||
\ / __/ _ \ __/ / / (_/ /__
|
||||
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.2.2
|
||||
|
||||
|
||||
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 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:
|
||||
==============
|
||||
|
||||
The examples/ directory contains a tool (webpmux) for manipulating WebP
|
||||
files. The webpmux tool can be used to create an extended format WebP file and
|
||||
also to extract or strip relevant data from such a file.
|
||||
|
||||
A list of options is available using the -help command line flag:
|
||||
|
||||
> webpmux -help
|
||||
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
|
||||
webpmux -set SET_OPTIONS INPUT -o OUTPUT
|
||||
webpmux -duration DURATION_OPTIONS [-duration ...]
|
||||
INPUT -o OUTPUT
|
||||
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
|
||||
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
|
||||
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
|
||||
webpmux -info INPUT
|
||||
webpmux [-h|-help]
|
||||
webpmux -version
|
||||
webpmux argument_file_name
|
||||
|
||||
GET_OPTIONS:
|
||||
Extract relevant data:
|
||||
icc get ICC profile
|
||||
exif get EXIF metadata
|
||||
xmp get XMP metadata
|
||||
frame n get nth frame
|
||||
|
||||
SET_OPTIONS:
|
||||
Set color profile/metadata/parameters:
|
||||
loop LOOP_COUNT set the loop count
|
||||
bgcolor BACKGROUND_COLOR set the animation background color
|
||||
icc file.icc set ICC profile
|
||||
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
|
||||
'file.xmp' contains the XMP metadata to be set
|
||||
|
||||
DURATION_OPTIONS:
|
||||
Set duration of selected frames:
|
||||
duration set duration for each frames
|
||||
duration,frame set duration of a particular frame
|
||||
duration,start,end set duration of frames in the
|
||||
interval [start,end])
|
||||
where: 'duration' is the duration in milliseconds
|
||||
'start' is the start frame index
|
||||
'end' is the inclusive end frame index
|
||||
The special 'end' value '0' means: last frame.
|
||||
|
||||
STRIP_OPTIONS:
|
||||
Strip color profile/metadata:
|
||||
icc strip ICC profile
|
||||
exif strip EXIF metadata
|
||||
xmp strip XMP metadata
|
||||
|
||||
FRAME_OPTIONS(i):
|
||||
Create animation:
|
||||
file_i +di+[xi+yi[+mi[bi]]]
|
||||
where: 'file_i' is the i'th animation frame (WebP format),
|
||||
'di' is the pause duration before next frame,
|
||||
'xi','yi' specify the image offset for this frame,
|
||||
'mi' is the dispose method for this frame (0 or 1),
|
||||
'bi' is the blending method for this frame (+b or -b)
|
||||
|
||||
LOOP_COUNT:
|
||||
Number of times to repeat the animation.
|
||||
Valid range is 0 to 65535 [Default: 0 (infinite)].
|
||||
|
||||
BACKGROUND_COLOR:
|
||||
Background color of the canvas.
|
||||
A,R,G,B
|
||||
where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying
|
||||
the Alpha, Red, Green and Blue component values respectively
|
||||
[Default: 255,255,255,255]
|
||||
|
||||
INPUT & OUTPUT are in WebP format.
|
||||
|
||||
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
|
||||
valid.
|
||||
|
||||
Note: if a single file name is passed as the argument, the arguments will be
|
||||
tokenized from this file. The file name must not start with the character '-'.
|
||||
|
||||
Visualization tool:
|
||||
===================
|
||||
|
||||
The examples/ directory also contains a tool (vwebp) for viewing WebP files.
|
||||
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 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.
|
||||
|
||||
int copy_data = 0;
|
||||
WebPMux* mux = WebPMuxNew();
|
||||
// ... (Prepare image data).
|
||||
WebPMuxSetImage(mux, &image, copy_data);
|
||||
// ... (Prepare ICC profile data).
|
||||
WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
|
||||
// ... (Prepare XMP metadata).
|
||||
WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
|
||||
// Get data from mux in WebP RIFF format.
|
||||
WebPMuxAssemble(mux, &output_data);
|
||||
WebPMuxDelete(mux);
|
||||
// ... (Consume output_data; e.g. write output_data.bytes to file).
|
||||
WebPDataClear(&output_data);
|
||||
|
||||
|
||||
Example#2 (pseudo code): Get image and color profile data from a WebP file.
|
||||
|
||||
int copy_data = 0;
|
||||
// ... (Read data from file).
|
||||
WebPMux* mux = WebPMuxCreate(&data, copy_data);
|
||||
WebPMuxGetFrame(mux, 1, &image);
|
||||
// ... (Consume image; e.g. call WebPDecode() to decode the data).
|
||||
WebPMuxGetChunk(mux, "ICCP", &icc_profile);
|
||||
// ... (Consume icc_profile).
|
||||
WebPMuxDelete(mux);
|
||||
free(data);
|
||||
|
||||
|
||||
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 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.
|
||||
|
||||
WebPDemuxer* demux = WebPDemux(&webp_data);
|
||||
uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
|
||||
uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
|
||||
// ... (Get information about the features present in the WebP file).
|
||||
uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
|
||||
|
||||
// ... (Iterate over all frames).
|
||||
WebPIterator iter;
|
||||
if (WebPDemuxGetFrame(demux, 1, &iter)) {
|
||||
do {
|
||||
// ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(),
|
||||
// ... and get other frame properties like width, height, offsets etc.
|
||||
// ... see 'struct WebPIterator' below for more info).
|
||||
} while (WebPDemuxNextFrame(&iter));
|
||||
WebPDemuxReleaseIterator(&iter);
|
||||
}
|
||||
|
||||
// ... (Extract metadata).
|
||||
WebPChunkIterator chunk_iter;
|
||||
if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter);
|
||||
// ... (Consume the ICC profile in 'chunk_iter.chunk').
|
||||
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||
if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter);
|
||||
// ... (Consume the EXIF metadata in 'chunk_iter.chunk').
|
||||
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||
if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter);
|
||||
// ... (Consume the XMP metadata in 'chunk_iter.chunk').
|
||||
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||
WebPDemuxDelete(demux);
|
||||
|
||||
|
||||
For a detailed Demux API reference, please refer to the header file
|
||||
(src/webp/demux.h).
|
||||
|
||||
AnimEncoder API:
|
||||
================
|
||||
The AnimEncoder API can be used to create animated WebP images.
|
||||
|
||||
Code example:
|
||||
|
||||
WebPAnimEncoderOptions enc_options;
|
||||
WebPAnimEncoderOptionsInit(&enc_options);
|
||||
// ... (Tune 'enc_options' as needed).
|
||||
WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options);
|
||||
while(<there are more frames>) {
|
||||
WebPConfig config;
|
||||
WebPConfigInit(&config);
|
||||
// ... (Tune 'config' as needed).
|
||||
WebPAnimEncoderAdd(enc, frame, duration, &config);
|
||||
}
|
||||
WebPAnimEncoderAssemble(enc, webp_data);
|
||||
WebPAnimEncoderDelete(enc);
|
||||
// ... (Write the 'webp_data' to a file, or re-mux it further).
|
||||
|
||||
|
||||
For a detailed AnimEncoder API reference, please refer to the header file
|
||||
(src/webp/mux.h).
|
||||
|
||||
AnimDecoder API:
|
||||
================
|
||||
This AnimDecoder API allows decoding (possibly) animated WebP images.
|
||||
|
||||
Code Example:
|
||||
|
||||
WebPAnimDecoderOptions dec_options;
|
||||
WebPAnimDecoderOptionsInit(&dec_options);
|
||||
// Tune 'dec_options' as needed.
|
||||
WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
|
||||
WebPAnimInfo anim_info;
|
||||
WebPAnimDecoderGetInfo(dec, &anim_info);
|
||||
for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
|
||||
while (WebPAnimDecoderHasMoreFrames(dec)) {
|
||||
uint8_t* buf;
|
||||
int timestamp;
|
||||
WebPAnimDecoderGetNext(dec, &buf, ×tamp);
|
||||
// ... (Render 'buf' based on 'timestamp').
|
||||
// ... (Do NOT free 'buf', as it is owned by 'dec').
|
||||
}
|
||||
WebPAnimDecoderReset(dec);
|
||||
}
|
||||
const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
|
||||
// ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
|
||||
WebPAnimDecoderDelete(dec);
|
||||
|
||||
For a detailed AnimDecoder API reference, please refer to the header file
|
||||
(src/webp/demux.h).
|
||||
|
||||
|
||||
Bugs:
|
||||
=====
|
||||
|
||||
Please report all bugs to the issue tracker:
|
||||
https://bugs.chromium.org/p/webp
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting-patches/
|
||||
|
||||
Discuss:
|
||||
========
|
||||
|
||||
Email: webp-discuss@webmproject.org
|
||||
Web: https://groups.google.com/a/webmproject.org/group/webp-discuss
|
@ -1,75 +0,0 @@
|
||||
__ __ ____ ____ ____ __ ____
|
||||
/ \\/ \ _ \ _ \ _ \ (__)/ __\
|
||||
\ / __/ _ \ __/ _) \_ \
|
||||
\__\__/_____/____/_/ /____/____/
|
||||
|
||||
Description:
|
||||
============
|
||||
|
||||
This file describes the compilation of libwebp into a JavaScript decoder
|
||||
using Emscripten and CMake.
|
||||
|
||||
- install the Emscripten SDK following the procedure described at:
|
||||
https://emscripten.org/docs/getting_started/downloads.html#installation-instructions-using-the-emsdk-recommended
|
||||
After installation, you should have some global variable positioned to the
|
||||
location of the SDK. In particular, $EMSDK should point to the
|
||||
top-level directory containing Emscripten tools.
|
||||
|
||||
- configure the project 'WEBP_JS' with CMake using:
|
||||
|
||||
cd webp_js && \
|
||||
emcmake cmake -DWEBP_BUILD_WEBP_JS=ON \
|
||||
../
|
||||
|
||||
- compile webp.js using 'emmake make'.
|
||||
|
||||
- that's it! Upon completion, you should have the webp.js and
|
||||
webp.wasm files generated.
|
||||
|
||||
The callable JavaScript function is WebPToSDL(), which decodes a raw WebP
|
||||
bitstream into a canvas. See webp_js/index.html for a simple usage sample
|
||||
(see below for instructions).
|
||||
|
||||
Demo HTML page:
|
||||
===============
|
||||
|
||||
The HTML page webp_js/index.html requires an HTTP server to serve the WebP
|
||||
image example. It's easy to just use Python for that.
|
||||
|
||||
cd webp_js && python -m SimpleHTTPServer 8080
|
||||
|
||||
and then navigate to http://localhost:8080 in your favorite browser.
|
||||
|
||||
|
||||
Web-Assembly (WASM) version:
|
||||
============================
|
||||
|
||||
CMakeLists.txt is configured to build the WASM version when using
|
||||
the option WEBP_BUILD_WEBP_JS=ON. The compilation step will assemble
|
||||
the files 'webp_wasm.js', 'webp_wasm.wasm' in the webp_js/ directory.
|
||||
See webp_js/index_wasm.html for a simple demo page using the WASM version
|
||||
of the library.
|
||||
|
||||
You will need a fairly recent version of Emscripten (at least 2.0.18,
|
||||
latest-upstream is recommended) and of your WASM-enabled browser to run this
|
||||
version.
|
||||
|
||||
Caveat:
|
||||
=======
|
||||
|
||||
- First decoding using the library is usually slower, due to just-in-time
|
||||
compilation.
|
||||
|
||||
- Some versions of llvm produce the following compile error when SSE2 is
|
||||
enabled.
|
||||
|
||||
"Unsupported: %516 = bitcast <8 x i16> %481 to i128
|
||||
LLVM ERROR: BitCast Instruction not yet supported for integer types larger than 64 bits"
|
||||
|
||||
The corresponding Emscripten bug is at:
|
||||
https://github.com/kripken/emscripten/issues/3788
|
||||
|
||||
Therefore, SSE2 optimization is currently disabled in CMakeLists.txt.
|
||||
|
||||
- If WEBP_ENABLE_SIMD is set to 1 the JavaScript version (webp.js) will be
|
||||
disabled as wasm2js does not support SIMD.
|
@ -105,6 +105,14 @@ model {
|
||||
sources {
|
||||
c {
|
||||
source {
|
||||
srcDir "sharpyuv"
|
||||
include "sharpyuv.c"
|
||||
include "sharpyuv_cpu.c"
|
||||
include "sharpyuv_csp.c"
|
||||
include "sharpyuv_dsp.c"
|
||||
include "sharpyuv_gamma.c"
|
||||
include "sharpyuv_neon.c"
|
||||
include "sharpyuv_sse2.c"
|
||||
srcDir "src/dec"
|
||||
include "alpha_dec.c"
|
||||
include "buffer_dec.c"
|
||||
@ -165,6 +173,7 @@ model {
|
||||
include "color_cache_utils.c"
|
||||
include "filters_utils.c"
|
||||
include "huffman_utils.c"
|
||||
include "palette.c"
|
||||
include "quant_levels_dec_utils.c"
|
||||
include "random_utils.c"
|
||||
include "rescaler_utils.c"
|
||||
|
@ -3,9 +3,17 @@ set(WEBP_VERSION ${WebP_VERSION})
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
if(@WEBP_USE_THREAD@)
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
set(WebP_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
|
||||
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIRS})
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
|
||||
set_and_check(WebP_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
|
||||
set(WebP_INCLUDE_DIRS ${WebP_INCLUDE_DIR})
|
||||
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIR})
|
||||
set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@")
|
||||
set(WEBP_LIBRARIES "${WebP_LIBRARIES}")
|
||||
|
||||
check_required_components(WebP)
|
||||
|
@ -16,48 +16,18 @@
|
||||
/* Define to 1 if you have the <cpu-features.h> header file. */
|
||||
#cmakedefine HAVE_CPU_FEATURES_H 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#cmakedefine HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the <GLUT/glut.h> header file. */
|
||||
#cmakedefine HAVE_GLUT_GLUT_H 1
|
||||
|
||||
/* Define to 1 if you have the <GL/glut.h> header file. */
|
||||
#cmakedefine HAVE_GL_GLUT_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#cmakedefine HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#cmakedefine HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the <OpenGL/glut.h> header file. */
|
||||
#cmakedefine HAVE_OPENGL_GLUT_H 1
|
||||
|
||||
/* Have PTHREAD_PRIO_INHERIT. */
|
||||
#cmakedefine HAVE_PTHREAD_PRIO_INHERIT @HAVE_PTHREAD_PRIO_INHERIT@
|
||||
|
||||
/* Define to 1 if you have the <shlwapi.h> header file. */
|
||||
#cmakedefine HAVE_SHLWAPI_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#cmakedefine HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#cmakedefine HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#cmakedefine HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#cmakedefine HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#cmakedefine HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#cmakedefine HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#cmakedefine HAVE_UNISTD_H 1
|
||||
|
||||
@ -93,9 +63,6 @@
|
||||
/* Define to the version of this package. */
|
||||
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#cmakedefine STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#cmakedefine VERSION "@VERSION@"
|
||||
|
||||
|
@ -18,7 +18,8 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
|
||||
unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
check_c_source_compiles("
|
||||
check_c_source_compiles(
|
||||
"
|
||||
#include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\"
|
||||
int main(void) {
|
||||
#if !defined(WEBP_USE_${WEBP_SIMD_FLAG})
|
||||
@ -26,7 +27,8 @@ function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
" WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
|
||||
"
|
||||
WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
|
||||
cmake_pop_check_state()
|
||||
if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
|
||||
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE)
|
||||
@ -52,17 +54,14 @@ if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||
endif()
|
||||
set(SIMD_DISABLE_FLAGS)
|
||||
else()
|
||||
set(SIMD_ENABLE_FLAGS
|
||||
"-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
|
||||
set(SIMD_DISABLE_FLAGS
|
||||
"-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
|
||||
set(SIMD_ENABLE_FLAGS "-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
|
||||
set(SIMD_DISABLE_FLAGS "-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
|
||||
endif()
|
||||
|
||||
set(WEBP_SIMD_FILES_TO_NOT_INCLUDE)
|
||||
set(WEBP_SIMD_FILES_TO_INCLUDE)
|
||||
set(WEBP_SIMD_FLAGS_TO_INCLUDE)
|
||||
|
||||
if(${ANDROID})
|
||||
if(ANDROID AND ANDROID_ABI)
|
||||
if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
|
||||
# This is because Android studio uses the configuration "-march=armv7-a
|
||||
# -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon
|
||||
@ -75,8 +74,8 @@ list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH)
|
||||
math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1")
|
||||
|
||||
foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
|
||||
# With Emscripten 2.0.9 -msimd128 -mfpu=neon will enable NEON, but the
|
||||
# source will fail to compile.
|
||||
# With Emscripten 2.0.9 -msimd128 -mfpu=neon will enable NEON, but the source
|
||||
# will fail to compile.
|
||||
if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 2)
|
||||
break()
|
||||
endif()
|
||||
@ -107,8 +106,9 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
|
||||
endif()
|
||||
# Check which files we should include or not.
|
||||
list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION)
|
||||
file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../"
|
||||
"src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
|
||||
file(GLOB SIMD_FILES
|
||||
"${CMAKE_CURRENT_LIST_DIR}/../sharpyuv/*${WEBP_SIMD_FILE_EXTENSION}"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
|
||||
if(WEBP_HAVE_${WEBP_SIMD_FLAG})
|
||||
# Memorize the file and flags.
|
||||
foreach(FILE ${SIMD_FILES})
|
||||
@ -142,11 +142,9 @@ foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
|
||||
set(COMMON_PATTERNS)
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG})
|
||||
check_c_source_compiles("int main(void) {return 0;}"
|
||||
FLAG_${SIMD_COMPILE_FLAG}
|
||||
FAIL_REGEX
|
||||
"warning: argument unused during compilation:"
|
||||
${COMMON_PATTERNS})
|
||||
check_c_source_compiles(
|
||||
"int main(void) {return 0;}" FLAG_${SIMD_COMPILE_FLAG} FAIL_REGEX
|
||||
"warning: argument unused during compilation:" ${COMMON_PATTERNS})
|
||||
if(NOT FLAG_${SIMD_COMPILE_FLAG})
|
||||
unset(HAS_COMPILE_FLAG)
|
||||
unset(HAS_COMPILE_FLAG CACHE)
|
||||
|
134
cmake/deps.cmake
134
cmake/deps.cmake
@ -10,24 +10,30 @@
|
||||
|
||||
# Check for compiler options.
|
||||
include(CheckCSourceCompiles)
|
||||
check_c_source_compiles("
|
||||
check_c_source_compiles(
|
||||
"
|
||||
int main(void) {
|
||||
(void)__builtin_bswap16(0);
|
||||
return 0;
|
||||
}
|
||||
" HAVE_BUILTIN_BSWAP16)
|
||||
check_c_source_compiles("
|
||||
"
|
||||
HAVE_BUILTIN_BSWAP16)
|
||||
check_c_source_compiles(
|
||||
"
|
||||
int main(void) {
|
||||
(void)__builtin_bswap32(0);
|
||||
return 0;
|
||||
}
|
||||
" HAVE_BUILTIN_BSWAP32)
|
||||
check_c_source_compiles("
|
||||
"
|
||||
HAVE_BUILTIN_BSWAP32)
|
||||
check_c_source_compiles(
|
||||
"
|
||||
int main(void) {
|
||||
(void)__builtin_bswap64(0);
|
||||
return 0;
|
||||
}
|
||||
" HAVE_BUILTIN_BSWAP64)
|
||||
"
|
||||
HAVE_BUILTIN_BSWAP64)
|
||||
|
||||
# Check for libraries.
|
||||
if(WEBP_USE_THREAD)
|
||||
@ -37,15 +43,7 @@ if(WEBP_USE_THREAD)
|
||||
if(CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
|
||||
endif()
|
||||
check_c_source_compiles("
|
||||
#include <pthread.h>
|
||||
int main (void) {
|
||||
int attr = PTHREAD_PRIO_INHERIT;
|
||||
return attr;
|
||||
}
|
||||
" FLAG_HAVE_PTHREAD_PRIO_INHERIT)
|
||||
set(HAVE_PTHREAD_PRIO_INHERIT ${FLAG_HAVE_PTHREAD_PRIO_INHERIT})
|
||||
list(APPEND WEBP_DEP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
|
||||
list(APPEND WEBP_DEP_LIBRARIES Threads::Threads)
|
||||
endif()
|
||||
set(WEBP_USE_THREAD ${Threads_FOUND})
|
||||
endif()
|
||||
@ -59,89 +57,88 @@ set(WEBP_HAVE_GL ${OPENGL_FOUND})
|
||||
|
||||
# Check if we need to link to the C math library. We do not look for it as it is
|
||||
# not found when cross-compiling, while it is here.
|
||||
check_c_source_compiles("
|
||||
check_c_source_compiles(
|
||||
"
|
||||
#include <math.h>
|
||||
int main(int argc, char** argv) {
|
||||
return (int)pow(argc, 2.5);
|
||||
}
|
||||
" HAVE_MATH_LIBRARY)
|
||||
"
|
||||
HAVE_MATH_LIBRARY)
|
||||
if(NOT HAVE_MATH_LIBRARY)
|
||||
message(STATUS "Adding -lm flag.")
|
||||
list(APPEND SHARPYUV_DEP_LIBRARIES m)
|
||||
list(APPEND WEBP_DEP_LIBRARIES m)
|
||||
endif()
|
||||
|
||||
# Find the standard image libraries.
|
||||
set(WEBP_DEP_IMG_LIBRARIES)
|
||||
set(WEBP_DEP_IMG_INCLUDE_DIRS)
|
||||
foreach(I_LIB PNG JPEG TIFF)
|
||||
find_package(${I_LIB})
|
||||
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
|
||||
if(${I_LIB}_FOUND)
|
||||
list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES})
|
||||
list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIR}
|
||||
${${I_LIB}_INCLUDE_DIRS})
|
||||
if(WEBP_FIND_IMG_LIBS)
|
||||
foreach(I_LIB PNG JPEG TIFF)
|
||||
# Disable tiff when compiling in static mode as it is failing on Ubuntu.
|
||||
if(WEBP_LINK_STATIC AND ${I_LIB} STREQUAL "TIFF")
|
||||
message(STATUS "TIFF is disabled when statically linking.")
|
||||
continue()
|
||||
endif()
|
||||
find_package(${I_LIB})
|
||||
set(WEBP_HAVE_${I_LIB} ${${I_LIB}_FOUND})
|
||||
if(${I_LIB}_FOUND)
|
||||
list(APPEND WEBP_DEP_IMG_LIBRARIES ${${I_LIB}_LIBRARIES})
|
||||
list(APPEND WEBP_DEP_IMG_INCLUDE_DIRS ${${I_LIB}_INCLUDE_DIR}
|
||||
${${I_LIB}_INCLUDE_DIRS})
|
||||
endif()
|
||||
endforeach()
|
||||
if(WEBP_DEP_IMG_INCLUDE_DIRS)
|
||||
list(REMOVE_DUPLICATES WEBP_DEP_IMG_INCLUDE_DIRS)
|
||||
endif()
|
||||
endforeach()
|
||||
if(WEBP_DEP_IMG_INCLUDE_DIRS)
|
||||
list(REMOVE_DUPLICATES WEBP_DEP_IMG_INCLUDE_DIRS)
|
||||
endif()
|
||||
|
||||
# GIF detection, gifdec isn't part of the imageio lib.
|
||||
include(CMakePushCheckState)
|
||||
set(WEBP_DEP_GIF_LIBRARIES)
|
||||
set(WEBP_DEP_GIF_INCLUDE_DIRS)
|
||||
find_package(GIF)
|
||||
set(WEBP_HAVE_GIF ${GIF_FOUND})
|
||||
if(GIF_FOUND)
|
||||
# GIF find_package only locates the header and library, it doesn't fail
|
||||
# compile tests when detecting the version, but falls back to 3 (as of at
|
||||
# least cmake 3.7.2). Make sure the library links to avoid incorrect detection
|
||||
# when cross compiling.
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR})
|
||||
check_c_source_compiles("
|
||||
# GIF detection, gifdec isn't part of the imageio lib.
|
||||
include(CMakePushCheckState)
|
||||
set(WEBP_DEP_GIF_LIBRARIES)
|
||||
set(WEBP_DEP_GIF_INCLUDE_DIRS)
|
||||
find_package(GIF)
|
||||
set(WEBP_HAVE_GIF ${GIF_FOUND})
|
||||
if(GIF_FOUND)
|
||||
# GIF find_package only locates the header and library, it doesn't fail
|
||||
# compile tests when detecting the version, but falls back to 3 (as of at
|
||||
# least cmake 3.7.2). Make sure the library links to avoid incorrect
|
||||
# detection when cross compiling.
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${GIF_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_INCLUDES ${GIF_INCLUDE_DIR})
|
||||
check_c_source_compiles(
|
||||
"
|
||||
#include <gif_lib.h>
|
||||
int main(void) {
|
||||
(void)DGifOpenFileHandle;
|
||||
return 0;
|
||||
}
|
||||
" GIF_COMPILES)
|
||||
cmake_pop_check_state()
|
||||
if(GIF_COMPILES)
|
||||
list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES})
|
||||
list(APPEND WEBP_DEP_GIF_INCLUDE_DIRS ${GIF_INCLUDE_DIR})
|
||||
else()
|
||||
unset(GIF_FOUND)
|
||||
"
|
||||
GIF_COMPILES)
|
||||
cmake_pop_check_state()
|
||||
if(GIF_COMPILES)
|
||||
list(APPEND WEBP_DEP_GIF_LIBRARIES ${GIF_LIBRARIES})
|
||||
list(APPEND WEBP_DEP_GIF_INCLUDE_DIRS ${GIF_INCLUDE_DIR})
|
||||
else()
|
||||
unset(GIF_FOUND)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for specific headers.
|
||||
include(CheckIncludeFiles)
|
||||
check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS)
|
||||
check_include_files(dlfcn.h HAVE_DLFCN_H)
|
||||
check_include_files(GLUT/glut.h HAVE_GLUT_GLUT_H)
|
||||
check_include_files(GL/glut.h HAVE_GL_GLUT_H)
|
||||
check_include_files(inttypes.h HAVE_INTTYPES_H)
|
||||
check_include_files(memory.h HAVE_MEMORY_H)
|
||||
check_include_files(OpenGL/glut.h HAVE_OPENGL_GLUT_H)
|
||||
check_include_files(shlwapi.h HAVE_SHLWAPI_H)
|
||||
check_include_files(stdint.h HAVE_STDINT_H)
|
||||
check_include_files(stdlib.h HAVE_STDLIB_H)
|
||||
check_include_files(strings.h HAVE_STRINGS_H)
|
||||
check_include_files(string.h HAVE_STRING_H)
|
||||
check_include_files(sys/stat.h HAVE_SYS_STAT_H)
|
||||
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
|
||||
check_include_files(unistd.h HAVE_UNISTD_H)
|
||||
check_include_files(wincodec.h HAVE_WINCODEC_H)
|
||||
check_include_files(windows.h HAVE_WINDOWS_H)
|
||||
|
||||
# Windows specifics
|
||||
if(HAVE_WINCODEC_H)
|
||||
list(APPEND WEBP_DEP_LIBRARIES
|
||||
shlwapi
|
||||
ole32
|
||||
windowscodecs)
|
||||
list(APPEND WEBP_DEP_LIBRARIES shlwapi ole32 windowscodecs)
|
||||
endif()
|
||||
|
||||
# Check for SIMD extensions.
|
||||
@ -153,17 +150,12 @@ set(PACKAGE_NAME ${PROJECT_NAME})
|
||||
|
||||
# Read from configure.ac.
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/configure.ac CONFIGURE_AC)
|
||||
string(REGEX MATCHALL
|
||||
"\\[([0-9a-z\\.:/]*)\\]"
|
||||
CONFIGURE_AC_PACKAGE_INFO
|
||||
string(REGEX MATCHALL "\\[([0-9a-z\\.:/]*)\\]" CONFIGURE_AC_PACKAGE_INFO
|
||||
${CONFIGURE_AC})
|
||||
function(strip_bracket VAR)
|
||||
string(LENGTH ${${VAR}} TMP_LEN)
|
||||
math(EXPR TMP_LEN ${TMP_LEN}-2)
|
||||
string(SUBSTRING ${${VAR}}
|
||||
1
|
||||
${TMP_LEN}
|
||||
TMP_SUB)
|
||||
string(SUBSTRING ${${VAR}} 1 ${TMP_LEN} TMP_SUB)
|
||||
set(${VAR} ${TMP_SUB} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
27
configure.ac
27
configure.ac
@ -1,5 +1,5 @@
|
||||
AC_INIT([libwebp], [1.2.2],
|
||||
[https://bugs.chromium.org/p/webp],,
|
||||
AC_INIT([libwebp], [1.4.0],
|
||||
[https://issues.webmproject.org],,
|
||||
[https://developers.google.com/speed/webp])
|
||||
AC_CANONICAL_HOST
|
||||
AC_PREREQ([2.60])
|
||||
@ -9,7 +9,8 @@ dnl === automake >= 1.12 requires this for 'unusual archivers' support.
|
||||
dnl === it must occur before LT_INIT (AC_PROG_LIBTOOL).
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
dnl === AC_PROG_LIBTOOL is deprecated.
|
||||
m4_ifdef([LT_INIT], [LT_INIT], [AC_PROG_LIBTOOL])
|
||||
AC_PROG_SED
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
@ -27,7 +28,8 @@ AC_ARG_ENABLE([everything],
|
||||
AS_HELP_STRING([--enable-everything],
|
||||
[Enable all optional targets. These can still be
|
||||
disabled with --disable-target]),
|
||||
[SET_IF_UNSET([enable_libwebpdecoder], [$enableval])
|
||||
[SET_IF_UNSET([enable_libsharpyuv], [$enableval])
|
||||
SET_IF_UNSET([enable_libwebpdecoder], [$enableval])
|
||||
SET_IF_UNSET([enable_libwebpdemux], [$enableval])
|
||||
SET_IF_UNSET([enable_libwebpextras], [$enableval])
|
||||
SET_IF_UNSET([enable_libwebpmux], [$enableval])])
|
||||
@ -104,6 +106,7 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wconstant-conversion])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wdeclaration-after-statement])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra-semi-stmt])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wfloat-conversion])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-nonliteral])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-security])
|
||||
@ -113,6 +116,7 @@ TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wparentheses-equality])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshadow])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wstrict-prototypes])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wundef])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code-aggressive])
|
||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code])
|
||||
@ -462,7 +466,7 @@ AC_ARG_ENABLE([sdl],
|
||||
@<:@default=auto@:>@]))
|
||||
AS_IF([test "x$enable_sdl" != "xno"], [
|
||||
CLEAR_LIBVARS([SDL])
|
||||
AC_PATH_PROGS([LIBSDL_CONFIG], [sdl-config])
|
||||
AC_PATH_PROGS([LIBSDL_CONFIG], [sdl2-config])
|
||||
if test -n "$LIBSDL_CONFIG"; then
|
||||
SDL_INCLUDES=`$LIBSDL_CONFIG --cflags`
|
||||
SDL_LIBS="`$LIBSDL_CONFIG --libs`"
|
||||
@ -472,13 +476,12 @@ AS_IF([test "x$enable_sdl" != "xno"], [
|
||||
|
||||
sdl_header="no"
|
||||
LIBCHECK_PROLOGUE([SDL])
|
||||
AC_CHECK_HEADER([SDL/SDL.h], [sdl_header="SDL/SDL.h"],
|
||||
[AC_CHECK_HEADER([SDL.h], [sdl_header="SDL.h"],
|
||||
[AC_MSG_WARN(SDL library not available - no sdl.h)])])
|
||||
AC_CHECK_HEADER([SDL2/SDL.h], [sdl_header="SDL2/SDL.h"],
|
||||
[AC_MSG_WARN(SDL2 library not available - no SDL.h)])
|
||||
if test x"$sdl_header" != "xno"; then
|
||||
AC_LANG_PUSH(C)
|
||||
SDL_SAVED_LIBS="$LIBS"
|
||||
for lib in "" "-lSDL" "-lSDLmain -lSDL"; do
|
||||
for lib in "" "-lSDL2" "-lSDL2main -lSDL2"; do
|
||||
LIBS="$SDL_SAVED_LIBS $lib"
|
||||
# Perform a full link to ensure SDL_main is resolved if needed.
|
||||
AC_LINK_IFELSE(
|
||||
@ -747,17 +750,21 @@ fi
|
||||
|
||||
dnl =========================
|
||||
|
||||
dnl Add an empty webp_libname_prefix variable for use in *.pc.in.
|
||||
AC_SUBST([webp_libname_prefix])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([src/webp/config.h])
|
||||
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \
|
||||
examples/Makefile extras/Makefile imageio/Makefile \
|
||||
sharpyuv/Makefile sharpyuv/libsharpyuv.pc \
|
||||
src/dec/Makefile src/enc/Makefile src/dsp/Makefile \
|
||||
src/demux/Makefile src/mux/Makefile \
|
||||
src/utils/Makefile \
|
||||
src/libwebp.pc src/libwebpdecoder.pc \
|
||||
src/demux/libwebpdemux.pc src/mux/libwebpmux.pc])
|
||||
|
||||
|
||||
dnl fix exports from MinGW builds
|
||||
AC_CONFIG_COMMANDS_POST([$SED -i 's/-DDLL_EXPORT/-DWEBP_DLL/' config.status])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_NOTICE([
|
||||
|
29
doc/README
29
doc/README
@ -1,29 +0,0 @@
|
||||
|
||||
Generate libwebp Container Spec Docs from Text Source
|
||||
=====================================================
|
||||
|
||||
HTML generation requires kramdown [1], easily installed as a
|
||||
rubygem [2]. Rubygems installation should satisfy dependencies
|
||||
automatically.
|
||||
|
||||
[1]: https://kramdown.gettalong.org/
|
||||
[2]: https://rubygems.org/
|
||||
|
||||
HTML generation can then be done from the project root:
|
||||
|
||||
$ kramdown doc/webp-container-spec.txt --template doc/template.html > \
|
||||
doc/output/webp-container-spec.html
|
||||
|
||||
kramdown can optionally syntax highlight code blocks, using CodeRay [3],
|
||||
a dependency of kramdown that rubygems will install automatically. The
|
||||
following will apply inline CSS styling; an external stylesheet is not
|
||||
needed.
|
||||
|
||||
$ kramdown doc/webp-lossless-bitstream-spec.txt --template \
|
||||
doc/template.html --coderay-css style --coderay-line-numbers ' ' \
|
||||
--coderay-default-lang c > \
|
||||
doc/output/webp-lossless-bitstream-spec.html
|
||||
|
||||
Optimally, use kramdown 0.13.7 or newer if syntax highlighting desired.
|
||||
|
||||
[3]: https://github.com/rubychan/coderay
|
385
doc/api.md
Normal file
385
doc/api.md
Normal file
@ -0,0 +1,385 @@
|
||||
# WebP APIs
|
||||
|
||||
## Encoding API
|
||||
|
||||
The main encoding functions are available in the header src/webp/encode.h
|
||||
|
||||
The ready-to-use ones are:
|
||||
|
||||
```c
|
||||
size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height, int stride,
|
||||
float quality_factor, uint8_t** output);
|
||||
size_t WebPEncodeBGR(const uint8_t* bgr, int width, int height, int stride,
|
||||
float quality_factor, uint8_t** output);
|
||||
size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride,
|
||||
float quality_factor, uint8_t** output);
|
||||
size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride,
|
||||
float quality_factor, uint8_t** output);
|
||||
```
|
||||
|
||||
They will convert raw RGB samples to a WebP data. The only control supplied is
|
||||
the quality factor.
|
||||
|
||||
There are some variants for using the lossless format:
|
||||
|
||||
```c
|
||||
size_t WebPEncodeLosslessRGB(const uint8_t* rgb, int width, int height,
|
||||
int stride, uint8_t** output);
|
||||
size_t WebPEncodeLosslessBGR(const uint8_t* bgr, int width, int height,
|
||||
int stride, uint8_t** output);
|
||||
size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height,
|
||||
int stride, uint8_t** output);
|
||||
size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height,
|
||||
int stride, uint8_t** output);
|
||||
```
|
||||
|
||||
Of course in this case, no quality factor is needed since the compression occurs
|
||||
without loss of the input values, at the expense of larger output sizes.
|
||||
|
||||
### Advanced encoding API
|
||||
|
||||
A more advanced API is based on the WebPConfig and WebPPicture structures.
|
||||
|
||||
WebPConfig contains the encoding settings and is not tied to a particular
|
||||
picture. WebPPicture contains input data, on which some WebPConfig will be used
|
||||
for compression. The encoding flow looks like:
|
||||
|
||||
```c
|
||||
#include <webp/encode.h>
|
||||
|
||||
// Setup a config, starting form a preset and tuning some additional
|
||||
// parameters
|
||||
WebPConfig config;
|
||||
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) {
|
||||
return 0; // version error
|
||||
}
|
||||
// ... additional tuning
|
||||
config.sns_strength = 90;
|
||||
config.filter_sharpness = 6;
|
||||
config_error = WebPValidateConfig(&config); // not mandatory, but useful
|
||||
|
||||
// Setup the input data
|
||||
WebPPicture pic;
|
||||
if (!WebPPictureInit(&pic)) {
|
||||
return 0; // version error
|
||||
}
|
||||
pic.width = width;
|
||||
pic.height = height;
|
||||
// allocated picture of dimension width x height
|
||||
if (!WebPPictureAlloc(&pic)) {
|
||||
return 0; // memory error
|
||||
}
|
||||
// at this point, 'pic' has been initialized as a container,
|
||||
// and can receive the Y/U/V samples.
|
||||
// Alternatively, one could use ready-made import functions like
|
||||
// WebPPictureImportRGB(), which will take care of memory allocation.
|
||||
// In any case, past this point, one will have to call
|
||||
// WebPPictureFree(&pic) to reclaim memory.
|
||||
|
||||
// Set up a byte-output write method. WebPMemoryWriter, for instance.
|
||||
WebPMemoryWriter wrt;
|
||||
WebPMemoryWriterInit(&wrt); // initialize 'wrt'
|
||||
|
||||
pic.writer = MyFileWriter;
|
||||
pic.custom_ptr = my_opaque_structure_to_make_MyFileWriter_work;
|
||||
|
||||
// Compress!
|
||||
int ok = WebPEncode(&config, &pic); // ok = 0 => error occurred!
|
||||
WebPPictureFree(&pic); // must be called independently of the 'ok' result.
|
||||
|
||||
// output data should have been handled by the writer at that point.
|
||||
// -> compressed data is the memory buffer described by wrt.mem / wrt.size
|
||||
|
||||
// deallocate the memory used by compressed data
|
||||
WebPMemoryWriterClear(&wrt);
|
||||
```
|
||||
|
||||
## Decoding API
|
||||
|
||||
This is mainly just one function to call:
|
||||
|
||||
```c
|
||||
#include "webp/decode.h"
|
||||
uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
|
||||
int* width, int* height);
|
||||
```
|
||||
|
||||
Please have a look at the file src/webp/decode.h for the details. There are
|
||||
variants for decoding in BGR/RGBA/ARGB/BGRA order, along with decoding to raw
|
||||
Y'CbCr samples. One can also decode the image directly into a pre-allocated
|
||||
buffer.
|
||||
|
||||
To detect a WebP file and gather the picture's dimensions, the function:
|
||||
|
||||
```c
|
||||
int WebPGetInfo(const uint8_t* data, size_t data_size,
|
||||
int* width, int* height);
|
||||
```
|
||||
|
||||
is supplied. No decoding is involved when using it.
|
||||
|
||||
### Incremental decoding API
|
||||
|
||||
In the case when data is being progressively transmitted, pictures can still be
|
||||
incrementally decoded using a slightly more complicated API. Decoder state is
|
||||
stored into an instance of the WebPIDecoder object. This object can be created
|
||||
with the purpose of decoding either RGB or Y'CbCr samples. For instance:
|
||||
|
||||
```c
|
||||
WebPDecBuffer buffer;
|
||||
WebPInitDecBuffer(&buffer);
|
||||
buffer.colorspace = MODE_BGR;
|
||||
...
|
||||
WebPIDecoder* idec = WebPINewDecoder(&buffer);
|
||||
```
|
||||
|
||||
As data is made progressively available, this incremental-decoder object can be
|
||||
used to decode the picture further. There are two (mutually exclusive) ways to
|
||||
pass freshly arrived data:
|
||||
|
||||
either by appending the fresh bytes:
|
||||
|
||||
```c
|
||||
WebPIAppend(idec, fresh_data, size_of_fresh_data);
|
||||
```
|
||||
|
||||
or by just mentioning the new size of the transmitted data:
|
||||
|
||||
```c
|
||||
WebPIUpdate(idec, buffer, size_of_transmitted_buffer);
|
||||
```
|
||||
|
||||
Note that 'buffer' can be modified between each call to WebPIUpdate, in
|
||||
particular when the buffer is resized to accommodate larger data.
|
||||
|
||||
These functions will return the decoding status: either VP8_STATUS_SUSPENDED if
|
||||
decoding is not finished yet or VP8_STATUS_OK when decoding is done. Any other
|
||||
status is an error condition.
|
||||
|
||||
The 'idec' object must always be released (even upon an error condition) by
|
||||
calling: WebPIDelete(idec).
|
||||
|
||||
To retrieve partially decoded picture samples, one must use the corresponding
|
||||
method: WebPIDecGetRGB or WebPIDecGetYUVA. It will return the last displayable
|
||||
pixel row.
|
||||
|
||||
Lastly, note that decoding can also be performed into a pre-allocated pixel
|
||||
buffer. This buffer must be passed when creating a WebPIDecoder, calling
|
||||
WebPINewRGB() or WebPINewYUVA().
|
||||
|
||||
Please have a look at the src/webp/decode.h header for further details.
|
||||
|
||||
### Advanced Decoding API
|
||||
|
||||
WebP decoding supports an advanced API which provides on-the-fly cropping and
|
||||
rescaling, something of great usefulness on memory-constrained environments like
|
||||
mobile phones. Basically, the memory usage will scale with the output's size,
|
||||
not the input's, when one only needs a quick preview or a zoomed in portion of
|
||||
an otherwise too-large picture. Some CPU can be saved too, incidentally.
|
||||
|
||||
```c
|
||||
// A) Init a configuration object
|
||||
WebPDecoderConfig config;
|
||||
CHECK(WebPInitDecoderConfig(&config));
|
||||
|
||||
// B) optional: retrieve the bitstream's features.
|
||||
CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK);
|
||||
|
||||
// C) Adjust 'config' options, if needed
|
||||
config.options.no_fancy_upsampling = 1;
|
||||
config.options.use_scaling = 1;
|
||||
config.options.scaled_width = scaledWidth();
|
||||
config.options.scaled_height = scaledHeight();
|
||||
// etc.
|
||||
|
||||
// D) Specify 'config' output options for specifying output colorspace.
|
||||
// Optionally the external image decode buffer can also be specified.
|
||||
config.output.colorspace = MODE_BGRA;
|
||||
// Optionally, the config.output can be pointed to an external buffer as
|
||||
// well for decoding the image. This externally supplied memory buffer
|
||||
// should be big enough to store the decoded picture.
|
||||
config.output.u.RGBA.rgba = (uint8_t*) memory_buffer;
|
||||
config.output.u.RGBA.stride = scanline_stride;
|
||||
config.output.u.RGBA.size = total_size_of_the_memory_buffer;
|
||||
config.output.is_external_memory = 1;
|
||||
|
||||
// E) Decode the WebP image. There are two variants w.r.t decoding image.
|
||||
// The first one (E.1) decodes the full image and the second one (E.2) is
|
||||
// used to incrementally decode the image using small input buffers.
|
||||
// Any one of these steps can be used to decode the WebP image.
|
||||
|
||||
// E.1) Decode full image.
|
||||
CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK);
|
||||
|
||||
// E.2) Decode image incrementally.
|
||||
WebPIDecoder* const idec = WebPIDecode(NULL, NULL, &config);
|
||||
CHECK(idec != NULL);
|
||||
while (bytes_remaining > 0) {
|
||||
VP8StatusCode status = WebPIAppend(idec, input, bytes_read);
|
||||
if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
|
||||
bytes_remaining -= bytes_read;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
WebPIDelete(idec);
|
||||
|
||||
// F) Decoded image is now in config.output (and config.output.u.RGBA).
|
||||
// It can be saved, displayed or otherwise processed.
|
||||
|
||||
// G) Reclaim memory allocated in config's object. It's safe to call
|
||||
// this function even if the memory is external and wasn't allocated
|
||||
// by WebPDecode().
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
```
|
||||
|
||||
## WebP Mux
|
||||
|
||||
WebPMux is a 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 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, see the
|
||||
[tools documentation](tools.md).
|
||||
|
||||
### 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 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.
|
||||
|
||||
```c
|
||||
int copy_data = 0;
|
||||
WebPMux* mux = WebPMuxNew();
|
||||
// ... (Prepare image data).
|
||||
WebPMuxSetImage(mux, &image, copy_data);
|
||||
// ... (Prepare ICC profile data).
|
||||
WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
|
||||
// ... (Prepare XMP metadata).
|
||||
WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
|
||||
// Get data from mux in WebP RIFF format.
|
||||
WebPMuxAssemble(mux, &output_data);
|
||||
WebPMuxDelete(mux);
|
||||
// ... (Consume output_data; e.g. write output_data.bytes to file).
|
||||
WebPDataClear(&output_data);
|
||||
```
|
||||
|
||||
Example#2 (pseudo code): Get image and color profile data from a WebP file.
|
||||
|
||||
```c
|
||||
int copy_data = 0;
|
||||
// ... (Read data from file).
|
||||
WebPMux* mux = WebPMuxCreate(&data, copy_data);
|
||||
WebPMuxGetFrame(mux, 1, &image);
|
||||
// ... (Consume image; e.g. call WebPDecode() to decode the data).
|
||||
WebPMuxGetChunk(mux, "ICCP", &icc_profile);
|
||||
// ... (Consume icc_profile).
|
||||
WebPMuxDelete(mux);
|
||||
free(data);
|
||||
```
|
||||
|
||||
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 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.
|
||||
|
||||
```c
|
||||
WebPDemuxer* demux = WebPDemux(&webp_data);
|
||||
uint32_t width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
|
||||
uint32_t height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
|
||||
// ... (Get information about the features present in the WebP file).
|
||||
uint32_t flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
|
||||
|
||||
// ... (Iterate over all frames).
|
||||
WebPIterator iter;
|
||||
if (WebPDemuxGetFrame(demux, 1, &iter)) {
|
||||
do {
|
||||
// ... (Consume 'iter'; e.g. Decode 'iter.fragment' with WebPDecode(),
|
||||
// ... and get other frame properties like width, height, offsets etc.
|
||||
// ... see 'struct WebPIterator' below for more info).
|
||||
} while (WebPDemuxNextFrame(&iter));
|
||||
WebPDemuxReleaseIterator(&iter);
|
||||
}
|
||||
|
||||
// ... (Extract metadata).
|
||||
WebPChunkIterator chunk_iter;
|
||||
if (flags & ICCP_FLAG) WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter);
|
||||
// ... (Consume the ICC profile in 'chunk_iter.chunk').
|
||||
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||
if (flags & EXIF_FLAG) WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter);
|
||||
// ... (Consume the EXIF metadata in 'chunk_iter.chunk').
|
||||
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||
if (flags & XMP_FLAG) WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter);
|
||||
// ... (Consume the XMP metadata in 'chunk_iter.chunk').
|
||||
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||
WebPDemuxDelete(demux);
|
||||
```
|
||||
|
||||
For a detailed Demux API reference, please refer to the header file
|
||||
(src/webp/demux.h).
|
||||
|
||||
## AnimEncoder API
|
||||
|
||||
The AnimEncoder API can be used to create animated WebP images.
|
||||
|
||||
Code example:
|
||||
|
||||
```c
|
||||
WebPAnimEncoderOptions enc_options;
|
||||
WebPAnimEncoderOptionsInit(&enc_options);
|
||||
// ... (Tune 'enc_options' as needed).
|
||||
WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options);
|
||||
while(<there are more frames>) {
|
||||
WebPConfig config;
|
||||
WebPConfigInit(&config);
|
||||
// ... (Tune 'config' as needed).
|
||||
WebPAnimEncoderAdd(enc, frame, duration, &config);
|
||||
}
|
||||
WebPAnimEncoderAssemble(enc, webp_data);
|
||||
WebPAnimEncoderDelete(enc);
|
||||
// ... (Write the 'webp_data' to a file, or re-mux it further).
|
||||
```
|
||||
|
||||
For a detailed AnimEncoder API reference, please refer to the header file
|
||||
(src/webp/mux.h).
|
||||
|
||||
## AnimDecoder API
|
||||
|
||||
This AnimDecoder API allows decoding (possibly) animated WebP images.
|
||||
|
||||
Code Example:
|
||||
|
||||
```c
|
||||
WebPAnimDecoderOptions dec_options;
|
||||
WebPAnimDecoderOptionsInit(&dec_options);
|
||||
// Tune 'dec_options' as needed.
|
||||
WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
|
||||
WebPAnimInfo anim_info;
|
||||
WebPAnimDecoderGetInfo(dec, &anim_info);
|
||||
for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
|
||||
while (WebPAnimDecoderHasMoreFrames(dec)) {
|
||||
uint8_t* buf;
|
||||
int timestamp;
|
||||
WebPAnimDecoderGetNext(dec, &buf, ×tamp);
|
||||
// ... (Render 'buf' based on 'timestamp').
|
||||
// ... (Do NOT free 'buf', as it is owned by 'dec').
|
||||
}
|
||||
WebPAnimDecoderReset(dec);
|
||||
}
|
||||
const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
|
||||
// ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
|
||||
WebPAnimDecoderDelete(dec);
|
||||
```
|
||||
|
||||
For a detailed AnimDecoder API reference, please refer to the header file
|
||||
(src/webp/demux.h).
|
231
doc/building.md
Normal file
231
doc/building.md
Normal file
@ -0,0 +1,231 @@
|
||||
# Building
|
||||
|
||||
## Windows build
|
||||
|
||||
By running:
|
||||
|
||||
```batch
|
||||
nmake /f Makefile.vc CFG=release-static RTLIBCFG=static OBJDIR=output
|
||||
```
|
||||
|
||||
the directory `output\release-static\(x64|x86)\bin` will contain the tools
|
||||
cwebp.exe and dwebp.exe. The directory `output\release-static\(x64|x86)\lib`
|
||||
will contain the libwebp static library. The target architecture (x86/x64) is
|
||||
detected by Makefile.vc from the Visual Studio compiler (cl.exe) available in
|
||||
the system path.
|
||||
|
||||
## Unix build using makefile.unix
|
||||
|
||||
On platforms with GNU tools installed (gcc and make), running
|
||||
|
||||
```shell
|
||||
make -f makefile.unix
|
||||
```
|
||||
|
||||
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 makefile.unix for additional details and
|
||||
customizations.
|
||||
|
||||
## Using autoconf tools
|
||||
|
||||
Prerequisites: a compiler (e.g., gcc), make, autoconf, automake, libtool.
|
||||
|
||||
On a Debian-like system the following should install everything you need for a
|
||||
minimal build:
|
||||
|
||||
```shell
|
||||
$ sudo apt-get install gcc make autoconf automake libtool
|
||||
```
|
||||
|
||||
When building from git sources, you will need to run autogen.sh to generate the
|
||||
configure script.
|
||||
|
||||
```shell
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
should be all you need to have the following files
|
||||
|
||||
```
|
||||
/usr/local/include/webp/decode.h
|
||||
/usr/local/include/webp/encode.h
|
||||
/usr/local/include/webp/types.h
|
||||
/usr/local/lib/libwebp.*
|
||||
/usr/local/bin/cwebp
|
||||
/usr/local/bin/dwebp
|
||||
```
|
||||
|
||||
installed.
|
||||
|
||||
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.
|
||||
|
||||
## Building for MIPS Linux
|
||||
|
||||
MIPS Linux toolchain stable available releases can be found at:
|
||||
https://community.imgtec.com/developers/mips/tools/codescape-mips-sdk/available-releases/
|
||||
|
||||
```shell
|
||||
# Add toolchain to PATH
|
||||
export PATH=$PATH:/path/to/toolchain/bin
|
||||
|
||||
# 32-bit build for mips32r5 (p5600)
|
||||
HOST=mips-mti-linux-gnu
|
||||
MIPS_CFLAGS="-O3 -mips32r5 -mabi=32 -mtune=p5600 -mmsa -mfp64 \
|
||||
-msched-weight -mload-store-pairs -fPIE"
|
||||
MIPS_LDFLAGS="-mips32r5 -mabi=32 -mmsa -mfp64 -pie"
|
||||
|
||||
# 64-bit build for mips64r6 (i6400)
|
||||
HOST=mips-img-linux-gnu
|
||||
MIPS_CFLAGS="-O3 -mips64r6 -mabi=64 -mtune=i6400 -mmsa -mfp64 \
|
||||
-msched-weight -mload-store-pairs -fPIE"
|
||||
MIPS_LDFLAGS="-mips64r6 -mabi=64 -mmsa -mfp64 -pie"
|
||||
|
||||
./configure --host=${HOST} --build=`config.guess` \
|
||||
CC="${HOST}-gcc -EL" \
|
||||
CFLAGS="$MIPS_CFLAGS" \
|
||||
LDFLAGS="$MIPS_LDFLAGS"
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
## Building libwebp - Using vcpkg
|
||||
|
||||
You can download and install libwebp using the
|
||||
[vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
```shell
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install libwebp
|
||||
```
|
||||
|
||||
The libwebp port in vcpkg is kept up to date by Microsoft team members and
|
||||
community contributors. If the version is out of date, please
|
||||
[create an issue or pull request](https://github.com/Microsoft/vcpkg) on the
|
||||
vcpkg repository.
|
||||
|
||||
## CMake
|
||||
|
||||
With CMake, you can compile libwebp, cwebp, dwebp, gif2webp, img2webp, webpinfo
|
||||
and the JS bindings.
|
||||
|
||||
Prerequisites: a compiler (e.g., gcc with autotools) and CMake.
|
||||
|
||||
On a Debian-like system the following should install everything you need for a
|
||||
minimal build:
|
||||
|
||||
```shell
|
||||
$ sudo apt-get install build-essential cmake
|
||||
```
|
||||
|
||||
When building from git sources, you will need to run cmake to generate the
|
||||
makefiles.
|
||||
|
||||
```shell
|
||||
mkdir build && cd build && cmake ../
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
If you also want any of the executables, you will need to enable them through
|
||||
CMake, e.g.:
|
||||
|
||||
```shell
|
||||
cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../
|
||||
```
|
||||
|
||||
or through your favorite interface (like ccmake or cmake-qt-gui).
|
||||
|
||||
Use option `-DWEBP_UNICODE=ON` for Unicode support on Windows (with chcp 65001).
|
||||
|
||||
Finally, once installed, you can also use WebP in your CMake project by doing:
|
||||
|
||||
```cmake
|
||||
find_package(WebP)
|
||||
```
|
||||
|
||||
which will define the CMake variables WebP_INCLUDE_DIRS and WebP_LIBRARIES.
|
||||
|
||||
## Gradle
|
||||
|
||||
The support for Gradle is minimal: it only helps you compile libwebp, cwebp and
|
||||
dwebp and webpmux_example.
|
||||
|
||||
Prerequisites: a compiler (e.g., gcc with autotools) and gradle.
|
||||
|
||||
On a Debian-like system the following should install everything you need for a
|
||||
minimal build:
|
||||
|
||||
```shell
|
||||
$ sudo apt-get install build-essential gradle
|
||||
```
|
||||
|
||||
When building from git sources, you will need to run the Gradle wrapper with the
|
||||
appropriate target, e.g. :
|
||||
|
||||
```shell
|
||||
./gradlew buildAllExecutables
|
||||
```
|
||||
|
||||
## SWIG bindings
|
||||
|
||||
To generate language bindings from swig/libwebp.swig at least swig-1.3
|
||||
(http://www.swig.org) is required.
|
||||
|
||||
Currently the following functions are mapped:
|
||||
|
||||
Decode:
|
||||
|
||||
```
|
||||
WebPGetDecoderVersion
|
||||
WebPGetInfo
|
||||
WebPDecodeRGBA
|
||||
WebPDecodeARGB
|
||||
WebPDecodeBGRA
|
||||
WebPDecodeBGR
|
||||
WebPDecodeRGB
|
||||
```
|
||||
|
||||
Encode:
|
||||
|
||||
```
|
||||
WebPGetEncoderVersion
|
||||
WebPEncodeRGBA
|
||||
WebPEncodeBGRA
|
||||
WebPEncodeRGB
|
||||
WebPEncodeBGR
|
||||
WebPEncodeLosslessRGBA
|
||||
WebPEncodeLosslessBGRA
|
||||
WebPEncodeLosslessRGB
|
||||
WebPEncodeLosslessBGR
|
||||
```
|
||||
|
||||
See also the [swig documentation](../swig/README.md) for more detailed build
|
||||
instructions and usage examples.
|
||||
|
||||
### Java bindings
|
||||
|
||||
To build the swig-generated JNI wrapper code at least JDK-1.5 (or equivalent) is
|
||||
necessary for enum support. The output is intended to be a shared object / DLL
|
||||
that can be loaded via `System.loadLibrary("webp_jni")`.
|
||||
|
||||
### Python bindings
|
||||
|
||||
To build the swig-generated Python extension code at least Python 2.6 is
|
||||
required. Python < 2.6 may build with some minor changes to libwebp.swig or the
|
||||
generated code, but is untested.
|
||||
|
||||
## Javascript decoder
|
||||
|
||||
Libwebp can be compiled into a JavaScript decoder using Emscripten and CMake.
|
||||
See the [corresponding documentation](../webp_js/README.md)
|
27
doc/specs_generation.md
Normal file
27
doc/specs_generation.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Generate libwebp Container Spec Docs from Text Source
|
||||
|
||||
HTML generation requires [kramdown](https://kramdown.gettalong.org/), easily
|
||||
installed as a [rubygem](https://rubygems.org/). Rubygems installation should
|
||||
satisfy dependencies automatically.
|
||||
|
||||
HTML generation can then be done from the project root:
|
||||
|
||||
```shell
|
||||
$ kramdown doc/webp-container-spec.txt --template doc/template.html > \
|
||||
doc/output/webp-container-spec.html
|
||||
```
|
||||
|
||||
kramdown can optionally syntax highlight code blocks, using
|
||||
[CodeRay](https://github.com/rubychan/coderay), a dependency of kramdown that
|
||||
rubygems will install automatically. The following will apply inline CSS
|
||||
styling; an external stylesheet is not needed.
|
||||
|
||||
```shell
|
||||
$ kramdown doc/webp-lossless-bitstream-spec.txt \
|
||||
--template doc/template.html \
|
||||
-x syntax-coderay --syntax-highlighter coderay \
|
||||
--syntax-highlighter-opts "{default_lang: c, line_numbers: , css: style}" \
|
||||
> doc/output/webp-lossless-bitstream-spec.html
|
||||
```
|
||||
|
||||
Optimally, use kramdown 0.13.7 or newer if syntax highlighting desired.
|
519
doc/tools.md
Normal file
519
doc/tools.md
Normal file
@ -0,0 +1,519 @@
|
||||
# WebP tools
|
||||
|
||||
## Encoding tool
|
||||
|
||||
The examples/ directory contains tools for encoding (cwebp) and decoding (dwebp)
|
||||
images.
|
||||
|
||||
The easiest use should look like:
|
||||
|
||||
```shell
|
||||
cwebp input.png -q 80 -o output.webp
|
||||
```
|
||||
|
||||
which will convert the input file to a WebP file using a quality factor of 80 on
|
||||
a 0->100 scale (0 being the lowest quality, 100 being the best. Default value is
|
||||
75).
|
||||
|
||||
You might want to try the `-lossless` flag too, which will compress the source
|
||||
(in RGBA format) without any loss. The `-q` quality parameter will in this case
|
||||
control the amount of processing time spent trying to make the output file as
|
||||
small as possible.
|
||||
|
||||
A longer list of options is available using the `-longhelp` command line flag:
|
||||
|
||||
```shell
|
||||
> cwebp -longhelp
|
||||
Usage:
|
||||
cwebp [-preset <...>] [options] in_file [-o out_file]
|
||||
```
|
||||
|
||||
If input size (-s) for an image is not specified, it is assumed to be a PNG,
|
||||
JPEG, TIFF or WebP file. Note: Animated PNG and WebP files are not supported.
|
||||
|
||||
Options:
|
||||
|
||||
```
|
||||
-h / -help ............. short help
|
||||
-H / -longhelp ......... long help
|
||||
-q <float> ............. quality factor (0:small..100:big), default=75
|
||||
-alpha_q <int> ......... transparency-compression quality (0..100),
|
||||
default=100
|
||||
-preset <string> ....... preset setting, one of:
|
||||
default, photo, picture,
|
||||
drawing, icon, text
|
||||
-preset must come first, as it overwrites other parameters
|
||||
-z <int> ............... activates lossless preset with given
|
||||
level in [0:fast, ..., 9:slowest]
|
||||
|
||||
-m <int> ............... compression method (0=fast, 6=slowest), default=4
|
||||
-segments <int> ........ number of segments to use (1..4), default=4
|
||||
-size <int> ............ target size (in bytes)
|
||||
-psnr <float> .......... target PSNR (in dB. typically: 42)
|
||||
|
||||
-s <int> <int> ......... input size (width x height) for YUV
|
||||
-sns <int> ............. spatial noise shaping (0:off, 100:max), default=50
|
||||
-f <int> ............... filter strength (0=off..100), default=60
|
||||
-sharpness <int> ....... filter sharpness (0:most .. 7:least sharp), default=0
|
||||
-strong ................ use strong filter instead of simple (default)
|
||||
-nostrong .............. use simple filter instead of strong
|
||||
-sharp_yuv ............. use sharper (and slower) RGB->YUV conversion
|
||||
-partition_limit <int> . limit quality to fit the 512k limit on
|
||||
the first partition (0=no degradation ... 100=full)
|
||||
-pass <int> ............ analysis pass number (1..10)
|
||||
-qrange <min> <max> .... specifies the permissible quality range
|
||||
(default: 0 100)
|
||||
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
|
||||
-resize <w> <h> ........ resize picture (*after* any cropping)
|
||||
-mt .................... use multi-threading if available
|
||||
-low_memory ............ reduce memory usage (slower encoding)
|
||||
-map <int> ............. print map of extra info
|
||||
-print_psnr ............ prints averaged PSNR distortion
|
||||
-print_ssim ............ prints averaged SSIM distortion
|
||||
-print_lsim ............ prints local-similarity distortion
|
||||
-d <file.pgm> .......... dump the compressed output (PGM file)
|
||||
-alpha_method <int> .... transparency-compression method (0..1), default=1
|
||||
-alpha_filter <string> . predictive filtering for alpha plane,
|
||||
one of: none, fast (default) or best
|
||||
-exact ................. preserve RGB values in transparent area, default=off
|
||||
-blend_alpha <hex> ..... blend colors against background color
|
||||
expressed as RGB values written in
|
||||
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
|
||||
green=0xe0 and blue=0xd0
|
||||
-noalpha ............... discard any transparency information
|
||||
-lossless .............. encode image losslessly, default=off
|
||||
-near_lossless <int> ... use near-lossless image preprocessing
|
||||
(0..100=off), default=100
|
||||
-hint <string> ......... specify image characteristics hint,
|
||||
one of: photo, picture or graph
|
||||
|
||||
-metadata <string> ..... comma separated list of metadata to
|
||||
copy from the input to the output if present.
|
||||
Valid values: all, none (default), exif, icc, xmp
|
||||
|
||||
-short ................. condense printed message
|
||||
-quiet ................. don't print anything
|
||||
-version ............... print version number and exit
|
||||
-noasm ................. disable all assembly optimizations
|
||||
-v ..................... verbose, e.g. print encoding/decoding times
|
||||
-progress .............. report encoding progress
|
||||
```
|
||||
|
||||
Experimental Options:
|
||||
|
||||
```
|
||||
-jpeg_like ............. roughly match expected JPEG size
|
||||
-af .................... auto-adjust filter strength
|
||||
-pre <int> ............. pre-processing filter
|
||||
```
|
||||
|
||||
The main options you might want to try in order to further tune the visual
|
||||
quality are:
|
||||
|
||||
-preset -sns -f -m
|
||||
|
||||
Namely:
|
||||
|
||||
* `preset` will set up a default encoding configuration targeting a particular
|
||||
type of input. It should appear first in the list of options, so that
|
||||
subsequent options can take effect on top of this preset. Default value is
|
||||
'default'.
|
||||
* `sns` will progressively turn on (when going from 0 to 100) some additional
|
||||
visual optimizations (like: segmentation map re-enforcement). This option
|
||||
will balance the bit allocation differently. It tries to take bits from the
|
||||
"easy" parts of the picture and use them in the "difficult" ones instead.
|
||||
Usually, raising the sns value (at fixed -q value) leads to larger files,
|
||||
but with better quality. Typical value is around '75'.
|
||||
* `f` option directly links to the filtering strength used by the codec's
|
||||
in-loop processing. The higher the value, the smoother the highly-compressed
|
||||
area will look. This is particularly useful when aiming at very small files.
|
||||
Typical values are around 20-30. Note that using the option
|
||||
-strong/-nostrong will change the type of filtering. Use "-f 0" to turn
|
||||
filtering off.
|
||||
* `m` controls the trade-off between encoding speed and quality. Default is 4.
|
||||
You can try -m 5 or -m 6 to explore more (time-consuming) encoding
|
||||
possibilities. A lower value will result in faster encoding at the expense
|
||||
of quality.
|
||||
|
||||
## Decoding tool
|
||||
|
||||
There is a decoding sample in examples/dwebp.c which will take a .webp file and
|
||||
decode it to a PNG image file (amongst other formats). This is simply to
|
||||
demonstrate the use of the API. You can verify the file test.webp decodes to
|
||||
exactly the same as test_ref.ppm by using:
|
||||
|
||||
```shell
|
||||
cd examples
|
||||
./dwebp test.webp -ppm -o test.ppm
|
||||
diff test.ppm test_ref.ppm
|
||||
```
|
||||
|
||||
The full list of options is available using -h:
|
||||
|
||||
```shell
|
||||
> dwebp -h
|
||||
Usage: dwebp in_file [options] [-o out_file]
|
||||
```
|
||||
|
||||
Decodes the WebP image file to PNG format [Default]. Note: Animated WebP files
|
||||
are not supported.
|
||||
|
||||
Use following options to convert into alternate image formats:
|
||||
|
||||
```
|
||||
-pam ......... save the raw RGBA samples as a color PAM
|
||||
-ppm ......... save the raw RGB samples as a color PPM
|
||||
-bmp ......... save as uncompressed BMP format
|
||||
-tiff ........ save as uncompressed TIFF format
|
||||
-pgm ......... save the raw YUV samples as a grayscale PGM
|
||||
file with IMC4 layout
|
||||
-yuv ......... save the raw YUV samples in flat layout
|
||||
```
|
||||
|
||||
Other options are:
|
||||
|
||||
```
|
||||
-version ..... print version number and exit
|
||||
-nofancy ..... don't use the fancy YUV420 upscaler
|
||||
-nofilter .... disable in-loop filtering
|
||||
-nodither .... disable dithering
|
||||
-dither <d> .. dithering strength (in 0..100)
|
||||
-alpha_dither use alpha-plane dithering if needed
|
||||
-mt .......... use multi-threading
|
||||
-crop <x> <y> <w> <h> ... crop output with the given rectangle
|
||||
-resize <w> <h> ......... resize output (*after* any cropping)
|
||||
-flip ........ flip the output vertically
|
||||
-alpha ....... only save the alpha plane
|
||||
-incremental . use incremental decoding (useful for tests)
|
||||
-h ........... this help message
|
||||
-v ........... verbose (e.g. print encoding/decoding times)
|
||||
-quiet ....... quiet mode, don't print anything
|
||||
-noasm ....... disable all assembly optimizations
|
||||
```
|
||||
|
||||
## WebP file analysis tool
|
||||
|
||||
`webpinfo` can be used to print out the chunk level structure and bitstream
|
||||
header information of WebP files. It can also check if the files are of valid
|
||||
WebP format.
|
||||
|
||||
Usage:
|
||||
|
||||
```shell
|
||||
webpinfo [options] in_files
|
||||
```
|
||||
|
||||
Note: there could be multiple input files; options must come before input files.
|
||||
|
||||
Options:
|
||||
|
||||
```
|
||||
-version ........... Print version number and exit.
|
||||
-quiet ............. Do not show chunk parsing information.
|
||||
-diag .............. Show parsing error diagnosis.
|
||||
-summary ........... Show chunk stats summary.
|
||||
-bitstream_info .... Parse bitstream header.
|
||||
```
|
||||
|
||||
## Visualization tool
|
||||
|
||||
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 build system, but you
|
||||
can try to manually compile it using the recommendations below.
|
||||
|
||||
Usage:
|
||||
|
||||
```shell
|
||||
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
|
||||
-dither <int> dithering strength (0..100), default=50
|
||||
-noalphadither disable alpha plane dithering
|
||||
-usebgcolor .. display background color
|
||||
-mt .......... use multi-threading
|
||||
-info ........ print info
|
||||
-h ........... this help message
|
||||
```
|
||||
|
||||
Keyboard shortcuts:
|
||||
|
||||
```
|
||||
'c' ................ toggle use of color profile
|
||||
'b' ................ toggle background color display
|
||||
'i' ................ overlay file information
|
||||
'd' ................ disable blending & disposal (debug)
|
||||
'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)
|
||||
|
||||
1. Download qcms from Mozilla / Chromium:
|
||||
https://hg.mozilla.org/mozilla-central/file/0e7639e3bdfb/gfx/qcms
|
||||
https://source.chromium.org/chromium/chromium/src/+/main:third_party/qcms/;drc=d4a2f8e1ed461d8fc05ed88d1ae2dc94c9773825
|
||||
2. Build and archive the source files as libqcms.a / qcms.lib
|
||||
3. Update makefile.unix / Makefile.vc
|
||||
1. Define WEBP_HAVE_QCMS
|
||||
2. Update include / library paths to reference the qcms directory.
|
||||
|
||||
Build using makefile.unix / Makefile.vc:
|
||||
|
||||
```shell
|
||||
$ make -f makefile.unix examples/vwebp
|
||||
> nmake /f Makefile.vc CFG=release-static \
|
||||
../obj/x64/release-static/bin/vwebp.exe
|
||||
```
|
||||
|
||||
## Animation creation tool
|
||||
|
||||
The utility `img2webp` can turn a sequence of input images (PNG, JPEG, ...) into
|
||||
an animated WebP file. It offers fine control over duration, encoding modes,
|
||||
etc.
|
||||
|
||||
Usage:
|
||||
|
||||
```shell
|
||||
img2webp [file_options] [[frame_options] frame_file]... [-o webp_file]
|
||||
```
|
||||
|
||||
File-level options (only used at the start of compression):
|
||||
|
||||
```
|
||||
-min_size ............ minimize size
|
||||
-kmax <int> .......... maximum number of frame between key-frames
|
||||
(0=only keyframes)
|
||||
-kmin <int> .......... minimum number of frame between key-frames
|
||||
(0=disable key-frames altogether)
|
||||
-mixed ............... use mixed lossy/lossless automatic mode
|
||||
-near_lossless <int> . use near-lossless image preprocessing
|
||||
(0..100=off), default=100
|
||||
-sharp_yuv ........... use sharper (and slower) RGB->YUV conversion
|
||||
(lossy only)
|
||||
-loop <int> .......... loop count (default: 0, = infinite loop)
|
||||
-v ................... verbose mode
|
||||
-h ................... this help
|
||||
-version ............. print version number and exit
|
||||
```
|
||||
|
||||
Per-frame options (only used for subsequent images input):
|
||||
|
||||
```
|
||||
-d <int> ............. frame duration in ms (default: 100)
|
||||
-lossless ............ use lossless mode (default)
|
||||
-lossy ............... use lossy mode
|
||||
-q <float> ........... quality
|
||||
-m <int> ............. method to use
|
||||
-exact, -noexact ..... preserve or alter RGB values in transparent area
|
||||
(default: -noexact, may cause artifacts
|
||||
with lossy animations)
|
||||
```
|
||||
|
||||
example: `img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp`
|
||||
|
||||
Note: if a single file name is passed as the argument, the arguments will be
|
||||
tokenized from this file. The file name must not start with the character '-'.
|
||||
|
||||
## Animated GIF conversion
|
||||
|
||||
Animated GIF files can be converted to WebP files with animation using the
|
||||
gif2webp utility available under examples/. The files can then be viewed using
|
||||
vwebp.
|
||||
|
||||
Usage:
|
||||
|
||||
```shell
|
||||
gif2webp [options] gif_file -o webp_file
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
```
|
||||
-h / -help ............. this help
|
||||
-lossy ................. encode image using lossy compression
|
||||
-mixed ................. for each frame in the image, pick lossy
|
||||
or lossless compression heuristically
|
||||
-q <float> ............. quality factor (0:small..100:big)
|
||||
-m <int> ............... compression method (0=fast, 6=slowest)
|
||||
-min_size .............. minimize output size (default:off)
|
||||
lossless compression by default; can be
|
||||
combined with -q, -m, -lossy or -mixed
|
||||
options
|
||||
-kmin <int> ............ min distance between key frames
|
||||
-kmax <int> ............ max distance between key frames
|
||||
-f <int> ............... filter strength (0=off..100)
|
||||
-metadata <string> ..... comma separated list of metadata to
|
||||
copy from the input to the output if present
|
||||
Valid values: all, none, icc, xmp (default)
|
||||
-loop_compatibility .... use compatibility mode for Chrome
|
||||
version prior to M62 (inclusive)
|
||||
-mt .................... use multi-threading if available
|
||||
|
||||
-version ............... print version number and exit
|
||||
-v ..................... verbose
|
||||
-quiet ................. don't print anything
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
With the libgif development files installed, gif2webp can be built using
|
||||
makefile.unix:
|
||||
|
||||
```shell
|
||||
$ make -f makefile.unix examples/gif2webp
|
||||
```
|
||||
|
||||
or using autoconf:
|
||||
|
||||
```shell
|
||||
$ ./configure --enable-everything
|
||||
$ make
|
||||
```
|
||||
|
||||
## Comparison of animated images
|
||||
|
||||
Test utility anim_diff under examples/ can be used to compare two animated
|
||||
images (each can be GIF or WebP).
|
||||
|
||||
Usage:
|
||||
|
||||
```shell
|
||||
anim_diff <image1> <image2> [options]
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
```
|
||||
-dump_frames <folder> dump decoded frames in PAM format
|
||||
-min_psnr <float> ... minimum per-frame PSNR
|
||||
-raw_comparison ..... if this flag is not used, RGB is
|
||||
premultiplied before comparison
|
||||
-max_diff <int> ..... maximum allowed difference per channel
|
||||
between corresponding pixels in subsequent
|
||||
frames
|
||||
-h .................. this help
|
||||
-version ............ print version number and exit
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
With the libgif development files installed, anim_diff can be built using
|
||||
makefile.unix:
|
||||
|
||||
```shell
|
||||
$ make -f makefile.unix examples/anim_diff
|
||||
```
|
||||
|
||||
or using autoconf:
|
||||
|
||||
```shell
|
||||
$ ./configure --enable-everything
|
||||
$ make
|
||||
```
|
||||
|
||||
## WebP Mux tool
|
||||
|
||||
The examples/ directory contains a tool (webpmux) for manipulating WebP files.
|
||||
The webpmux tool can be used to create an extended format WebP file and also to
|
||||
extract or strip relevant data from such a file.
|
||||
|
||||
A list of options is available using the -help command line flag:
|
||||
|
||||
```shell
|
||||
> webpmux -help
|
||||
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
|
||||
webpmux -set SET_OPTIONS INPUT -o OUTPUT
|
||||
webpmux -duration DURATION_OPTIONS [-duration ...]
|
||||
INPUT -o OUTPUT
|
||||
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
|
||||
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
|
||||
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
|
||||
webpmux -info INPUT
|
||||
webpmux [-h|-help]
|
||||
webpmux -version
|
||||
webpmux argument_file_name
|
||||
|
||||
GET_OPTIONS:
|
||||
Extract relevant data:
|
||||
icc get ICC profile
|
||||
exif get EXIF metadata
|
||||
xmp get XMP metadata
|
||||
frame n get nth frame
|
||||
|
||||
SET_OPTIONS:
|
||||
Set color profile/metadata/parameters:
|
||||
loop LOOP_COUNT set the loop count
|
||||
bgcolor BACKGROUND_COLOR set the animation background color
|
||||
icc file.icc set ICC profile
|
||||
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
|
||||
'file.xmp' contains the XMP metadata to be set
|
||||
|
||||
DURATION_OPTIONS:
|
||||
Set duration of selected frames:
|
||||
duration set duration for all frames
|
||||
duration,frame set duration of a particular frame
|
||||
duration,start,end set duration of frames in the
|
||||
interval [start,end])
|
||||
where: 'duration' is the duration in milliseconds
|
||||
'start' is the start frame index
|
||||
'end' is the inclusive end frame index
|
||||
The special 'end' value '0' means: last frame.
|
||||
|
||||
STRIP_OPTIONS:
|
||||
Strip color profile/metadata:
|
||||
icc strip ICC profile
|
||||
exif strip EXIF metadata
|
||||
xmp strip XMP metadata
|
||||
|
||||
FRAME_OPTIONS(i):
|
||||
Create animation:
|
||||
file_i +di[+xi+yi[+mi[bi]]]
|
||||
where: 'file_i' is the i'th animation frame (WebP format),
|
||||
'di' is the pause duration before next frame,
|
||||
'xi','yi' specify the image offset for this frame,
|
||||
'mi' is the dispose method for this frame (0 or 1),
|
||||
'bi' is the blending method for this frame (+b or -b)
|
||||
|
||||
LOOP_COUNT:
|
||||
Number of times to repeat the animation.
|
||||
Valid range is 0 to 65535 [Default: 0 (infinite)].
|
||||
|
||||
BACKGROUND_COLOR:
|
||||
Background color of the canvas.
|
||||
A,R,G,B
|
||||
where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying
|
||||
the Alpha, Red, Green and Blue component values respectively
|
||||
[Default: 255,255,255,255]
|
||||
|
||||
INPUT & OUTPUT are in WebP format.
|
||||
|
||||
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
|
||||
valid.
|
||||
|
||||
Note: if a single file name is passed as the argument, the arguments will be
|
||||
tokenized from this file. The file name must not start with the character '-'.
|
||||
```
|
@ -4,8 +4,8 @@ Although you may be viewing an alternate representation, this document
|
||||
is sourced in Markdown, a light-duty markup scheme, and is optimized for
|
||||
the [kramdown](https://kramdown.gettalong.org/) transformer.
|
||||
|
||||
See the accompanying README. External link targets are referenced at the
|
||||
end of this file.
|
||||
See the accompanying specs_generation.md. External link targets are referenced
|
||||
at the end of this file.
|
||||
|
||||
-->
|
||||
|
||||
@ -20,46 +20,48 @@ WebP Container Specification
|
||||
Introduction
|
||||
------------
|
||||
|
||||
WebP is an image format that uses either (i) the VP8 key frame encoding
|
||||
to compress image data in a lossy way, or (ii) the WebP lossless encoding
|
||||
(and possibly other encodings in the future). These encoding schemes should
|
||||
make it more efficient than currently used formats. It is optimized for fast
|
||||
image transfer over the network (e.g., for websites). The WebP format has
|
||||
feature parity (color profile, metadata, animation etc) with other formats as
|
||||
well. This document describes the structure of a WebP file.
|
||||
WebP is an image format that uses either (i) the VP8 key frame encoding to
|
||||
compress image data in a lossy way or (ii) the WebP lossless encoding. These
|
||||
encoding schemes should make it more efficient than older formats, such as JPEG,
|
||||
GIF, and PNG. It is optimized for fast image transfer over the network (for
|
||||
example, for websites). The WebP format has feature parity (color profile,
|
||||
metadata, animation, etc.) with other formats as well. This document describes
|
||||
the structure of a WebP file.
|
||||
|
||||
The WebP container (i.e., RIFF container for WebP) allows feature support over
|
||||
and above the basic use case of WebP (i.e., a file containing a single image
|
||||
encoded as a VP8 key frame). The WebP container provides additional support
|
||||
for:
|
||||
The WebP container (that is, the RIFF container for WebP) allows feature support
|
||||
over and above the basic use case of WebP (that is, a file containing a single
|
||||
image encoded as a VP8 key frame). The WebP container provides additional
|
||||
support for the following:
|
||||
|
||||
* **Lossless compression.** An image can be losslessly compressed, using the
|
||||
* Lossless Compression: An image can be losslessly compressed, using the
|
||||
WebP Lossless Format.
|
||||
|
||||
* **Metadata.** An image may have metadata stored in EXIF or XMP formats.
|
||||
* Metadata: An image may have metadata stored in Exchangeable Image File
|
||||
Format (Exif) or Extensible Metadata Platform (XMP) format.
|
||||
|
||||
* **Transparency.** An image may have transparency, i.e., an alpha channel.
|
||||
* Transparency: An image may have transparency, that is, an alpha channel.
|
||||
|
||||
* **Color Profile.** An image may have an embedded ICC profile as described
|
||||
* Color Profile: An image may have an embedded ICC profile as described
|
||||
by the [International Color Consortium][iccspec].
|
||||
|
||||
* **Animation.** An image may have multiple frames with pauses between them,
|
||||
* Animation: An image may have multiple frames with pauses between them,
|
||||
making it an animation.
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC 2119][].
|
||||
Terminology & Basics
|
||||
--------------------
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
||||
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in BCP 14 [RFC 2119][] [RFC 8174][]
|
||||
when, and only when, they appear in all capitals, as shown here.
|
||||
|
||||
A WebP file contains either a still image (that is, an encoded matrix of pixels)
|
||||
or an [animation](#animation). Optionally, it can also contain transparency
|
||||
information, a color profile and metadata. We refer to the matrix of pixels as
|
||||
the _canvas_ of the image.
|
||||
|
||||
Bit numbering in chunk diagrams starts at `0` for the most significant bit
|
||||
('MSB 0') as described in [RFC 1166][].
|
||||
|
||||
Terminology & Basics
|
||||
------------------------
|
||||
|
||||
A WebP file contains either a still image (i.e., an encoded matrix of pixels)
|
||||
or an [animation](#animation). Optionally, it can also contain transparency
|
||||
information, color profile and metadata. In case we need to refer only to the
|
||||
matrix of pixels, we will call it the _canvas_ of the image.
|
||||
('MSB 0'), as described in [RFC 1166][].
|
||||
|
||||
Below are additional terms used throughout this document:
|
||||
|
||||
@ -82,19 +84,25 @@ _uint32_
|
||||
|
||||
_FourCC_
|
||||
|
||||
: A _FourCC_ (four-character code) is a _uint32_ created by concatenating four
|
||||
ASCII characters in little-endian order.
|
||||
: A four-character code (FourCC) is a _uint32_ created by concatenating four
|
||||
ASCII characters in little-endian order. This means 'aaaa' (0x61616161) and
|
||||
'AAAA' (0x41414141) are treated as different _FourCCs_.
|
||||
|
||||
_1-based_
|
||||
|
||||
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
|
||||
would store value _25_ as _24_.
|
||||
: An unsigned integer field storing values offset by `-1`, for example, such a
|
||||
field would store value _25_ as _24_.
|
||||
|
||||
_ChunkHeader('ABCD')_
|
||||
|
||||
: 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.
|
||||
|
||||
|
||||
RIFF File Format
|
||||
----------------
|
||||
|
||||
The WebP file format is based on the RIFF (resource interchange file format)
|
||||
The WebP file format is based on the RIFF (Resource Interchange File Format)
|
||||
document format.
|
||||
|
||||
The basic element of a RIFF file is a _chunk_. It consists of:
|
||||
@ -106,7 +114,7 @@ The basic element of a RIFF file is a _chunk_. It consists of:
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Chunk Size |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Chunk Payload |
|
||||
: Chunk Payload :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Chunk FourCC: 32 bits
|
||||
@ -115,21 +123,15 @@ Chunk FourCC: 32 bits
|
||||
|
||||
Chunk Size: 32 bits (_uint32_)
|
||||
|
||||
: The size of the chunk not including this field, the chunk identifier or
|
||||
padding.
|
||||
: The size of the chunk in bytes, not including this field, the chunk
|
||||
identifier, or padding.
|
||||
|
||||
Chunk Payload: _Chunk Size_ bytes
|
||||
|
||||
: The data payload. If _Chunk Size_ is odd, a single padding byte -- that
|
||||
SHOULD be `0` -- is added.
|
||||
: The data payload. If _Chunk Size_ is odd, a single padding byte -- which MUST
|
||||
be `0` to conform with RIFF -- is added.
|
||||
|
||||
_ChunkHeader('ABCD')_
|
||||
|
||||
: 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:** RIFF has a convention that all-uppercase chunk FourCCs are standard
|
||||
**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.
|
||||
|
||||
@ -149,23 +151,25 @@ WebP File Header
|
||||
|
||||
'RIFF': 32 bits
|
||||
|
||||
: The ASCII characters 'R' 'I' 'F' 'F'.
|
||||
: The ASCII characters 'R', 'I', 'F', 'F'.
|
||||
|
||||
File Size: 32 bits (_uint32_)
|
||||
|
||||
: The size of the file in bytes starting at offset 8. The maximum value of
|
||||
: The size of the file in bytes, starting at offset 8. The maximum value of
|
||||
this field is 2^32 minus 10 bytes and thus the size of the whole file is at
|
||||
most 4GiB minus 2 bytes.
|
||||
most 4 GiB minus 2 bytes.
|
||||
|
||||
'WEBP': 32 bits
|
||||
|
||||
: The ASCII characters 'W' 'E' 'B' 'P'.
|
||||
: The ASCII characters 'W', 'E', 'B', 'P'.
|
||||
|
||||
A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size
|
||||
in the header is the total size of the chunks that follow plus `4` bytes for
|
||||
the 'WEBP' FourCC. The file SHOULD NOT contain anything after it. As the size
|
||||
of any chunk is even, the size given by the RIFF header is also even. The
|
||||
contents of individual chunks will be described in the following sections.
|
||||
the 'WEBP' FourCC. The file SHOULD NOT contain any data after the data
|
||||
specified by _File Size_. Readers MAY parse such files, ignoring the trailing
|
||||
data. As the size of any chunk is even, the size given by the RIFF header is
|
||||
also even. The contents of individual chunks are described in the following
|
||||
sections.
|
||||
|
||||
|
||||
Simple File Format (Lossy)
|
||||
@ -180,37 +184,43 @@ Simple WebP (lossy) file format:
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| WebP file header (12 bytes) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| VP8 chunk |
|
||||
: 'VP8 ' Chunk :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
VP8 chunk:
|
||||
'VP8 ' Chunk:
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ChunkHeader('VP8 ') |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| VP8 data |
|
||||
: VP8 data :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
VP8 data: _Chunk Size_ bytes
|
||||
|
||||
: VP8 bitstream data.
|
||||
|
||||
The VP8 bitstream format specification can be found at [VP8 Data Format and
|
||||
Decoding Guide][vp8spec]. Note that the VP8 frame header contains the VP8 frame
|
||||
Note that the fourth character in the 'VP8 ' FourCC is an ASCII space (0x20).
|
||||
|
||||
The VP8 bitstream format specification is described in [VP8 Data Format and
|
||||
Decoding Guide][rfc 6386]. Note that the VP8 frame header contains the VP8 frame
|
||||
width and height. That is assumed to be the width and height of the canvas.
|
||||
|
||||
The VP8 specification describes how to decode the image into Y'CbCr
|
||||
format. To convert to RGB, Rec. 601 SHOULD be used.
|
||||
The VP8 specification describes how to decode the image into Y'CbCr format. To
|
||||
convert to RGB, [Recommendation BT.601][rec601] SHOULD be used. Applications MAY
|
||||
use another conversion method, but visual results may differ among decoders.
|
||||
|
||||
|
||||
Simple File Format (Lossless)
|
||||
-----------------------------
|
||||
|
||||
**Note:** Older readers may not support files using the lossless format.
|
||||
**Note**: Older readers may not support files using the lossless format.
|
||||
|
||||
This layout SHOULD be used if the image requires _lossless_ encoding (with an
|
||||
optional transparency channel) and does not require advanced features provided
|
||||
@ -221,19 +231,22 @@ Simple WebP (lossless) file format:
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| WebP file header (12 bytes) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| VP8L chunk |
|
||||
: 'VP8L' Chunk :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
VP8L chunk:
|
||||
'VP8L' Chunk:
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ChunkHeader('VP8L') |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| VP8L data |
|
||||
: VP8L data :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
VP8L data: _Chunk Size_ bytes
|
||||
@ -249,21 +262,21 @@ and height of the canvas.
|
||||
Extended File Format
|
||||
--------------------
|
||||
|
||||
**Note:** Older readers may not support files using the extended format.
|
||||
**Note**: Older readers may not support files using the extended format.
|
||||
|
||||
An extended format file consists of:
|
||||
|
||||
* A 'VP8X' chunk with information about features used in the file.
|
||||
* A 'VP8X' Chunk with information about features used in the file.
|
||||
|
||||
* An optional 'ICCP' chunk with color profile.
|
||||
* An optional 'ICCP' Chunk with a color profile.
|
||||
|
||||
* An optional 'ANIM' chunk with animation control data.
|
||||
* An optional 'ANIM' Chunk with animation control data.
|
||||
|
||||
* Image data.
|
||||
|
||||
* An optional 'EXIF' chunk with EXIF metadata.
|
||||
* An optional 'EXIF' Chunk with Exif metadata.
|
||||
|
||||
* An optional 'XMP ' chunk with XMP metadata.
|
||||
* An optional 'XMP ' Chunk with XMP metadata.
|
||||
|
||||
* An optional list of [unknown chunks](#unknown-chunks).
|
||||
|
||||
@ -277,15 +290,18 @@ up of:
|
||||
For an _animated image_, the _image data_ consists of multiple frames. More
|
||||
details about frames can be found in the [Animation](#animation) section.
|
||||
|
||||
All chunks SHOULD be placed in the same order as listed above. If a chunk
|
||||
appears in the wrong place, the file is invalid, but readers MAY parse the
|
||||
file, ignoring the chunks that come too late.
|
||||
All chunks necessary for reconstruction and color correction, that is, 'VP8X',
|
||||
'ICCP', 'ANIM', 'ANMF', 'ALPH', 'VP8 ', and 'VP8L', MUST appear in the order
|
||||
described earlier. Readers SHOULD fail when chunks necessary for reconstruction
|
||||
and color correction are out of order.
|
||||
|
||||
**Rationale:** Setting the order of chunks should allow quicker file
|
||||
parsing. For example, if an 'ALPH' chunk does not appear in its required
|
||||
position, a decoder can choose to stop searching for it. The rule of
|
||||
ignoring late chunks should make programs that need to do a full search
|
||||
give the same results as the ones stopping early.
|
||||
[Metadata](#metadata) and [unknown chunks](#unknown-chunks) MAY appear out of
|
||||
order.
|
||||
|
||||
**Rationale:** The chunks necessary for reconstruction should appear first in
|
||||
the file to allow a reader to begin decoding an image before receiving all of
|
||||
the data. An application may benefit from varying the order of metadata and
|
||||
custom chunks to suit the implementation.
|
||||
|
||||
Extended WebP file header:
|
||||
{:#extended_header}
|
||||
@ -293,9 +309,12 @@ Extended WebP file header:
|
||||
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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |
|
||||
| WebP file header (12 bytes) |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ChunkHeader('VP8X') |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|Rsv|I|L|E|X|A|R| Reserved |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
@ -306,20 +325,20 @@ Extended WebP file header:
|
||||
|
||||
Reserved (Rsv): 2 bits
|
||||
|
||||
: SHOULD be `0`.
|
||||
: MUST be `0`. Readers MUST ignore this field.
|
||||
|
||||
ICC profile (I): 1 bit
|
||||
|
||||
: Set if the file contains an ICC profile.
|
||||
: Set if the file contains an 'ICCP' Chunk.
|
||||
|
||||
Alpha (L): 1 bit
|
||||
|
||||
: Set if any of the frames of the image contain transparency information
|
||||
("alpha").
|
||||
|
||||
EXIF metadata (E): 1 bit
|
||||
Exif metadata (E): 1 bit
|
||||
|
||||
: Set if the file contains EXIF metadata.
|
||||
: Set if the file contains Exif metadata.
|
||||
|
||||
XMP metadata (X): 1 bit
|
||||
|
||||
@ -327,38 +346,38 @@ XMP metadata (X): 1 bit
|
||||
|
||||
Animation (A): 1 bit
|
||||
|
||||
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be
|
||||
: Set if this is an animated image. Data in 'ANIM' and 'ANMF' Chunks should be
|
||||
used to control the animation.
|
||||
|
||||
Reserved (R): 1 bit
|
||||
|
||||
: SHOULD be `0`.
|
||||
: MUST be `0`. Readers MUST ignore this field.
|
||||
|
||||
Reserved: 24 bits
|
||||
|
||||
: SHOULD be `0`.
|
||||
: MUST be `0`. Readers MUST ignore this field.
|
||||
|
||||
Canvas Width Minus One: 24 bits
|
||||
|
||||
: _1-based_ width of the canvas in pixels.
|
||||
The actual canvas width is '1 + Canvas Width Minus One'
|
||||
The actual canvas width is `1 + Canvas Width Minus One`.
|
||||
|
||||
Canvas Height Minus One: 24 bits
|
||||
|
||||
: _1-based_ height of the canvas in pixels.
|
||||
The actual canvas height is '1 + Canvas Height Minus One'
|
||||
The actual canvas height is `1 + Canvas Height Minus One`.
|
||||
|
||||
The product of _Canvas Width_ and _Canvas Height_ MUST be at most `2^32 - 1`.
|
||||
|
||||
Future specifications MAY add more fields.
|
||||
Future specifications may add more fields. Unknown fields MUST be ignored.
|
||||
|
||||
### Chunks
|
||||
|
||||
#### Animation
|
||||
|
||||
An animation is controlled by ANIM and ANMF chunks.
|
||||
An animation is controlled by 'ANIM' and 'ANMF' Chunks.
|
||||
|
||||
ANIM Chunk:
|
||||
'ANIM' Chunk:
|
||||
{:#anim_chunk}
|
||||
|
||||
For an animated image, this chunk contains the _global parameters_ of the
|
||||
@ -368,6 +387,7 @@ animation.
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ChunkHeader('ANIM') |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Background Color |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
@ -379,14 +399,14 @@ Background Color: 32 bits (_uint32_)
|
||||
: The default background color of the canvas in \[Blue, Green, Red, Alpha\]
|
||||
byte order. This color MAY be used to fill the unused space on the canvas
|
||||
around the frames, as well as the transparent pixels of the first frame.
|
||||
Background color is also used when disposal method is `1`.
|
||||
The background color is also used when the Disposal method is `1`.
|
||||
|
||||
**Note**:
|
||||
**Notes**:
|
||||
|
||||
* Background color MAY contain a transparency value (alpha), even if the
|
||||
_Alpha_ flag in [VP8X chunk](#extended_header) is unset.
|
||||
* The background color MAY contain a non-opaque alpha value, even if the
|
||||
_Alpha_ flag in the ['VP8X' Chunk](#extended_header) is unset.
|
||||
|
||||
* Viewer applications SHOULD treat the background color value as a hint, and
|
||||
* Viewer applications SHOULD treat the background color value as a hint and
|
||||
are not required to use it.
|
||||
|
||||
* The canvas is cleared at the start of each loop. The background color MAY be
|
||||
@ -394,13 +414,14 @@ Background Color: 32 bits (_uint32_)
|
||||
|
||||
Loop Count: 16 bits (_uint16_)
|
||||
|
||||
: The number of times to loop the animation. `0` means infinitely.
|
||||
: The number of times to loop the animation. If it is `0`, this means
|
||||
infinitely.
|
||||
|
||||
This chunk MUST appear if the _Animation_ flag in the VP8X chunk is set.
|
||||
If the _Animation_ flag is not set and this chunk is present, it
|
||||
SHOULD be ignored.
|
||||
This chunk MUST appear if the _Animation_ flag in the 'VP8X' Chunk is set.
|
||||
If the _Animation_ flag is not set and this chunk is present, it MUST be
|
||||
ignored.
|
||||
|
||||
ANMF chunk:
|
||||
'ANMF' Chunk:
|
||||
|
||||
For animated images, this chunk contains information about a _single_ frame.
|
||||
If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
|
||||
@ -409,6 +430,7 @@ If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ChunkHeader('ANMF') |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Frame X | ...
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
@ -418,47 +440,47 @@ If the _Animation flag_ is not set, then this chunk SHOULD NOT be present.
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Frame Duration | Reserved |B|D|
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Frame Data |
|
||||
: Frame Data :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Frame X: 24 bits (_uint24_)
|
||||
|
||||
: The X coordinate of the upper left corner of the frame is `Frame X * 2`
|
||||
: The X coordinate of the upper left corner of the frame is `Frame X * 2`.
|
||||
|
||||
Frame Y: 24 bits (_uint24_)
|
||||
|
||||
: The Y coordinate of the upper left corner of the frame is `Frame Y * 2`
|
||||
: The Y coordinate of the upper left corner of the frame is `Frame Y * 2`.
|
||||
|
||||
Frame Width Minus One: 24 bits (_uint24_)
|
||||
|
||||
: The _1-based_ width of the frame.
|
||||
The frame width is `1 + Frame Width Minus One`
|
||||
The frame width is `1 + Frame Width Minus One`.
|
||||
|
||||
Frame Height Minus One: 24 bits (_uint24_)
|
||||
|
||||
: The _1-based_ height of the frame.
|
||||
The frame height is `1 + Frame Height Minus One`
|
||||
The frame height is `1 + Frame Height Minus One`.
|
||||
|
||||
Frame Duration: 24 bits (_uint24_)
|
||||
|
||||
: The time to wait before displaying the next frame, in 1 millisecond units.
|
||||
Note the interpretation of frame duration of 0 (and often <= 10) is
|
||||
implementation defined. Many tools and browsers assign a minimum duration
|
||||
similar to GIF.
|
||||
: The time to wait before displaying the next frame, in 1-millisecond units.
|
||||
Note that the interpretation of the Frame Duration of 0 (and often <= 10) is
|
||||
defined by the implementation. Many tools and browsers assign a minimum
|
||||
duration similar to GIF.
|
||||
|
||||
Reserved: 6 bits
|
||||
|
||||
: SHOULD be 0.
|
||||
: MUST be `0`. Readers MUST ignore this field.
|
||||
|
||||
Blending method (B): 1 bit
|
||||
|
||||
: Indicates how transparent pixels of _the current frame_ are to be blended
|
||||
with corresponding pixels of the previous canvas:
|
||||
|
||||
* `0`: Use alpha blending. After disposing of the previous frame, render the
|
||||
* `0`: Use alpha-blending. After disposing of the previous frame, render the
|
||||
current frame on the canvas using [alpha-blending](#alpha-blending). If
|
||||
the current frame does not have an alpha channel, assume alpha value of
|
||||
255, effectively replacing the rectangle.
|
||||
the current frame does not have an alpha channel, assume the alpha value
|
||||
is 255, effectively replacing the rectangle.
|
||||
|
||||
* `1`: Do not blend. After disposing of the previous frame, render the
|
||||
current frame on the canvas by overwriting the rectangle covered by the
|
||||
@ -471,20 +493,20 @@ Disposal method (D): 1 bit
|
||||
|
||||
* `0`: Do not dispose. Leave the canvas as is.
|
||||
|
||||
* `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).
|
||||
* `1`: Dispose to the background color. Fill the _rectangle_ on the canvas
|
||||
covered by the _current frame_ with the background color specified in the
|
||||
['ANIM' Chunk](#anim_chunk).
|
||||
|
||||
**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.
|
||||
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**:
|
||||
* Alpha-blending:
|
||||
|
||||
Given that each of the R, G, B and A channels is 8-bit, and the RGB
|
||||
Given that each of the R, G, B, and A channels is 8 bits, and the RGB
|
||||
channels are _not premultiplied_ by alpha, the formula for blending
|
||||
'dst' onto 'src' is:
|
||||
|
||||
@ -493,16 +515,17 @@ Disposal method (D): 1 bit
|
||||
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
|
||||
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).
|
||||
not present, standard RGB (sRGB) is to be assumed. (Note that sRGB also
|
||||
needs to be linearized due to a gamma of ~2.2.)
|
||||
|
||||
Frame Data: _Chunk Size_ - `16` bytes
|
||||
Frame Data: _Chunk Size_ bytes - `16`
|
||||
|
||||
: Consists of:
|
||||
|
||||
@ -512,8 +535,8 @@ 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).
|
||||
**Note**: The 'ANMF' payload, _Frame Data_, consists of individual
|
||||
_padded_ chunks, as described by the [RIFF file format](#riff-file-format).
|
||||
|
||||
#### Alpha
|
||||
|
||||
@ -521,26 +544,29 @@ _padded_ chunks as described by the [RIFF file format](#riff-file-format).
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ChunkHeader('ALPH') |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|Rsv| P | F | C | Alpha Bitstream... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Reserved (Rsv): 2 bits
|
||||
|
||||
: SHOULD be `0`.
|
||||
: MUST be `0`. Readers MUST ignore this field.
|
||||
|
||||
Pre-processing (P): 2 bits
|
||||
Preprocessing (P): 2 bits
|
||||
|
||||
: These INFORMATIVE bits are used to signal the pre-processing that has
|
||||
: These _informative_ bits are used to signal the preprocessing that has
|
||||
been performed during compression. The decoder can use this information to
|
||||
e.g. dither the values or smooth the gradients prior to display.
|
||||
for example, dither the values or smooth the gradients prior to display.
|
||||
|
||||
* `0`: no pre-processing
|
||||
* `1`: level reduction
|
||||
* `0`: No preprocessing.
|
||||
* `1`: Level reduction.
|
||||
|
||||
Decoders are not required to use this information in any specified way.
|
||||
|
||||
Filtering method (F): 2 bits
|
||||
|
||||
: The filtering method used:
|
||||
: The filtering methods used are described as follows:
|
||||
|
||||
* `0`: None.
|
||||
* `1`: Horizontal filter.
|
||||
@ -564,27 +590,25 @@ made depending on the filtering method:
|
||||
|
||||
where `clip(v)` is equal to:
|
||||
|
||||
* 0 if v < 0
|
||||
* 255 if v > 255
|
||||
* 0 if v < 0,
|
||||
* 255 if v > 255, or
|
||||
* v otherwise
|
||||
|
||||
The final value is derived by adding the decompressed value `X` to the
|
||||
predictor and using modulo-256 arithmetic to wrap the \[256-511\] range
|
||||
into the \[0-255\] one:
|
||||
predictor and using modulo-256 arithmetic to wrap the \[256..511\] range
|
||||
into the \[0..255\] one:
|
||||
|
||||
`alpha = (predictor + X) % 256`
|
||||
|
||||
There are special cases for left-most and top-most pixel positions:
|
||||
There are special cases for the left-most and top-most pixel positions. For
|
||||
example, the top-left value at location (0, 0) uses 0 as the predictor value.
|
||||
Otherwise:
|
||||
|
||||
* Top-left value at location (0,0) uses 0 as predictor value. Otherwise,
|
||||
* For horizontal or gradient filtering methods, the left-most pixels at
|
||||
location (0, y) are predicted using the location (0, y-1) just above.
|
||||
* For vertical or gradient filtering methods, the top-most pixels at
|
||||
location (x, 0) are predicted using the location (x-1, 0) on the left.
|
||||
|
||||
|
||||
Decoders are not required to use this information in any specified way.
|
||||
|
||||
Compression method (C): 2 bits
|
||||
|
||||
: The compression method used:
|
||||
@ -592,37 +616,37 @@ Compression method (C): 2 bits
|
||||
* `0`: No compression.
|
||||
* `1`: Compressed using the WebP lossless format.
|
||||
|
||||
Alpha bitstream: _Chunk Size_ - `1` bytes
|
||||
Alpha bitstream: _Chunk Size_ bytes - `1`
|
||||
|
||||
: Encoded alpha bitstream.
|
||||
|
||||
This optional chunk contains encoded alpha data for this frame. A frame
|
||||
containing a 'VP8L' chunk SHOULD NOT contain this chunk.
|
||||
containing a 'VP8L' Chunk SHOULD NOT contain this chunk.
|
||||
|
||||
**Rationale**: The transparency information is already part of the 'VP8L'
|
||||
chunk.
|
||||
Chunk.
|
||||
|
||||
The alpha channel data is stored as uncompressed raw data (when
|
||||
The alpha channel data is stored as uncompressed raw data (when the
|
||||
compression method is '0') or compressed using the lossless format
|
||||
(when the compression method is '1').
|
||||
|
||||
* Raw data: consists of a byte sequence of length width * height,
|
||||
* Raw data: This consists of a byte sequence of length = width * height,
|
||||
containing all the 8-bit transparency values in scan order.
|
||||
|
||||
* Lossless format compression: the byte sequence is a compressed
|
||||
image-stream (as described in the [WebP Lossless Bitstream Format]
|
||||
[webpllspec]) of implicit dimension width x height. That is, this
|
||||
image-stream does NOT contain any headers describing the image dimension.
|
||||
* Lossless format compression: The byte sequence is a compressed
|
||||
image-stream (as described in ["WebP Lossless Bitstream Format"]
|
||||
[webpllspec]) of implicit dimensions width x height. That is, this
|
||||
image-stream does NOT contain any headers describing the image dimensions.
|
||||
|
||||
**Rationale**: the dimension is already known from other sources,
|
||||
so storing it again would be redundant and error-prone.
|
||||
**Rationale**: The dimensions are already known from other sources,
|
||||
so storing them again would be redundant and prone to error.
|
||||
|
||||
Once the image-stream is decoded into ARGB color values, following
|
||||
the process described in the lossless format specification, the
|
||||
transparency information must be extracted from the *green* channel
|
||||
of the ARGB quadruplet.
|
||||
Once the image-stream is decoded into Alpha, Red, Green, Blue (ARGB) color
|
||||
values, following the process described in the lossless format
|
||||
specification, the transparency information must be extracted from the
|
||||
*green* channel of the ARGB quadruplet.
|
||||
|
||||
**Rationale**: the green channel is allowed extra transformation
|
||||
**Rationale**: The green channel is allowed extra transformation
|
||||
steps in the specification -- unlike the other channels -- that can
|
||||
improve compression.
|
||||
|
||||
@ -630,22 +654,23 @@ compression method is '0') or compressed using the lossless format
|
||||
|
||||
This chunk contains compressed bitstream data for a single frame.
|
||||
|
||||
A bitstream chunk may be either (i) a VP8 chunk, using "VP8 " (note the
|
||||
significant fourth-character space) as its tag _or_ (ii) a VP8L chunk, using
|
||||
"VP8L" as its tag.
|
||||
A bitstream chunk may be either (i) a 'VP8 ' Chunk, using 'VP8 ' (note the
|
||||
significant fourth-character space) as its FourCC, _or_ (ii) a 'VP8L' Chunk,
|
||||
using 'VP8L' as its FourCC.
|
||||
|
||||
The formats of VP8 and VP8L chunks are as described in sections
|
||||
The formats of 'VP8 ' and 'VP8L' Chunks are as described in sections
|
||||
[Simple File Format (Lossy)](#simple-file-format-lossy)
|
||||
and [Simple File Format (Lossless)](#simple-file-format-lossless) respectively.
|
||||
and [Simple File Format (Lossless)](#simple-file-format-lossless), respectively.
|
||||
|
||||
#### Color profile
|
||||
#### 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
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ChunkHeader('ICCP') |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Color Profile |
|
||||
: Color Profile :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
Color Profile: _Chunk Size_ bytes
|
||||
@ -662,114 +687,145 @@ If this chunk is not present, sRGB SHOULD be assumed.
|
||||
|
||||
#### Metadata
|
||||
|
||||
Metadata can be stored in 'EXIF' or 'XMP ' chunks.
|
||||
Metadata can be stored in 'EXIF' or 'XMP ' Chunks.
|
||||
|
||||
There SHOULD be at most one chunk of each type ('EXIF' and 'XMP '). If there
|
||||
are more such chunks, readers MAY ignore all except the first one. Also, a file
|
||||
may possibly contain both 'EXIF' and 'XMP ' chunks.
|
||||
are more such chunks, readers MAY ignore all except the first one.
|
||||
|
||||
The chunks are defined as follows:
|
||||
|
||||
EXIF chunk:
|
||||
'EXIF' Chunk:
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ChunkHeader('EXIF') |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| EXIF Metadata |
|
||||
: Exif Metadata :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
EXIF Metadata: _Chunk Size_ bytes
|
||||
Exif Metadata: _Chunk Size_ bytes
|
||||
|
||||
: image metadata in EXIF format.
|
||||
: Image metadata in Exif format.
|
||||
|
||||
XMP chunk:
|
||||
'XMP ' Chunk:
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ChunkHeader('XMP ') |
|
||||
| |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| XMP Metadata |
|
||||
: XMP Metadata :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
XMP Metadata: _Chunk Size_ bytes
|
||||
|
||||
: image metadata in XMP format.
|
||||
: Image metadata in XMP format.
|
||||
|
||||
Note that the fourth character in the 'XMP ' FourCC is an ASCII space (0x20).
|
||||
|
||||
Additional guidance about handling metadata can be found in the
|
||||
Metadata Working Group's [Guidelines for Handling Metadata][metadata].
|
||||
Metadata Working Group's ["Guidelines for Handling Metadata"][metadata].
|
||||
|
||||
#### Unknown Chunks
|
||||
|
||||
A RIFF chunk (described in [this](#terminology-amp-basics) section) whose _chunk
|
||||
tag_ is different from any of the chunks described in this document, is
|
||||
A RIFF chunk (described in the [RIFF File Format](#riff-file-format) section)
|
||||
whose FourCC is different from any of the chunks described in this document, is
|
||||
considered an _unknown chunk_.
|
||||
|
||||
**Rationale**: Allowing unknown chunks gives a provision for future extension
|
||||
of the format, and also allows storage of any application-specific data.
|
||||
of the format and also allows storage of any application-specific data.
|
||||
|
||||
A file MAY contain unknown chunks:
|
||||
|
||||
* At the end of the file as described in [Extended WebP file
|
||||
header](#extended_header) section.
|
||||
* At the end of ANMF chunks as described in the
|
||||
* at the end of the file, as described in [Extended WebP file
|
||||
header](#extended_header) section, or
|
||||
* at the end of 'ANMF' Chunks, as described in the
|
||||
[Animation](#animation) section.
|
||||
|
||||
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 frames
|
||||
### Canvas Assembly from Frames
|
||||
|
||||
Here we provide an overview of how a reader should assemble a canvas in the
|
||||
case of an animated image. The notation _VP8X.field_ means the field in the
|
||||
'VP8X' chunk with the same description.
|
||||
Here we provide an overview of how a reader MUST assemble a canvas in the case
|
||||
of an animated image.
|
||||
|
||||
Displaying an _animated image_ canvas MUST be equivalent to the following
|
||||
pseudocode:
|
||||
The process begins with creating a canvas using the dimensions given in the
|
||||
'VP8X' Chunk, `Canvas Width Minus One + 1` pixels wide by `Canvas Height Minus
|
||||
One + 1` pixels high. The `Loop Count` field from the 'ANIM' Chunk controls how
|
||||
many times the animation process is repeated. This is `Loop Count - 1` for
|
||||
nonzero `Loop Count` values or infinite if the `Loop Count` is zero.
|
||||
|
||||
At the beginning of each loop iteration, the canvas is filled using the
|
||||
background color from the 'ANIM' Chunk or an application-defined color.
|
||||
|
||||
'ANMF' Chunks contain individual frames given in display order. Before rendering
|
||||
each frame, the previous frame's `Disposal method` is applied.
|
||||
|
||||
The rendering of the decoded frame begins at the Cartesian coordinates (`2 *
|
||||
Frame X`, `2 * Frame Y`), using the top-left corner of the canvas as the origin.
|
||||
`Frame Width Minus One + 1` pixels wide by `Frame Height Minus One + 1` pixels
|
||||
high are rendered onto the canvas using the `Blending method`.
|
||||
|
||||
The canvas is displayed for `Frame Duration` milliseconds. This continues until
|
||||
all frames given by 'ANMF' Chunks have been displayed. A new loop iteration is
|
||||
then begun, or the canvas is left in its final state if all iterations have been
|
||||
completed.
|
||||
|
||||
The following pseudocode illustrates the rendering process. The notation
|
||||
_VP8X.field_ means the field in the 'VP8X' Chunk with the same description.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
assert VP8X.flags.hasAnimation
|
||||
VP8X.flags.hasAnimation MUST be TRUE
|
||||
canvas ← new image of size VP8X.canvasWidth x VP8X.canvasHeight with
|
||||
background color ANIM.background_color.
|
||||
background color ANIM.background_color or
|
||||
application-defined color.
|
||||
loop_count ← ANIM.loopCount
|
||||
dispose_method ← ANIM.disposeMethod
|
||||
dispose_method ← Dispose to background color
|
||||
if loop_count == 0:
|
||||
loop_count = ∞
|
||||
loop_count = ∞
|
||||
frame_params ← nil
|
||||
assert next chunk in image_data is ANMF
|
||||
next chunk in image_data is ANMF MUST be TRUE
|
||||
for loop = 0..loop_count - 1
|
||||
clear canvas to ANIM.background_color or application defined color
|
||||
until eof or non-ANMF chunk
|
||||
frame_params.frameX = Frame X
|
||||
frame_params.frameY = Frame Y
|
||||
frame_params.frameWidth = Frame Width Minus One + 1
|
||||
frame_params.frameHeight = Frame Height Minus One + 1
|
||||
frame_params.frameDuration = Frame Duration
|
||||
frame_right = frame_params.frameX + frame_params.frameWidth
|
||||
frame_bottom = frame_params.frameY + frame_params.frameHeight
|
||||
assert VP8X.canvasWidth >= frame_right
|
||||
assert VP8X.canvasHeight >= frame_bottom
|
||||
for subchunk in 'Frame Data':
|
||||
if subchunk.tag == "ALPH":
|
||||
assert alpha subchunks not found in 'Frame Data' earlier
|
||||
frame_params.alpha = alpha_data
|
||||
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
|
||||
assert bitstream subchunks not found in 'Frame Data' earlier
|
||||
frame_params.bitstream = bitstream_data
|
||||
render frame with frame_params.alpha and frame_params.bitstream on
|
||||
canvas with top-left corner at (frame_params.frameX,
|
||||
frame_params.frameY), using dispose method dispose_method.
|
||||
canvas contains the decoded image.
|
||||
Show the contents of the canvas for frame_params.frameDuration * 1ms.
|
||||
clear canvas to ANIM.background_color or application-defined color
|
||||
until eof or non-ANMF chunk
|
||||
frame_params.frameX = Frame X
|
||||
frame_params.frameY = Frame Y
|
||||
frame_params.frameWidth = Frame Width Minus One + 1
|
||||
frame_params.frameHeight = Frame Height Minus One + 1
|
||||
frame_params.frameDuration = Frame Duration
|
||||
frame_right = frame_params.frameX + frame_params.frameWidth
|
||||
frame_bottom = frame_params.frameY + frame_params.frameHeight
|
||||
VP8X.canvasWidth >= frame_right MUST be TRUE
|
||||
VP8X.canvasHeight >= frame_bottom MUST be TRUE
|
||||
for subchunk in 'Frame Data':
|
||||
if subchunk.tag == "ALPH":
|
||||
alpha subchunks not found in 'Frame Data' earlier MUST be
|
||||
TRUE
|
||||
frame_params.alpha = alpha_data
|
||||
else if subchunk.tag == "VP8 " OR subchunk.tag == "VP8L":
|
||||
bitstream subchunks not found in 'Frame Data' earlier MUST
|
||||
be TRUE
|
||||
frame_params.bitstream = bitstream_data
|
||||
apply dispose_method.
|
||||
render frame with frame_params.alpha and frame_params.bitstream
|
||||
on canvas with top-left corner at (frame_params.frameX,
|
||||
frame_params.frameY), using Blending method
|
||||
frame_params.blendingMethod.
|
||||
canvas contains the decoded image.
|
||||
Show the contents of the canvas for
|
||||
frame_params.frameDuration * 1 ms.
|
||||
dispose_method = frame_params.disposeMethod
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
Example File Layouts
|
||||
--------------------
|
||||
|
||||
A lossy encoded image with alpha may look as follows:
|
||||
A lossy-encoded image with alpha may look as follows:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
RIFF/WEBP
|
||||
@ -778,16 +834,16 @@ RIFF/WEBP
|
||||
+- VP8 (bitstream)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A losslessly encoded image may look as follows:
|
||||
A lossless-encoded image may look as follows:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
RIFF/WEBP
|
||||
+- VP8X (descriptions of features used)
|
||||
+- XYZW (unknown chunk)
|
||||
+- VP8L (lossless bitstream)
|
||||
+- XYZW (unknown chunk)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A lossless image with ICC profile and XMP metadata may
|
||||
A lossless image with an ICC profile and XMP metadata may
|
||||
look as follows:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -798,7 +854,7 @@ RIFF/WEBP
|
||||
+- XMP (metadata)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An animated image with EXIF metadata may look as follows:
|
||||
An animated image with Exif metadata may look as follows:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
RIFF/WEBP
|
||||
@ -811,9 +867,11 @@ RIFF/WEBP
|
||||
+- EXIF (metadata)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[vp8spec]: https://datatracker.ietf.org/doc/html/rfc6386
|
||||
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt
|
||||
[iccspec]: https://www.color.org/icc_specs2.xalter
|
||||
[metadata]: https://web.archive.org/web/20180919181934/http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
|
||||
[rec601]: https://www.itu.int/rec/R-REC-BT.601
|
||||
[rfc 1166]: https://datatracker.ietf.org/doc/html/rfc1166
|
||||
[rfc 2119]: https://datatracker.ietf.org/doc/html/rfc2119
|
||||
[rfc 6386]: https://datatracker.ietf.org/doc/html/rfc6386
|
||||
[rfc 8174]: https://datatracker.ietf.org/doc/html/rfc8174
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,5 @@
|
||||
# Ignore this file during non-NDK builds.
|
||||
ifdef NDK_ROOT
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
################################################################################
|
||||
@ -91,3 +93,4 @@ LOCAL_STATIC_LIBRARIES := example_util imageio_util webp
|
||||
LOCAL_MODULE := webpinfo_example
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
endif # NDK_ROOT
|
||||
|
@ -47,7 +47,7 @@ anim_dump_LDADD += ../imageio/libimageenc.la
|
||||
anim_dump_LDADD += $(PNG_LIBS) $(GIF_LIBS) $(TIFF_LIBS) -lm
|
||||
|
||||
cwebp_SOURCES = cwebp.c stopwatch.h
|
||||
cwebp_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
cwebp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)
|
||||
cwebp_LDADD =
|
||||
cwebp_LDADD += libexample_util.la
|
||||
cwebp_LDADD += ../imageio/libimageio_util.la
|
||||
@ -92,7 +92,7 @@ webpmux_LDADD += ../src/mux/libwebpmux.la
|
||||
webpmux_LDADD += ../src/libwebp.la
|
||||
|
||||
img2webp_SOURCES = img2webp.c
|
||||
img2webp_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
img2webp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)
|
||||
img2webp_LDADD =
|
||||
img2webp_LDADD += libexample_util.la
|
||||
img2webp_LDADD += ../imageio/libimageio_util.la
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // for 'strtod'.
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // for 'strcmp'.
|
||||
|
||||
#include "./anim_util.h"
|
||||
@ -206,8 +206,9 @@ static void Help(void) {
|
||||
printf(" -version ............ print version number and exit\n");
|
||||
}
|
||||
|
||||
// Returns 0 on success, 1 if animation files differ, and 2 for any error.
|
||||
int main(int argc, const char* argv[]) {
|
||||
int return_code = -1;
|
||||
int return_code = 2;
|
||||
int dump_frames = 0;
|
||||
const char* dump_folder = NULL;
|
||||
double min_psnr = 0.;
|
||||
@ -269,18 +270,18 @@ int main(int argc, const char* argv[]) {
|
||||
}
|
||||
if (parse_error) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(return_code);
|
||||
}
|
||||
}
|
||||
if (argc < 3) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(return_code);
|
||||
}
|
||||
|
||||
|
||||
if (!got_input2) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(return_code);
|
||||
}
|
||||
|
||||
if (dump_frames) {
|
||||
@ -293,7 +294,7 @@ int main(int argc, const char* argv[]) {
|
||||
if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) {
|
||||
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n",
|
||||
(const W_CHAR*)files[i]);
|
||||
return_code = -2;
|
||||
return_code = 2;
|
||||
goto End;
|
||||
} else {
|
||||
MinimizeAnimationFrames(&images[i], max_diff);
|
||||
@ -304,7 +305,7 @@ int main(int argc, const char* argv[]) {
|
||||
premultiply, min_psnr)) {
|
||||
WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0],
|
||||
(const W_CHAR*)files[1]);
|
||||
return_code = -3;
|
||||
return_code = 1;
|
||||
} else {
|
||||
WPRINTF("\nFiles %s and %s are identical.\n", (const W_CHAR*)files[0],
|
||||
(const W_CHAR*)files[1]);
|
||||
|
@ -12,6 +12,7 @@
|
||||
// Author: Skal (pascal.massimino@gmail.com)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // for 'strcmp'.
|
||||
|
||||
#include "./anim_util.h"
|
||||
@ -35,6 +36,7 @@ static void Help(void) {
|
||||
printf(" -version ............ print version number and exit\n");
|
||||
}
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, const char* argv[]) {
|
||||
int error = 0;
|
||||
const W_CHAR* dump_folder = TO_W_CHAR(".");
|
||||
@ -47,7 +49,7 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
if (argc < 2) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (c = 1; !error && c < argc; ++c) {
|
||||
@ -73,7 +75,7 @@ int main(int argc, const char* argv[]) {
|
||||
suffix = TO_W_CHAR("pam");
|
||||
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-version")) {
|
||||
int dec_version, demux_version;
|
||||
GetAnimatedImageVersions(&dec_version, &demux_version);
|
||||
@ -82,7 +84,7 @@ int main(int argc, const char* argv[]) {
|
||||
(dec_version >> 0) & 0xff,
|
||||
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
|
||||
(demux_version >> 0) & 0xff);
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else {
|
||||
uint32_t i;
|
||||
AnimatedImage image;
|
||||
@ -98,7 +100,11 @@ int main(int argc, const char* argv[]) {
|
||||
for (i = 0; !error && i < image.num_frames; ++i) {
|
||||
W_CHAR out_file[1024];
|
||||
WebPDecBuffer buffer;
|
||||
WebPInitDecBuffer(&buffer);
|
||||
if (!WebPInitDecBuffer(&buffer)) {
|
||||
fprintf(stderr, "Cannot init dec buffer\n");
|
||||
error = 1;
|
||||
continue;
|
||||
}
|
||||
buffer.colorspace = MODE_RGBA;
|
||||
buffer.is_external_memory = 1;
|
||||
buffer.width = image.canvas_width;
|
||||
@ -117,5 +123,5 @@ int main(int argc, const char* argv[]) {
|
||||
ClearAnimatedImage(&image);
|
||||
}
|
||||
}
|
||||
FREE_WARGV_AND_RETURN(error ? 1 : 0);
|
||||
FREE_WARGV_AND_RETURN(error ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ static int ReadAnimatedWebP(const char filename[],
|
||||
image->bgcolor = anim_info.bgcolor;
|
||||
|
||||
// Allocate frames.
|
||||
if (!AllocateFrames(image, anim_info.frame_count)) return 0;
|
||||
if (!AllocateFrames(image, anim_info.frame_count)) goto End;
|
||||
|
||||
// Decode frames.
|
||||
while (WebPAnimDecoderHasMoreFrames(dec)) {
|
||||
@ -558,7 +558,10 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
||||
}
|
||||
}
|
||||
// Allocate frames.
|
||||
AllocateFrames(image, frame_count);
|
||||
if (!AllocateFrames(image, frame_count)) {
|
||||
DGifCloseFile(gif, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
canvas_width = image->canvas_width;
|
||||
canvas_height = image->canvas_height;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "../imageio/webpdec.h"
|
||||
#include "./stopwatch.h"
|
||||
#include "./unicode.h"
|
||||
#include "sharpyuv/sharpyuv.h"
|
||||
#include "webp/encode.h"
|
||||
|
||||
#ifndef WEBP_DLL
|
||||
@ -177,8 +178,14 @@ static void PrintFullLosslessInfo(const WebPAuxStats* const stats,
|
||||
if (stats->lossless_features & 8) fprintf(stderr, " PALETTE");
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
fprintf(stderr, " * Precision Bits: histogram=%d transform=%d cache=%d\n",
|
||||
stats->histogram_bits, stats->transform_bits, stats->cache_bits);
|
||||
fprintf(stderr, " * Precision Bits: histogram=%d", stats->histogram_bits);
|
||||
if (stats->lossless_features & 1) {
|
||||
fprintf(stderr, " prediction=%d", stats->transform_bits);
|
||||
}
|
||||
if (stats->lossless_features & 2) {
|
||||
fprintf(stderr, " cross-color=%d", stats->cross_color_transform_bits);
|
||||
}
|
||||
fprintf(stderr, " cache=%d\n", stats->cache_bits);
|
||||
if (stats->palette_size > 0) {
|
||||
fprintf(stderr, " * Palette size: %d\n", stats->palette_size);
|
||||
}
|
||||
@ -305,6 +312,7 @@ static int MyWriter(const uint8_t* data, size_t data_size,
|
||||
// Dumps a picture as a PGM file using the IMC4 layout.
|
||||
static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
|
||||
int y;
|
||||
int ok = 0;
|
||||
const int uv_width = (picture->width + 1) / 2;
|
||||
const int uv_height = (picture->height + 1) / 2;
|
||||
const int stride = (picture->width + 1) & ~1;
|
||||
@ -319,23 +327,26 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
|
||||
if (f == NULL) return 0;
|
||||
fprintf(f, "P5\n%d %d\n255\n", stride, height);
|
||||
for (y = 0; y < picture->height; ++y) {
|
||||
if (fwrite(src_y, picture->width, 1, f) != 1) return 0;
|
||||
if (fwrite(src_y, picture->width, 1, f) != 1) goto Error;
|
||||
if (picture->width & 1) fputc(0, f); // pad
|
||||
src_y += picture->y_stride;
|
||||
}
|
||||
for (y = 0; y < uv_height; ++y) {
|
||||
if (fwrite(src_u, uv_width, 1, f) != 1) return 0;
|
||||
if (fwrite(src_v, uv_width, 1, f) != 1) return 0;
|
||||
if (fwrite(src_u, uv_width, 1, f) != 1) goto Error;
|
||||
if (fwrite(src_v, uv_width, 1, f) != 1) goto Error;
|
||||
src_u += picture->uv_stride;
|
||||
src_v += picture->uv_stride;
|
||||
}
|
||||
for (y = 0; y < alpha_height; ++y) {
|
||||
if (fwrite(src_a, picture->width, 1, f) != 1) return 0;
|
||||
if (fwrite(src_a, picture->width, 1, f) != 1) goto Error;
|
||||
if (picture->width & 1) fputc(0, f); // pad
|
||||
src_a += picture->a_stride;
|
||||
}
|
||||
ok = 1;
|
||||
|
||||
Error:
|
||||
fclose(f);
|
||||
return 1;
|
||||
return ok;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -571,7 +582,7 @@ static void HelpLong(void) {
|
||||
printf(" -qrange <min> <max> .... specifies the permissible quality range\n"
|
||||
" (default: 0 100)\n");
|
||||
printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n");
|
||||
printf(" -resize <w> <h> ........ resize picture (after any cropping)\n");
|
||||
printf(" -resize <w> <h> ........ resize picture (*after* any cropping)\n");
|
||||
printf(" -mt .................... use multi-threading if available\n");
|
||||
printf(" -low_memory ............ reduce memory usage (slower encoding)\n");
|
||||
printf(" -map <int> ............. print map of extra info\n");
|
||||
@ -591,9 +602,8 @@ static void HelpLong(void) {
|
||||
" green=0xe0 and blue=0xd0\n");
|
||||
printf(" -noalpha ............... discard any transparency information\n");
|
||||
printf(" -lossless .............. encode image losslessly, default=off\n");
|
||||
printf(" -near_lossless <int> ... use near-lossless image\n"
|
||||
" preprocessing (0..100=off), "
|
||||
"default=100\n");
|
||||
printf(" -near_lossless <int> ... use near-lossless image preprocessing\n"
|
||||
" (0..100=off), default=100\n");
|
||||
printf(" -hint <string> ......... specify image characteristics hint,\n");
|
||||
printf(" one of: photo, picture or graph\n");
|
||||
|
||||
@ -620,6 +630,7 @@ static void HelpLong(void) {
|
||||
printf(" -af .................... auto-adjust filter strength\n");
|
||||
printf(" -pre <int> ............. pre-processing filter\n");
|
||||
printf("\n");
|
||||
printf("Supported input formats:\n %s\n", WebPGetEnabledInputFileFormats());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -646,8 +657,9 @@ static const char* const kErrorMessages[VP8_ENC_ERROR_LAST] = {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, const char* argv[]) {
|
||||
int return_value = -1;
|
||||
int return_value = EXIT_FAILURE;
|
||||
const char* in_file = NULL, *out_file = NULL, *dump_file = NULL;
|
||||
FILE* out = NULL;
|
||||
int c;
|
||||
@ -681,22 +693,22 @@ int main(int argc, const char* argv[]) {
|
||||
!WebPPictureInit(&original_picture) ||
|
||||
!WebPConfigInit(&config)) {
|
||||
fprintf(stderr, "Error! Version mismatch!\n");
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
HelpShort();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
for (c = 1; c < argc; ++c) {
|
||||
int parse_error = 0;
|
||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||
HelpShort();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
|
||||
HelpLong();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-o") && c + 1 < argc) {
|
||||
out_file = (const char*)GET_WARGV(argv, ++c);
|
||||
} else if (!strcmp(argv[c], "-d") && c + 1 < argc) {
|
||||
@ -831,9 +843,13 @@ int main(int argc, const char* argv[]) {
|
||||
#endif
|
||||
} else if (!strcmp(argv[c], "-version")) {
|
||||
const int version = WebPGetEncoderVersion();
|
||||
const int sharpyuv_version = SharpYuvGetVersion();
|
||||
printf("%d.%d.%d\n",
|
||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
printf("libsharpyuv: %d.%d.%d\n",
|
||||
(sharpyuv_version >> 24) & 0xff, (sharpyuv_version >> 16) & 0xffff,
|
||||
sharpyuv_version & 0xff);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-progress")) {
|
||||
show_progress = 1;
|
||||
} else if (!strcmp(argv[c], "-quiet")) {
|
||||
@ -895,7 +911,7 @@ int main(int argc, const char* argv[]) {
|
||||
if (i == kNumTokens) {
|
||||
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
|
||||
(int)(token - start), start);
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
start = token + 1;
|
||||
}
|
||||
@ -914,14 +930,14 @@ int main(int argc, const char* argv[]) {
|
||||
} else if (argv[c][0] == '-') {
|
||||
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
|
||||
HelpLong();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
} else {
|
||||
in_file = (const char*)GET_WARGV(argv, c);
|
||||
}
|
||||
|
||||
if (parse_error) {
|
||||
HelpLong();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (in_file == NULL) {
|
||||
@ -1139,9 +1155,10 @@ int main(int argc, const char* argv[]) {
|
||||
}
|
||||
|
||||
picture.use_argb = 1;
|
||||
if (!ReadWebP(memory_writer.mem, memory_writer.size, &picture,
|
||||
/*keep_alpha=*/WebPPictureHasTransparency(&picture),
|
||||
/*metadata=*/NULL)) {
|
||||
if (!ReadWebP(
|
||||
memory_writer.mem, memory_writer.size, &picture,
|
||||
/*keep_alpha=*/WebPPictureHasTransparency(&original_picture),
|
||||
/*metadata=*/NULL)) {
|
||||
fprintf(stderr, "Error! Cannot decode encoded WebP bitstream\n");
|
||||
fprintf(stderr, "Error code: %d (%s)\n", picture.error_code,
|
||||
kErrorMessages[picture.error_code]);
|
||||
@ -1221,7 +1238,7 @@ int main(int argc, const char* argv[]) {
|
||||
PrintMetadataInfo(&metadata, metadata_written);
|
||||
}
|
||||
}
|
||||
return_value = 0;
|
||||
return_value = EXIT_SUCCESS;
|
||||
|
||||
Error:
|
||||
WebPMemoryWriterClear(&memory_writer);
|
||||
|
@ -96,7 +96,7 @@ static void Help(void) {
|
||||
" -alpha_dither use alpha-plane dithering if needed\n"
|
||||
" -mt .......... use multi-threading\n"
|
||||
" -crop <x> <y> <w> <h> ... crop output with the given rectangle\n"
|
||||
" -resize <w> <h> ......... scale the output (*after* any cropping)\n"
|
||||
" -resize <w> <h> ......... resize output (*after* any cropping)\n"
|
||||
" -flip ........ flip the output vertically\n"
|
||||
" -alpha ....... only save the alpha plane\n"
|
||||
" -incremental . use incremental decoding (useful for tests)\n"
|
||||
@ -177,6 +177,7 @@ static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
||||
return external_buffer;
|
||||
}
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, const char* argv[]) {
|
||||
int ok = 0;
|
||||
const char* in_file = NULL;
|
||||
@ -197,14 +198,14 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
if (!WebPInitDecoderConfig(&config)) {
|
||||
fprintf(stderr, "Library version mismatch!\n");
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (c = 1; c < argc; ++c) {
|
||||
int parse_error = 0;
|
||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
|
||||
out_file = (const char*)GET_WARGV(argv, ++c);
|
||||
} else if (!strcmp(argv[c], "-alpha")) {
|
||||
@ -227,7 +228,7 @@ int main(int argc, const char* argv[]) {
|
||||
const int version = WebPGetDecoderVersion();
|
||||
printf("%d.%d.%d\n",
|
||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-pgm")) {
|
||||
format = PGM;
|
||||
} else if (!strcmp(argv[c], "-yuv")) {
|
||||
@ -293,21 +294,21 @@ int main(int argc, const char* argv[]) {
|
||||
} else if (argv[c][0] == '-') {
|
||||
fprintf(stderr, "Unknown option '%s'\n", argv[c]);
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
} else {
|
||||
in_file = (const char*)GET_WARGV(argv, c);
|
||||
}
|
||||
|
||||
if (parse_error) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_file == NULL) {
|
||||
fprintf(stderr, "missing input file!!\n");
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (quiet) verbose = 0;
|
||||
@ -316,7 +317,7 @@ int main(int argc, const char* argv[]) {
|
||||
VP8StatusCode status = VP8_STATUS_OK;
|
||||
size_t data_size = 0;
|
||||
if (!LoadWebP(in_file, &data, &data_size, bitstream)) {
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
@ -415,7 +416,7 @@ int main(int argc, const char* argv[]) {
|
||||
WebPFreeDecBuffer(output_buffer);
|
||||
WebPFree((void*)external_buffer);
|
||||
WebPFree((void*)data);
|
||||
FREE_WARGV_AND_RETURN(ok ? 0 : -1);
|
||||
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -103,7 +103,10 @@ int ExUtilInitCommandLineArguments(int argc, const char* argv[],
|
||||
}
|
||||
args->own_argv_ = 1;
|
||||
args->argv_ = (const char**)WebPMalloc(MAX_ARGC * sizeof(*args->argv_));
|
||||
if (args->argv_ == NULL) return 0;
|
||||
if (args->argv_ == NULL) {
|
||||
ExUtilDeleteCommandLineArguments(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
argc = 0;
|
||||
for (cur = strtok((char*)args->argv_data_.bytes, sep);
|
||||
@ -111,6 +114,7 @@ int ExUtilInitCommandLineArguments(int argc, const char* argv[],
|
||||
cur = strtok(NULL, sep)) {
|
||||
if (argc == MAX_ARGC) {
|
||||
fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC);
|
||||
ExUtilDeleteCommandLineArguments(args);
|
||||
return 0;
|
||||
}
|
||||
assert(strlen(cur) != 0);
|
||||
|
@ -96,6 +96,7 @@ static void Help(void) {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, const char* argv[]) {
|
||||
int verbose = 0;
|
||||
int gif_error = GIF_ERROR;
|
||||
@ -140,7 +141,7 @@ int main(int argc, const char* argv[]) {
|
||||
!WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) ||
|
||||
!WebPPictureInit(&prev_canvas)) {
|
||||
fprintf(stderr, "Error! Version mismatch!\n");
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
config.lossless = 1; // Use lossless compression by default.
|
||||
|
||||
@ -150,14 +151,14 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
if (argc == 1) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
for (c = 1; c < argc; ++c) {
|
||||
int parse_error = 0;
|
||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
|
||||
out_file = GET_WARGV(argv, ++c);
|
||||
} else if (!strcmp(argv[c], "-lossy")) {
|
||||
@ -216,7 +217,7 @@ int main(int argc, const char* argv[]) {
|
||||
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
|
||||
(int)(token - start), start);
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
start = token + 1;
|
||||
}
|
||||
@ -229,7 +230,7 @@ int main(int argc, const char* argv[]) {
|
||||
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
|
||||
enc_version & 0xff, (mux_version >> 16) & 0xff,
|
||||
(mux_version >> 8) & 0xff, mux_version & 0xff);
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-quiet")) {
|
||||
quiet = 1;
|
||||
enc_options.verbose = 0;
|
||||
@ -242,14 +243,14 @@ int main(int argc, const char* argv[]) {
|
||||
} else if (argv[c][0] == '-') {
|
||||
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
} else {
|
||||
in_file = GET_WARGV(argv, c);
|
||||
}
|
||||
|
||||
if (parse_error) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,8 +315,11 @@ int main(int argc, const char* argv[]) {
|
||||
frame.use_argb = 1;
|
||||
if (!WebPPictureAlloc(&frame)) goto End;
|
||||
GIFClearPic(&frame, NULL);
|
||||
WebPPictureCopy(&frame, &curr_canvas);
|
||||
WebPPictureCopy(&frame, &prev_canvas);
|
||||
if (!(WebPPictureCopy(&frame, &curr_canvas) &&
|
||||
WebPPictureCopy(&frame, &prev_canvas))) {
|
||||
fprintf(stderr, "Error allocating canvas.\n");
|
||||
goto End;
|
||||
}
|
||||
|
||||
// Background color.
|
||||
GIFGetBackgroundColor(gif->SColorMap, gif->SBackGroundColor,
|
||||
@ -590,7 +594,7 @@ int main(int argc, const char* argv[]) {
|
||||
#endif
|
||||
}
|
||||
|
||||
FREE_WARGV_AND_RETURN(!ok);
|
||||
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#else // !WEBP_HAVE_GIF
|
||||
@ -598,7 +602,7 @@ int main(int argc, const char* argv[]) {
|
||||
int main(int argc, const char* argv[]) {
|
||||
fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]);
|
||||
(void)argc;
|
||||
return 0;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -317,7 +317,7 @@ void GIFDisplayError(const GifFileType* const gif, int gif_error) {
|
||||
|
||||
#else // !WEBP_HAVE_GIF
|
||||
|
||||
static void ErrorGIFNotAvailable() {
|
||||
static void ErrorGIFNotAvailable(void) {
|
||||
fprintf(stderr, "GIF support not compiled. Please install the libgif-dev "
|
||||
"package before building.\n");
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "../imageio/imageio_util.h"
|
||||
#include "./stopwatch.h"
|
||||
#include "./unicode.h"
|
||||
#include "sharpyuv/sharpyuv.h"
|
||||
#include "webp/encode.h"
|
||||
#include "webp/mux.h"
|
||||
|
||||
@ -35,17 +36,22 @@
|
||||
|
||||
static void Help(void) {
|
||||
printf("Usage:\n\n");
|
||||
printf(" img2webp [file_options] [[frame_options] frame_file]...\n");
|
||||
printf("\n");
|
||||
printf(" img2webp [file_options] [[frame_options] frame_file]...");
|
||||
printf(" [-o webp_file]\n\n");
|
||||
|
||||
printf("File-level options (only used at the start of compression):\n");
|
||||
printf(" -min_size ............ minimize size\n");
|
||||
printf(" -loop <int> .......... loop count (default: 0, = infinite loop)\n");
|
||||
printf(" -kmax <int> .......... maximum number of frame between key-frames\n"
|
||||
" (0=only keyframes)\n");
|
||||
printf(" -kmin <int> .......... minimum number of frame between key-frames\n"
|
||||
" (0=disable key-frames altogether)\n");
|
||||
printf(" -mixed ............... use mixed lossy/lossless automatic mode\n");
|
||||
printf(" -near_lossless <int> . use near-lossless image preprocessing\n"
|
||||
" (0..100=off), default=100\n");
|
||||
printf(" -sharp_yuv ........... use sharper (and slower) RGB->YUV "
|
||||
"conversion\n "
|
||||
"(lossy only)\n");
|
||||
printf(" -loop <int> .......... loop count (default: 0, = infinite loop)\n");
|
||||
printf(" -v ................... verbose mode\n");
|
||||
printf(" -h ................... this help\n");
|
||||
printf(" -version ............. print version number and exit\n");
|
||||
@ -53,10 +59,14 @@ static void Help(void) {
|
||||
|
||||
printf("Per-frame options (only used for subsequent images input):\n");
|
||||
printf(" -d <int> ............. frame duration in ms (default: 100)\n");
|
||||
printf(" -lossless ........... use lossless mode (default)\n");
|
||||
printf(" -lossy ... ........... use lossy mode\n");
|
||||
printf(" -lossless ............ use lossless mode (default)\n");
|
||||
printf(" -lossy ............... use lossy mode\n");
|
||||
printf(" -q <float> ........... quality\n");
|
||||
printf(" -m <int> ............. method to use\n");
|
||||
printf(" -exact, -noexact ..... preserve or alter RGB values in transparent "
|
||||
"area\n"
|
||||
" (default: -noexact, may cause artifacts\n"
|
||||
" with lossy animations)\n");
|
||||
|
||||
printf("\n");
|
||||
printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
|
||||
@ -65,6 +75,8 @@ static void Help(void) {
|
||||
"arguments will be\n");
|
||||
printf("tokenized from this file. The file name must not start with "
|
||||
"the character '-'.\n");
|
||||
printf("\nSupported input formats:\n %s\n",
|
||||
WebPGetEnabledInputFileFormats());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -122,6 +134,7 @@ static int SetLoopCount(int loop_count, WebPData* const webp_data) {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, const char* argv[]) {
|
||||
const char* output = NULL;
|
||||
WebPAnimEncoder* enc = NULL;
|
||||
@ -143,7 +156,7 @@ int main(int argc, const char* argv[]) {
|
||||
INIT_WARGV(argc, argv);
|
||||
|
||||
ok = ExUtilInitCommandLineArguments(argc - 1, argv + 1, &cmd_args);
|
||||
if (!ok) FREE_WARGV_AND_RETURN(1);
|
||||
if (!ok) FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
|
||||
argc = cmd_args.argc_;
|
||||
argv = cmd_args.argv_;
|
||||
@ -182,18 +195,26 @@ int main(int argc, const char* argv[]) {
|
||||
} else if (!strcmp(argv[c], "-mixed")) {
|
||||
anim_config.allow_mixed = 1;
|
||||
config.lossless = 0;
|
||||
} else if (!strcmp(argv[c], "-near_lossless") && c + 1 < argc) {
|
||||
argv[c] = NULL;
|
||||
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||
} else if (!strcmp(argv[c], "-sharp_yuv")) {
|
||||
config.use_sharp_yuv = 1;
|
||||
} else if (!strcmp(argv[c], "-v")) {
|
||||
verbose = 1;
|
||||
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||
Help();
|
||||
goto End;
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-version")) {
|
||||
const int enc_version = WebPGetEncoderVersion();
|
||||
const int mux_version = WebPGetMuxVersion();
|
||||
const int sharpyuv_version = SharpYuvGetVersion();
|
||||
printf("WebP Encoder version: %d.%d.%d\nWebP Mux version: %d.%d.%d\n",
|
||||
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
|
||||
enc_version & 0xff, (mux_version >> 16) & 0xff,
|
||||
(mux_version >> 8) & 0xff, mux_version & 0xff);
|
||||
printf("libsharpyuv: %d.%d.%d\n", (sharpyuv_version >> 24) & 0xff,
|
||||
(sharpyuv_version >> 16) & 0xffff, sharpyuv_version & 0xff);
|
||||
goto End;
|
||||
} else {
|
||||
continue;
|
||||
@ -231,6 +252,10 @@ int main(int argc, const char* argv[]) {
|
||||
fprintf(stderr, "Invalid negative duration (%d)\n", duration);
|
||||
parse_error = 1;
|
||||
}
|
||||
} else if (!strcmp(argv[c], "-exact")) {
|
||||
config.exact = 1;
|
||||
} else if (!strcmp(argv[c], "-noexact")) {
|
||||
config.exact = 0;
|
||||
} else {
|
||||
parse_error = 1; // shouldn't be here.
|
||||
fprintf(stderr, "Unknown option [%s]\n", argv[c]);
|
||||
@ -319,5 +344,5 @@ int main(int argc, const char* argv[]) {
|
||||
}
|
||||
WebPDataClear(&webp_data);
|
||||
ExUtilDeleteCommandLineArguments(&cmd_args);
|
||||
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
|
||||
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
@ -16,11 +16,15 @@
|
||||
#ifndef WEBP_EXAMPLES_UNICODE_H_
|
||||
#define WEBP_EXAMPLES_UNICODE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(_WIN32) && defined(_UNICODE)
|
||||
|
||||
// wchar_t is used instead of TCHAR because we only perform additional work when
|
||||
// Unicode is enabled and because the output of CommandLineToArgvW() is wchar_t.
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <wchar.h>
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
@ -55,8 +59,16 @@
|
||||
|
||||
#define WFOPEN(ARG, OPT) _wfopen((const W_CHAR*)ARG, TO_W_CHAR(OPT))
|
||||
|
||||
#define WPRINTF(STR, ...) wprintf(TO_W_CHAR(STR), __VA_ARGS__)
|
||||
#define WFPRINTF(STDERR, STR, ...) fwprintf(STDERR, TO_W_CHAR(STR), __VA_ARGS__)
|
||||
#define WFPRINTF(STREAM, STR, ...) \
|
||||
do { \
|
||||
int prev_mode; \
|
||||
fflush(STREAM); \
|
||||
prev_mode = _setmode(_fileno(STREAM), _O_U8TEXT); \
|
||||
fwprintf(STREAM, TO_W_CHAR(STR), __VA_ARGS__); \
|
||||
fflush(STREAM); \
|
||||
(void)_setmode(_fileno(STREAM), prev_mode); \
|
||||
} while (0)
|
||||
#define WPRINTF(STR, ...) WFPRINTF(stdout, STR, __VA_ARGS__)
|
||||
|
||||
#define WSTRLEN(FILENAME) wcslen((const W_CHAR*)FILENAME)
|
||||
#define WSTRCMP(FILENAME, STR) wcscmp((const W_CHAR*)FILENAME, TO_W_CHAR(STR))
|
||||
@ -65,6 +77,8 @@
|
||||
|
||||
#else
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// Unicode file paths work as is on Unix platforms, and no extra work is done on
|
||||
// Windows either if Unicode is disabled.
|
||||
|
||||
@ -83,7 +97,7 @@
|
||||
#define WFOPEN(ARG, OPT) fopen(ARG, OPT)
|
||||
|
||||
#define WPRINTF(STR, ...) printf(STR, __VA_ARGS__)
|
||||
#define WFPRINTF(STDERR, STR, ...) fprintf(STDERR, STR, __VA_ARGS__)
|
||||
#define WFPRINTF(STREAM, STR, ...) fprintf(STREAM, STR, __VA_ARGS__)
|
||||
|
||||
#define WSTRLEN(FILENAME) strlen(FILENAME)
|
||||
#define WSTRCMP(FILENAME, STR) strcmp(FILENAME, STR)
|
||||
|
@ -45,18 +45,19 @@ static GifFileType* DGifOpenFileUnicode(const W_CHAR* file_name, int* error) {
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(_UNICODE)
|
||||
|
||||
int file_handle = _wopen(file_name, _O_RDONLY | _O_BINARY);
|
||||
if (file_handle == -1) {
|
||||
if (error != NULL) *error = D_GIF_ERR_OPEN_FAILED;
|
||||
return NULL;
|
||||
}
|
||||
{
|
||||
int file_handle = _wopen(file_name, _O_RDONLY | _O_BINARY);
|
||||
if (file_handle == -1) {
|
||||
if (error != NULL) *error = D_GIF_ERR_OPEN_FAILED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if LOCAL_GIF_PREREQ(5, 0)
|
||||
return DGifOpenFileHandle(file_handle, error);
|
||||
return DGifOpenFileHandle(file_handle, error);
|
||||
#else
|
||||
return DGifOpenFileHandle(file_handle);
|
||||
return DGifOpenFileHandle(file_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define _POSIX_C_SOURCE 200112L // for setenv
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -292,6 +293,19 @@ static void PrintString(const char* const text) {
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintStringW(const char* const text) {
|
||||
#if defined(_WIN32) && defined(_UNICODE)
|
||||
void* const font = GLUT_BITMAP_9_BY_15;
|
||||
const W_CHAR* const wtext = (const W_CHAR*)text;
|
||||
int i;
|
||||
for (i = 0; wtext[i]; ++i) {
|
||||
glutBitmapCharacter(font, wtext[i]);
|
||||
}
|
||||
#else
|
||||
PrintString(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
static float GetColorf(uint32_t color, int shift) {
|
||||
return ((color >> shift) & 0xff) / 255.f;
|
||||
}
|
||||
@ -396,7 +410,7 @@ static void HandleDisplay(void) {
|
||||
|
||||
glColor4f(0.90f, 0.0f, 0.90f, 1.0f);
|
||||
glRasterPos2f(-0.95f, 0.90f);
|
||||
PrintString(kParams.file_name);
|
||||
PrintStringW(kParams.file_name);
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height);
|
||||
glColor4f(0.90f, 0.0f, 0.90f, 1.0f);
|
||||
@ -417,10 +431,13 @@ static void HandleDisplay(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void StartDisplay(void) {
|
||||
static void StartDisplay(const char* filename) {
|
||||
int width = kParams.canvas_width;
|
||||
int height = kParams.canvas_height;
|
||||
int screen_width, screen_height;
|
||||
const char viewername[] = " - WebP viewer";
|
||||
// max linux file len + viewername string
|
||||
char title[4096 + sizeof(viewername)] = "";
|
||||
// TODO(webp:365) GLUT_DOUBLE results in flickering / old frames to be
|
||||
// partially displayed with animated webp + alpha.
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
@ -440,8 +457,9 @@ static void StartDisplay(void) {
|
||||
height = screen_height;
|
||||
}
|
||||
}
|
||||
snprintf(title, sizeof(title), "%s%s", filename, viewername);
|
||||
glutInitWindowSize(width, height);
|
||||
glutCreateWindow("WebP viewer");
|
||||
glutCreateWindow(title);
|
||||
glutDisplayFunc(HandleDisplay);
|
||||
glutReshapeFunc(HandleReshape);
|
||||
glutIdleFunc(NULL);
|
||||
@ -480,7 +498,7 @@ static void Help(void) {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int c;
|
||||
int c, file_name_argv_index = 1;
|
||||
WebPDecoderConfig* const config = &kParams.config;
|
||||
WebPIterator* const curr = &kParams.curr_frame;
|
||||
|
||||
@ -488,7 +506,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
if (!WebPInitDecoderConfig(config)) {
|
||||
fprintf(stderr, "Library version mismatch!\n");
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
config->options.dithering_strength = 50;
|
||||
config->options.alpha_dithering_strength = 100;
|
||||
@ -500,7 +518,7 @@ int main(int argc, char* argv[]) {
|
||||
int parse_error = 0;
|
||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-noicc")) {
|
||||
kParams.use_color_profile = 0;
|
||||
} else if (!strcmp(argv[c], "-nofancy")) {
|
||||
@ -523,30 +541,34 @@ int main(int argc, char* argv[]) {
|
||||
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
||||
dec_version & 0xff, (dmux_version >> 16) & 0xff,
|
||||
(dmux_version >> 8) & 0xff, dmux_version & 0xff);
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-mt")) {
|
||||
config->options.use_threads = 1;
|
||||
} else if (!strcmp(argv[c], "--")) {
|
||||
if (c < argc - 1) kParams.file_name = (const char*)GET_WARGV(argv, ++c);
|
||||
if (c < argc - 1) {
|
||||
kParams.file_name = (const char*)GET_WARGV(argv, ++c);
|
||||
file_name_argv_index = c;
|
||||
}
|
||||
break;
|
||||
} else if (argv[c][0] == '-') {
|
||||
printf("Unknown option '%s'\n", argv[c]);
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
} else {
|
||||
kParams.file_name = (const char*)GET_WARGV(argv, c);
|
||||
file_name_argv_index = c;
|
||||
}
|
||||
|
||||
if (parse_error) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (kParams.file_name == NULL) {
|
||||
printf("missing input file!!\n");
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (!ImgIoUtilReadFile(kParams.file_name,
|
||||
@ -600,7 +622,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Position iterator to last frame. Next call to HandleDisplay will wrap over.
|
||||
// We take this into account by bumping up loop_count.
|
||||
WebPDemuxGetFrame(kParams.dmux, 0, curr);
|
||||
if (!WebPDemuxGetFrame(kParams.dmux, 0, curr)) goto Error;
|
||||
if (kParams.loop_count) ++kParams.loop_count;
|
||||
|
||||
#if defined(__unix__) || defined(__CYGWIN__)
|
||||
@ -614,18 +636,18 @@ int main(int argc, char* argv[]) {
|
||||
#ifdef FREEGLUT
|
||||
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
|
||||
#endif
|
||||
StartDisplay();
|
||||
StartDisplay(argv[file_name_argv_index]);
|
||||
|
||||
if (kParams.has_animation) glutTimerFunc(0, decode_callback, 0);
|
||||
glutMainLoop();
|
||||
|
||||
// Should only be reached when using FREEGLUT:
|
||||
ClearParams();
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
|
||||
Error:
|
||||
ClearParams();
|
||||
FREE_WARGV_AND_RETURN(-1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#else // !WEBP_HAVE_GL
|
||||
@ -633,7 +655,7 @@ int main(int argc, char* argv[]) {
|
||||
int main(int argc, const char* argv[]) {
|
||||
fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]);
|
||||
(void)argc;
|
||||
return 0;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "webp/config.h"
|
||||
@ -357,12 +358,12 @@ static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data,
|
||||
}
|
||||
data += 3;
|
||||
data_size -= 3;
|
||||
printf(" Key frame: %s\n"
|
||||
" Profile: %d\n"
|
||||
" Display: %s\n"
|
||||
" Part. 0 length: %d\n",
|
||||
key_frame ? "Yes" : "No", profile,
|
||||
display ? "Yes" : "No", partition0_length);
|
||||
printf(
|
||||
" Key frame: %s\n"
|
||||
" Profile: %d\n"
|
||||
" Display: Yes\n"
|
||||
" Part. 0 length: %d\n",
|
||||
key_frame ? "Yes" : "No", profile, partition0_length);
|
||||
if (key_frame) {
|
||||
if (!(data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a)) {
|
||||
LOG_ERROR("Invalid lossy bitstream signature.");
|
||||
@ -1120,6 +1121,7 @@ static void Help(void) {
|
||||
" -bitstream_info .... Parse bitstream header.\n");
|
||||
}
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, const char* argv[]) {
|
||||
int c, quiet = 0, show_diag = 0, show_summary = 0;
|
||||
int parse_bitstream = 0;
|
||||
@ -1130,7 +1132,7 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
if (argc == 1) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
// Parse command-line input.
|
||||
@ -1138,7 +1140,7 @@ int main(int argc, const char* argv[]) {
|
||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help") ||
|
||||
!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(WEBP_INFO_OK);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else if (!strcmp(argv[c], "-quiet")) {
|
||||
quiet = 1;
|
||||
} else if (!strcmp(argv[c], "-diag")) {
|
||||
@ -1151,7 +1153,7 @@ int main(int argc, const char* argv[]) {
|
||||
const int version = WebPGetDecoderVersion();
|
||||
printf("WebP Decoder version: %d.%d.%d\n",
|
||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else { // Assume the remaining are all input files.
|
||||
break;
|
||||
}
|
||||
@ -1159,7 +1161,7 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
if (c == argc) {
|
||||
Help();
|
||||
FREE_WARGV_AND_RETURN(WEBP_INFO_INVALID_COMMAND);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Process input files one by one.
|
||||
@ -1182,5 +1184,6 @@ int main(int argc, const char* argv[]) {
|
||||
webp_info_status = AnalyzeWebP(&webp_info, &webp_data);
|
||||
WebPDataClear(&webp_data);
|
||||
}
|
||||
FREE_WARGV_AND_RETURN(webp_info_status);
|
||||
FREE_WARGV_AND_RETURN((webp_info_status == WEBP_INFO_OK) ? EXIT_SUCCESS
|
||||
: EXIT_FAILURE);
|
||||
}
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webp/decode.h"
|
||||
#include "webp/mux.h"
|
||||
#include "../examples/example_util.h"
|
||||
@ -150,16 +151,20 @@ static const char* ErrorString(WebPMuxError err) {
|
||||
}
|
||||
|
||||
#define RETURN_IF_ERROR(ERR_MSG) \
|
||||
if (err != WEBP_MUX_OK) { \
|
||||
fprintf(stderr, ERR_MSG); \
|
||||
return err; \
|
||||
}
|
||||
do { \
|
||||
if (err != WEBP_MUX_OK) { \
|
||||
fprintf(stderr, ERR_MSG); \
|
||||
return err; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RETURN_IF_ERROR3(ERR_MSG, FORMAT_STR1, FORMAT_STR2) \
|
||||
if (err != WEBP_MUX_OK) { \
|
||||
fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \
|
||||
return err; \
|
||||
}
|
||||
do { \
|
||||
if (err != WEBP_MUX_OK) { \
|
||||
fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2); \
|
||||
return err; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ERROR_GOTO1(ERR_MSG, LABEL) \
|
||||
do { \
|
||||
@ -329,7 +334,7 @@ static void PrintHelp(void) {
|
||||
printf("\n");
|
||||
printf("DURATION_OPTIONS:\n");
|
||||
printf(" Set duration of selected frames:\n");
|
||||
printf(" duration set duration for each frames\n");
|
||||
printf(" duration set duration for all frames\n");
|
||||
printf(" duration,frame set duration of a particular frame\n");
|
||||
printf(" duration,start,end set duration of frames in the\n");
|
||||
printf(" interval [start,end])\n");
|
||||
@ -348,7 +353,7 @@ static void PrintHelp(void) {
|
||||
printf("\n");
|
||||
printf("FRAME_OPTIONS(i):\n");
|
||||
printf(" Create animation:\n");
|
||||
printf(" file_i +di+[xi+yi[+mi[bi]]]\n");
|
||||
printf(" file_i +di[+xi+yi[+mi[bi]]]\n");
|
||||
printf(" where: 'file_i' is the i'th animation frame (WebP format),\n");
|
||||
printf(" 'di' is the pause duration before next frame,\n");
|
||||
printf(" 'xi','yi' specify the image offset for this frame,\n");
|
||||
@ -460,7 +465,8 @@ static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) {
|
||||
if (err == WEBP_MUX_OK && metadata.size > 0) {
|
||||
err = WebPMuxSetChunk(new_mux, kFourccList[i], &metadata, 1);
|
||||
if (err != WEBP_MUX_OK) {
|
||||
ERROR_GOTO1("Error transferring metadata in DuplicateMux().", End);
|
||||
ERROR_GOTO1("Error transferring metadata in DuplicateMuxHeader().",
|
||||
End);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -604,20 +610,26 @@ static int ValidateCommandLine(const CommandLineArguments* const cmd_args,
|
||||
#define FEATURETYPE_IS_NIL (config->type_ == NIL_FEATURE)
|
||||
|
||||
#define CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL) \
|
||||
if (argc < i + (NUM)) { \
|
||||
fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \
|
||||
goto LABEL; \
|
||||
}
|
||||
do { \
|
||||
if (argc < i + (NUM)) { \
|
||||
fprintf(stderr, "ERROR: Too few arguments for '%s'.\n", argv[i]); \
|
||||
goto LABEL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_NUM_ARGS_AT_MOST(NUM, LABEL) \
|
||||
if (argc > i + (NUM)) { \
|
||||
fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \
|
||||
goto LABEL; \
|
||||
}
|
||||
do { \
|
||||
if (argc > i + (NUM)) { \
|
||||
fprintf(stderr, "ERROR: Too many arguments for '%s'.\n", argv[i]); \
|
||||
goto LABEL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_NUM_ARGS_EXACTLY(NUM, LABEL) \
|
||||
CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \
|
||||
CHECK_NUM_ARGS_AT_MOST(NUM, LABEL);
|
||||
do { \
|
||||
CHECK_NUM_ARGS_AT_LEAST(NUM, LABEL); \
|
||||
CHECK_NUM_ARGS_AT_MOST(NUM, LABEL); \
|
||||
} while (0)
|
||||
|
||||
// Parses command-line arguments to fill up config object. Also performs some
|
||||
// semantic checks. unicode_argv contains wchar_t arguments or is null.
|
||||
@ -684,7 +696,7 @@ static int ParseCommandLine(Config* config, const W_CHAR** const unicode_argv) {
|
||||
ERROR_GOTO1("ERROR: Multiple features specified.\n", ErrParse);
|
||||
}
|
||||
arg->subtype_ = SUBTYPE_ANMF;
|
||||
arg->filename_ = argv[i + 1];
|
||||
arg->filename_ = wargv[i + 1];
|
||||
arg->params_ = argv[i + 2];
|
||||
++feature_arg_index;
|
||||
i += 3;
|
||||
@ -1214,6 +1226,7 @@ static int Process(const Config* config) {
|
||||
//------------------------------------------------------------------------------
|
||||
// Main.
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, const char* argv[]) {
|
||||
Config config;
|
||||
int ok;
|
||||
@ -1227,7 +1240,7 @@ int main(int argc, const char* argv[]) {
|
||||
PrintHelp();
|
||||
}
|
||||
DeleteConfig(&config);
|
||||
FREE_WARGV_AND_RETURN(!ok);
|
||||
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -7,6 +7,7 @@ noinst_HEADERS += ../src/webp/types.h
|
||||
|
||||
libwebpextras_la_SOURCES =
|
||||
libwebpextras_la_SOURCES += extras.c extras.h quality_estimate.c
|
||||
libwebpextras_la_SOURCES += sharpyuv_risk_table.c sharpyuv_risk_table.h
|
||||
|
||||
libwebpextras_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
libwebpextras_la_LDFLAGS = -lm
|
||||
|
170
extras/extras.c
170
extras/extras.c
@ -11,15 +11,21 @@
|
||||
//
|
||||
|
||||
#include "extras/extras.h"
|
||||
#include "webp/format_constants.h"
|
||||
#include "src/dsp/dsp.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "extras/sharpyuv_risk_table.h"
|
||||
#include "sharpyuv/sharpyuv.h"
|
||||
#include "src/dsp/dsp.h"
|
||||
#include "src/utils/utils.h"
|
||||
#include "webp/format_constants.h"
|
||||
#include "webp/types.h"
|
||||
|
||||
#define XTRA_MAJ_VERSION 1
|
||||
#define XTRA_MIN_VERSION 2
|
||||
#define XTRA_REV_VERSION 2
|
||||
#define XTRA_MIN_VERSION 4
|
||||
#define XTRA_REV_VERSION 0
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -160,3 +166,159 @@ int WebPUnmultiplyARGB(WebPPicture* pic) {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 420 risk metric
|
||||
|
||||
#define YUV_FIX 16 // fixed-point precision for RGB->YUV
|
||||
static const int kYuvHalf = 1 << (YUV_FIX - 1);
|
||||
|
||||
// Maps a value in [0, (256 << YUV_FIX) - 1] to [0,
|
||||
// precomputed_scores_table_sampling - 1]. It is important that the extremal
|
||||
// values are preserved and 1:1 mapped:
|
||||
// ConvertValue(0) = 0
|
||||
// ConvertValue((256 << 16) - 1) = rgb_sampling_size - 1
|
||||
static int SharpYuvConvertValueToSampledIdx(int v, int rgb_sampling_size) {
|
||||
v = (v + kYuvHalf) >> YUV_FIX;
|
||||
v = (v < 0) ? 0 : (v > 255) ? 255 : v;
|
||||
return (v * (rgb_sampling_size - 1)) / 255;
|
||||
}
|
||||
|
||||
#undef YUV_FIX
|
||||
|
||||
// For each pixel, computes the index to look up that color in a precomputed
|
||||
// risk score table where the YUV space is subsampled to a size of
|
||||
// precomputed_scores_table_sampling^3 (see sharpyuv_risk_table.h)
|
||||
static int SharpYuvConvertToYuvSharpnessIndex(
|
||||
int r, int g, int b, const SharpYuvConversionMatrix* matrix,
|
||||
int precomputed_scores_table_sampling) {
|
||||
const int y = SharpYuvConvertValueToSampledIdx(
|
||||
matrix->rgb_to_y[0] * r + matrix->rgb_to_y[1] * g +
|
||||
matrix->rgb_to_y[2] * b + matrix->rgb_to_y[3],
|
||||
precomputed_scores_table_sampling);
|
||||
const int u = SharpYuvConvertValueToSampledIdx(
|
||||
matrix->rgb_to_u[0] * r + matrix->rgb_to_u[1] * g +
|
||||
matrix->rgb_to_u[2] * b + matrix->rgb_to_u[3],
|
||||
precomputed_scores_table_sampling);
|
||||
const int v = SharpYuvConvertValueToSampledIdx(
|
||||
matrix->rgb_to_v[0] * r + matrix->rgb_to_v[1] * g +
|
||||
matrix->rgb_to_v[2] * b + matrix->rgb_to_v[3],
|
||||
precomputed_scores_table_sampling);
|
||||
return y + u * precomputed_scores_table_sampling +
|
||||
v * precomputed_scores_table_sampling *
|
||||
precomputed_scores_table_sampling;
|
||||
}
|
||||
|
||||
static void SharpYuvRowToYuvSharpnessIndex(
|
||||
const uint8_t* r_ptr, const uint8_t* g_ptr, const uint8_t* b_ptr,
|
||||
int rgb_step, int rgb_bit_depth, int width, uint16_t* dst,
|
||||
const SharpYuvConversionMatrix* matrix,
|
||||
int precomputed_scores_table_sampling) {
|
||||
int i;
|
||||
assert(rgb_bit_depth == 8);
|
||||
(void)rgb_bit_depth; // Unused for now.
|
||||
for (i = 0; i < width;
|
||||
++i, r_ptr += rgb_step, g_ptr += rgb_step, b_ptr += rgb_step) {
|
||||
dst[i] =
|
||||
SharpYuvConvertToYuvSharpnessIndex(r_ptr[0], g_ptr[0], b_ptr[0], matrix,
|
||||
precomputed_scores_table_sampling);
|
||||
}
|
||||
}
|
||||
|
||||
#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((uint64_t)(W) * (H), sizeof(T)))
|
||||
|
||||
static int DoEstimateRisk(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
||||
const uint8_t* b_ptr, int rgb_step, int rgb_stride,
|
||||
int rgb_bit_depth, int width, int height,
|
||||
const SharpYuvOptions* options,
|
||||
const uint8_t precomputed_scores_table[],
|
||||
int precomputed_scores_table_sampling,
|
||||
float* score_out) {
|
||||
const int sampling3 = precomputed_scores_table_sampling *
|
||||
precomputed_scores_table_sampling *
|
||||
precomputed_scores_table_sampling;
|
||||
const int kNoiseLevel = 4;
|
||||
double total_score = 0;
|
||||
double count = 0;
|
||||
// Rows of indices in
|
||||
uint16_t* row1 = SAFE_ALLOC(width, 1, uint16_t);
|
||||
uint16_t* row2 = SAFE_ALLOC(width, 1, uint16_t);
|
||||
uint16_t* tmp;
|
||||
int i, j;
|
||||
|
||||
if (row1 == NULL || row2 == NULL) {
|
||||
WebPFree(row1);
|
||||
WebPFree(row2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert the first row ahead.
|
||||
SharpYuvRowToYuvSharpnessIndex(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth,
|
||||
width, row2, options->yuv_matrix,
|
||||
precomputed_scores_table_sampling);
|
||||
|
||||
for (j = 1; j < height; ++j) {
|
||||
r_ptr += rgb_stride;
|
||||
g_ptr += rgb_stride;
|
||||
b_ptr += rgb_stride;
|
||||
// Swap row 1 and row 2.
|
||||
tmp = row1;
|
||||
row1 = row2;
|
||||
row2 = tmp;
|
||||
// Convert the row below.
|
||||
SharpYuvRowToYuvSharpnessIndex(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth,
|
||||
width, row2, options->yuv_matrix,
|
||||
precomputed_scores_table_sampling);
|
||||
for (i = 0; i < width - 1; ++i) {
|
||||
const int idx0 = row1[i + 0];
|
||||
const int idx1 = row1[i + 1];
|
||||
const int idx2 = row2[i + 0];
|
||||
const int score = precomputed_scores_table[idx0 + sampling3 * idx1] +
|
||||
precomputed_scores_table[idx0 + sampling3 * idx2] +
|
||||
precomputed_scores_table[idx1 + sampling3 * idx2];
|
||||
if (score > kNoiseLevel) {
|
||||
total_score += score;
|
||||
count += 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count > 0.) total_score /= count;
|
||||
|
||||
// If less than 1% of pixels were evaluated -> below noise level.
|
||||
if (100. * count / (width * height) < 1.) total_score = 0.;
|
||||
|
||||
// Rescale to [0:100]
|
||||
total_score = (total_score > 25.) ? 100. : total_score * 100. / 25.;
|
||||
|
||||
WebPFree(row1);
|
||||
WebPFree(row2);
|
||||
|
||||
*score_out = (float)total_score;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef SAFE_ALLOC
|
||||
|
||||
int SharpYuvEstimate420Risk(const void* r_ptr, const void* g_ptr,
|
||||
const void* b_ptr, int rgb_step, int rgb_stride,
|
||||
int rgb_bit_depth, int width, int height,
|
||||
const SharpYuvOptions* options, float* score) {
|
||||
if (width < 1 || height < 1 || width == INT_MAX || height == INT_MAX ||
|
||||
r_ptr == NULL || g_ptr == NULL || b_ptr == NULL || options == NULL ||
|
||||
score == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (rgb_bit_depth != 8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (width <= 4 || height <= 4) {
|
||||
*score = 0.0f; // too small, no real risk.
|
||||
return 1;
|
||||
}
|
||||
|
||||
return DoEstimateRisk(
|
||||
(const uint8_t*)r_ptr, (const uint8_t*)g_ptr, (const uint8_t*)b_ptr,
|
||||
rgb_step, rgb_stride, rgb_bit_depth, width, height, options,
|
||||
kSharpYuvPrecomputedRisk, kSharpYuvPrecomputedRiskYuvSampling, score);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -17,9 +17,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "sharpyuv/sharpyuv.h"
|
||||
#include "webp/encode.h"
|
||||
|
||||
#define WEBP_EXTRAS_ABI_VERSION 0x0002 // MAJOR(8b) + MINOR(8b)
|
||||
#define WEBP_EXTRAS_ABI_VERSION 0x0003 // MAJOR(8b) + MINOR(8b)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -70,6 +71,38 @@ WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Computes a score between 0 and 100 which represents the risk of having visual
|
||||
// quality loss from converting an RGB image to YUV420.
|
||||
// A low score, typically < 40, means there is a low risk of artifacts from
|
||||
// chroma subsampling and a simple averaging algorithm can be used instead of
|
||||
// the more expensive SharpYuvConvert function.
|
||||
// A medium score, typically >= 40 and < 70, means that simple chroma
|
||||
// subsampling will produce artifacts and it may be advisable to use the more
|
||||
// costly SharpYuvConvert for YUV420 conversion.
|
||||
// A high score, typically >= 70, means there is a very high risk of artifacts
|
||||
// from chroma subsampling even with SharpYuvConvert, and best results might be
|
||||
// achieved by using YUV444.
|
||||
// If not using SharpYuvConvert, a threshold of about 50 can be used to decide
|
||||
// between (simple averaging) 420 and 444.
|
||||
// r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point
|
||||
// to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise.
|
||||
// rgb_step: distance in bytes between two horizontally adjacent pixels on the
|
||||
// r, g and b channels. If rgb_bit_depth is > 8, it should be a
|
||||
// multiple of 2.
|
||||
// rgb_stride: distance in bytes between two vertically adjacent pixels on the
|
||||
// r, g, and b channels. If rgb_bit_depth is > 8, it should be a
|
||||
// multiple of 2.
|
||||
// rgb_bit_depth: number of bits for each r/g/b value. Only a value of 8 is
|
||||
// currently supported.
|
||||
// width, height: width and height of the image in pixels
|
||||
// Returns 0 on failure.
|
||||
WEBP_EXTERN int SharpYuvEstimate420Risk(
|
||||
const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step,
|
||||
int rgb_stride, int rgb_bit_depth, int width, int height,
|
||||
const SharpYuvOptions* options, float* score);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@ -223,13 +223,15 @@ static void Help(void) {
|
||||
" -o <file> . save the diff map as a WebP lossless file\n"
|
||||
" -scale .... scale the difference map to fit [0..255] range\n"
|
||||
" -gray ..... use grayscale for difference map (-scale)\n"
|
||||
" Also handles PNG, JPG and TIFF files, in addition to WebP.\n");
|
||||
"\nSupported input formats:\n %s\n",
|
||||
WebPGetEnabledInputFileFormats());
|
||||
}
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, const char* argv[]) {
|
||||
WebPPicture pic1, pic2;
|
||||
size_t size1 = 0, size2 = 0;
|
||||
int ret = 1;
|
||||
int ret = EXIT_FAILURE;
|
||||
float disto[5];
|
||||
int type = 0;
|
||||
int c;
|
||||
@ -245,7 +247,7 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
if (!WebPPictureInit(&pic1) || !WebPPictureInit(&pic2)) {
|
||||
fprintf(stderr, "Can't init pictures\n");
|
||||
FREE_WARGV_AND_RETURN(1);
|
||||
FREE_WARGV_AND_RETURN(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (c = 1; c < argc; ++c) {
|
||||
@ -261,7 +263,7 @@ int main(int argc, const char* argv[]) {
|
||||
use_gray = 1;
|
||||
} else if (!strcmp(argv[c], "-h")) {
|
||||
help = 1;
|
||||
ret = 0;
|
||||
ret = EXIT_SUCCESS;
|
||||
} else if (!strcmp(argv[c], "-o")) {
|
||||
if (++c == argc) {
|
||||
fprintf(stderr, "missing file name after %s option.\n", argv[c - 1]);
|
||||
@ -336,7 +338,8 @@ int main(int argc, const char* argv[]) {
|
||||
fprintf(stderr, "Error during lossless encoding.\n");
|
||||
goto End;
|
||||
}
|
||||
ret = ImgIoUtilWriteFile(output, data, data_size) ? 0 : 1;
|
||||
ret = ImgIoUtilWriteFile(output, data, data_size) ? EXIT_SUCCESS
|
||||
: EXIT_FAILURE;
|
||||
WebPFree(data);
|
||||
if (ret) goto End;
|
||||
#else
|
||||
@ -344,9 +347,10 @@ int main(int argc, const char* argv[]) {
|
||||
(void)data_size;
|
||||
fprintf(stderr, "Cannot save the difference map. Please recompile "
|
||||
"without the WEBP_REDUCE_CSP flag.\n");
|
||||
goto End;
|
||||
#endif // WEBP_REDUCE_CSP
|
||||
}
|
||||
ret = 0;
|
||||
ret = EXIT_SUCCESS;
|
||||
|
||||
End:
|
||||
WebPPictureFree(&pic1);
|
||||
|
6210
extras/sharpyuv_risk_table.c
Normal file
6210
extras/sharpyuv_risk_table.c
Normal file
File diff suppressed because it is too large
Load Diff
27
extras/sharpyuv_risk_table.h
Normal file
27
extras/sharpyuv_risk_table.h
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2023 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Precomputed data for 420 risk estimation.
|
||||
|
||||
#ifndef WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_
|
||||
#define WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_
|
||||
|
||||
#include "src/webp/types.h"
|
||||
|
||||
extern const int kSharpYuvPrecomputedRiskYuvSampling;
|
||||
// Table of precomputed risk scores when chroma subsampling images with two
|
||||
// given colors.
|
||||
// Since precomputing values for all possible YUV colors would create a huge
|
||||
// table, the YUV space (i.e. [0, 255]^3) is reduced to
|
||||
// [0, kSharpYuvPrecomputedRiskYuvSampling-1]^3
|
||||
// where 255 maps to kSharpYuvPrecomputedRiskYuvSampling-1.
|
||||
// Table size: kSharpYuvPrecomputedRiskYuvSampling^6 bytes or 114 KiB
|
||||
extern const uint8_t kSharpYuvPrecomputedRisk[];
|
||||
|
||||
#endif // WEBP_EXTRAS_SHARPYUV_RISK_TABLE_H_
|
@ -15,6 +15,7 @@
|
||||
// Author: James Zern (jzern@google.com)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "webp/config.h"
|
||||
@ -30,7 +31,7 @@
|
||||
#if defined(WEBP_HAVE_JUST_SDL_H)
|
||||
#include <SDL.h>
|
||||
#else
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#endif
|
||||
|
||||
static void ProcessEvents(void) {
|
||||
@ -49,6 +50,7 @@ static void ProcessEvents(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, char* argv[]) {
|
||||
int c;
|
||||
int ok = 0;
|
||||
@ -61,7 +63,7 @@ int main(int argc, char* argv[]) {
|
||||
size_t webp_size = 0;
|
||||
if (!strcmp(argv[c], "-h")) {
|
||||
printf("Usage: %s [-h] image.webp [more_files.webp...]\n", argv[0]);
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else {
|
||||
file = (const char*)GET_WARGV(argv, c);
|
||||
}
|
||||
@ -75,7 +77,7 @@ int main(int argc, char* argv[]) {
|
||||
fprintf(stderr, "File too large.\n");
|
||||
goto Error;
|
||||
}
|
||||
ok = WebpToSDL((const char*)webp, (int)webp_size);
|
||||
ok = WebPToSDL((const char*)webp, (int)webp_size);
|
||||
free((void*)webp);
|
||||
if (!ok) {
|
||||
WFPRINTF(stderr, "Error decoding file %s\n", (const W_CHAR*)file);
|
||||
@ -87,7 +89,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
Error:
|
||||
SDL_Quit();
|
||||
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
|
||||
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#else // !WEBP_HAVE_SDL
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "imageio/imageio_util.h"
|
||||
#include "../examples/unicode.h"
|
||||
|
||||
// Returns EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
||||
int main(int argc, const char* argv[]) {
|
||||
int c;
|
||||
int quiet = 0;
|
||||
@ -27,7 +28,7 @@ int main(int argc, const char* argv[]) {
|
||||
quiet = 1;
|
||||
} else if (!strcmp(argv[c], "-help") || !strcmp(argv[c], "-h")) {
|
||||
printf("webp_quality [-h][-quiet] webp_files...\n");
|
||||
FREE_WARGV_AND_RETURN(0);
|
||||
FREE_WARGV_AND_RETURN(EXIT_SUCCESS);
|
||||
} else {
|
||||
const char* const filename = (const char*)GET_WARGV(argv, c);
|
||||
const uint8_t* data = NULL;
|
||||
@ -50,5 +51,5 @@ int main(int argc, const char* argv[]) {
|
||||
free((void*)data);
|
||||
}
|
||||
}
|
||||
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
|
||||
FREE_WARGV_AND_RETURN(ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
@ -20,88 +20,75 @@
|
||||
#include "webp_to_sdl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "src/webp/decode.h"
|
||||
|
||||
#if defined(WEBP_HAVE_JUST_SDL_H)
|
||||
#include <SDL.h>
|
||||
#else
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#endif
|
||||
|
||||
static int init_ok = 0;
|
||||
int WebpToSDL(const char* data, unsigned int data_size) {
|
||||
int WebPToSDL(const char* data, unsigned int data_size) {
|
||||
int ok = 0;
|
||||
VP8StatusCode status;
|
||||
WebPDecoderConfig config;
|
||||
WebPBitstreamFeatures* const input = &config.input;
|
||||
WebPDecBuffer* const output = &config.output;
|
||||
SDL_Surface* screen = NULL;
|
||||
SDL_Surface* surface = NULL;
|
||||
|
||||
if (!WebPInitDecoderConfig(&config)) {
|
||||
fprintf(stderr, "Library version mismatch!\n");
|
||||
return 0;
|
||||
}
|
||||
WebPBitstreamFeatures input;
|
||||
uint8_t* output = NULL;
|
||||
SDL_Window* window = NULL;
|
||||
SDL_Renderer* renderer = NULL;
|
||||
SDL_Texture* texture = NULL;
|
||||
int width, height;
|
||||
|
||||
if (!init_ok) {
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
init_ok = 1;
|
||||
}
|
||||
|
||||
status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &config.input);
|
||||
status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &input);
|
||||
if (status != VP8_STATUS_OK) goto Error;
|
||||
width = input.width;
|
||||
height = input.height;
|
||||
|
||||
screen = SDL_SetVideoMode(input->width, input->height, 32, SDL_SWSURFACE);
|
||||
if (screen == NULL) {
|
||||
fprintf(stderr, "Unable to set video mode (32bpp %dx%d)!\n",
|
||||
input->width, input->height);
|
||||
SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer);
|
||||
if (window == NULL || renderer == NULL) {
|
||||
fprintf(stderr, "Unable to create window or renderer!\n");
|
||||
goto Error;
|
||||
}
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,
|
||||
"linear"); // make the scaled rendering look smoother.
|
||||
SDL_RenderSetLogicalSize(renderer, width, height);
|
||||
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
input->width, input->height, 32,
|
||||
0x000000ffu, // R mask
|
||||
0x0000ff00u, // G mask
|
||||
0x00ff0000u, // B mask
|
||||
0xff000000u); // A mask
|
||||
|
||||
if (surface == NULL) {
|
||||
fprintf(stderr, "Unable to create %dx%d RGBA surface!\n",
|
||||
input->width, input->height);
|
||||
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888,
|
||||
SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
if (texture == NULL) {
|
||||
fprintf(stderr, "Unable to create %dx%d RGBA texture!\n", width, height);
|
||||
goto Error;
|
||||
}
|
||||
if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
|
||||
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
output->colorspace = MODE_BGRA;
|
||||
output = WebPDecodeBGRA((const uint8_t*)data, (size_t)data_size, &width,
|
||||
&height);
|
||||
#else
|
||||
output->colorspace = MODE_RGBA;
|
||||
output = WebPDecodeRGBA((const uint8_t*)data, (size_t)data_size, &width,
|
||||
&height);
|
||||
#endif
|
||||
output->width = surface->w;
|
||||
output->height = surface->h;
|
||||
output->u.RGBA.rgba = surface->pixels;
|
||||
output->u.RGBA.stride = surface->pitch;
|
||||
output->u.RGBA.size = surface->pitch * surface->h;
|
||||
output->is_external_memory = 1;
|
||||
|
||||
status = WebPDecode((const uint8_t*)data, (size_t)data_size, &config);
|
||||
if (status != VP8_STATUS_OK) {
|
||||
if (output == NULL) {
|
||||
fprintf(stderr, "Error decoding image (%d)\n", status);
|
||||
goto Error;
|
||||
}
|
||||
|
||||
if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
|
||||
if (SDL_BlitSurface(surface, NULL, screen, NULL) ||
|
||||
SDL_Flip(screen)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
SDL_UpdateTexture(texture, NULL, output, width * sizeof(uint32_t));
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
ok = 1;
|
||||
|
||||
Error:
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_FreeSurface(screen);
|
||||
WebPFreeDecBuffer(output);
|
||||
// We should call SDL_DestroyWindow(window) but that makes .js fail.
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyTexture(texture);
|
||||
WebPFree(output);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
||||
#ifndef WEBP_EXTRAS_WEBP_TO_SDL_H_
|
||||
#define WEBP_EXTRAS_WEBP_TO_SDL_H_
|
||||
|
||||
// Exports the method WebpToSDL(const char* data, int data_size) which decodes
|
||||
// Exports the method WebPToSDL(const char* data, int data_size) which decodes
|
||||
// a WebP bitstream into an RGBA SDL surface.
|
||||
// Return false on failure.
|
||||
extern int WebpToSDL(const char* data, unsigned int data_size);
|
||||
extern int WebPToSDL(const char* data, unsigned int data_size);
|
||||
|
||||
#endif // WEBP_EXTRAS_WEBP_TO_SDL_H_
|
||||
|
@ -1,3 +1,5 @@
|
||||
# Ignore this file during non-NDK builds.
|
||||
ifdef NDK_ROOT
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
################################################################################
|
||||
@ -52,3 +54,4 @@ LOCAL_STATIC_LIBRARIES := imageio_util
|
||||
LOCAL_MODULE := imageenc
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
endif # NDK_ROOT
|
||||
|
@ -11,6 +11,24 @@
|
||||
|
||||
#include "./image_dec.h"
|
||||
|
||||
const char* WebPGetEnabledInputFileFormats(void) {
|
||||
return "WebP"
|
||||
#ifdef WEBP_HAVE_JPEG
|
||||
", JPEG"
|
||||
#endif
|
||||
#ifdef WEBP_HAVE_PNG
|
||||
", PNG"
|
||||
#endif
|
||||
", PNM (PGM, PPM, PAM)"
|
||||
#ifdef WEBP_HAVE_TIFF
|
||||
", TIFF"
|
||||
#endif
|
||||
#ifdef HAVE_WINCODEC_H
|
||||
", Windows Imaging Component (WIC)"
|
||||
#endif
|
||||
"";
|
||||
}
|
||||
|
||||
static WEBP_INLINE uint32_t GetBE32(const uint8_t buf[]) {
|
||||
return ((uint32_t)buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
||||
}
|
||||
|
@ -41,6 +41,9 @@ typedef enum {
|
||||
WEBP_UNSUPPORTED_FORMAT
|
||||
} WebPInputFileFormat;
|
||||
|
||||
// Returns a comma separated list of enabled input formats.
|
||||
const char* WebPGetEnabledInputFileFormats(void);
|
||||
|
||||
// Try to infer the image format. 'data_size' should be larger than 12.
|
||||
// Returns WEBP_UNSUPPORTED_FORMAT if format can't be guess safely.
|
||||
WebPInputFileFormat WebPGuessImageType(const uint8_t* const data,
|
||||
|
@ -260,14 +260,20 @@ int WebPWritePAM(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||
|
||||
// Save 16b mode (RGBA4444, RGB565, ...) for debugging purpose.
|
||||
int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||
const uint32_t width = buffer->width;
|
||||
const uint32_t height = buffer->height;
|
||||
const uint8_t* rgba = buffer->u.RGBA.rgba;
|
||||
const int stride = buffer->u.RGBA.stride;
|
||||
uint32_t width, height;
|
||||
uint8_t* rgba;
|
||||
int stride;
|
||||
const uint32_t bytes_per_px = 2;
|
||||
uint32_t y;
|
||||
|
||||
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
|
||||
if (fout == NULL || buffer == NULL) return 0;
|
||||
|
||||
width = buffer->width;
|
||||
height = buffer->height;
|
||||
rgba = buffer->u.RGBA.rgba;
|
||||
stride = buffer->u.RGBA.stride;
|
||||
|
||||
if (rgba == NULL) return 0;
|
||||
|
||||
fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height);
|
||||
for (y = 0; y < height; ++y) {
|
||||
@ -295,22 +301,29 @@ static void PutLE32(uint8_t* const dst, uint32_t value) {
|
||||
#define BMP_HEADER_SIZE 54
|
||||
#define BMP_HEADER_ALPHA_EXTRA_SIZE 16 // for alpha info
|
||||
int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
||||
const int header_size =
|
||||
BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0);
|
||||
const uint32_t width = buffer->width;
|
||||
const uint32_t height = buffer->height;
|
||||
const uint8_t* rgba = buffer->u.RGBA.rgba;
|
||||
const int stride = buffer->u.RGBA.stride;
|
||||
const uint32_t bytes_per_px = has_alpha ? 4 : 3;
|
||||
int has_alpha, header_size;
|
||||
uint32_t width, height;
|
||||
uint8_t* rgba;
|
||||
int stride;
|
||||
uint32_t y;
|
||||
const uint32_t line_size = bytes_per_px * width;
|
||||
const uint32_t bmp_stride = (line_size + 3) & ~3; // pad to 4
|
||||
const uint32_t image_size = bmp_stride * height;
|
||||
const uint32_t total_size = image_size + header_size;
|
||||
uint32_t bytes_per_px, line_size, image_size, bmp_stride, total_size;
|
||||
uint8_t bmp_header[BMP_HEADER_SIZE + BMP_HEADER_ALPHA_EXTRA_SIZE] = { 0 };
|
||||
|
||||
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
|
||||
if (fout == NULL || buffer == NULL) return 0;
|
||||
|
||||
has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
||||
header_size = BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0);
|
||||
width = buffer->width;
|
||||
height = buffer->height;
|
||||
rgba = buffer->u.RGBA.rgba;
|
||||
stride = buffer->u.RGBA.stride;
|
||||
bytes_per_px = has_alpha ? 4 : 3;
|
||||
line_size = bytes_per_px * width;
|
||||
bmp_stride = (line_size + 3) & ~3; // pad to 4
|
||||
image_size = bmp_stride * height;
|
||||
total_size = image_size + header_size;
|
||||
|
||||
if (rgba == NULL) return 0;
|
||||
|
||||
// bitmap file header
|
||||
PutLE16(bmp_header + 0, 0x4d42); // signature 'BM'
|
||||
@ -372,17 +385,14 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||
#define TIFF_HEADER_SIZE (EXTRA_DATA_OFFSET + EXTRA_DATA_SIZE)
|
||||
|
||||
int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
||||
const uint32_t width = buffer->width;
|
||||
const uint32_t height = buffer->height;
|
||||
const uint8_t* rgba = buffer->u.RGBA.rgba;
|
||||
const int stride = buffer->u.RGBA.stride;
|
||||
const uint8_t bytes_per_px = has_alpha ? 4 : 3;
|
||||
const uint8_t assoc_alpha =
|
||||
WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2;
|
||||
int has_alpha;
|
||||
uint32_t width, height;
|
||||
uint8_t* rgba;
|
||||
int stride;
|
||||
uint8_t bytes_per_px = 0;
|
||||
const uint8_t assoc_alpha = 0;
|
||||
// For non-alpha case, we omit tag 0x152 (ExtraSamples).
|
||||
const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES
|
||||
: NUM_IFD_ENTRIES - 1;
|
||||
const uint8_t num_ifd_entries = 0;
|
||||
uint8_t tiff_header[TIFF_HEADER_SIZE] = {
|
||||
0x49, 0x49, 0x2a, 0x00, // little endian signature
|
||||
8, 0, 0, 0, // offset to the unique IFD that follows
|
||||
@ -416,7 +426,20 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||
};
|
||||
uint32_t y;
|
||||
|
||||
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
|
||||
if (fout == NULL || buffer == NULL) return 0;
|
||||
|
||||
has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
||||
width = buffer->width;
|
||||
height = buffer->height;
|
||||
rgba = buffer->u.RGBA.rgba;
|
||||
stride = buffer->u.RGBA.stride;
|
||||
|
||||
if (rgba == NULL) return 0;
|
||||
|
||||
// Update bytes_per_px, num_ifd_entries and assoc_alpha.
|
||||
tiff_header[38] = tiff_header[102] = bytes_per_px = has_alpha ? 4 : 3;
|
||||
tiff_header[8] = has_alpha ? NUM_IFD_ENTRIES : NUM_IFD_ENTRIES - 1;
|
||||
tiff_header[186] = WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2;
|
||||
|
||||
// Fill placeholders in IFD:
|
||||
PutLE32(tiff_header + 10 + 8, width);
|
||||
|
@ -89,6 +89,11 @@ int ImgIoUtilReadFile(const char* const file_name,
|
||||
}
|
||||
fseek(in, 0, SEEK_END);
|
||||
file_size = ftell(in);
|
||||
if (file_size == (size_t)-1) {
|
||||
fclose(in);
|
||||
WFPRINTF(stderr, "error getting size of '%s'\n", (const W_CHAR*)file_name);
|
||||
return 0;
|
||||
}
|
||||
fseek(in, 0, SEEK_SET);
|
||||
// we allocate one extra byte for the \0 terminator
|
||||
file_data = (uint8_t*)WebPMalloc(file_size + 1);
|
||||
|
@ -206,8 +206,18 @@ struct my_error_mgr {
|
||||
|
||||
static void my_error_exit(j_common_ptr dinfo) {
|
||||
struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err;
|
||||
// The following code is disabled in fuzzing mode because:
|
||||
// - the logs can be flooded due to invalid JPEG files
|
||||
// - msg_code is wrongfully seen as uninitialized by msan when the libjpeg
|
||||
// dependency is not built with sanitizers enabled
|
||||
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
const int msg_code = myerr->pub.msg_code;
|
||||
fprintf(stderr, "libjpeg error: ");
|
||||
dinfo->err->output_message(dinfo);
|
||||
if (msg_code == JERR_INPUT_EOF || msg_code == JERR_FILE_READ) {
|
||||
fprintf(stderr, "`jpegtran -copy all` MAY be able to process this file.\n");
|
||||
}
|
||||
#endif
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||
volatile png_infop end_info = NULL;
|
||||
PNGReadContext context = { NULL, 0, 0 };
|
||||
int color_type, bit_depth, interlaced;
|
||||
int has_alpha;
|
||||
int num_channels;
|
||||
int num_passes;
|
||||
int p;
|
||||
volatile int ok = 0;
|
||||
@ -293,9 +293,6 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||
}
|
||||
if (png_get_valid(png, info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(png);
|
||||
has_alpha = 1;
|
||||
} else {
|
||||
has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
|
||||
}
|
||||
|
||||
// Apply gamma correction if needed.
|
||||
@ -310,13 +307,16 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||
|
||||
if (!keep_alpha) {
|
||||
png_set_strip_alpha(png);
|
||||
has_alpha = 0;
|
||||
}
|
||||
|
||||
num_passes = png_set_interlace_handling(png);
|
||||
png_read_update_info(png, info);
|
||||
|
||||
stride = (int64_t)(has_alpha ? 4 : 3) * width * sizeof(*rgb);
|
||||
num_channels = png_get_channels(png, info);
|
||||
if (num_channels != 3 && num_channels != 4) {
|
||||
goto Error;
|
||||
}
|
||||
stride = (int64_t)num_channels * width * sizeof(*rgb);
|
||||
if (stride != (int)stride ||
|
||||
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
|
||||
goto Error;
|
||||
@ -341,8 +341,8 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
||||
|
||||
pic->width = (int)width;
|
||||
pic->height = (int)height;
|
||||
ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, (int)stride)
|
||||
: WebPPictureImportRGB(pic, rgb, (int)stride);
|
||||
ok = (num_channels == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride)
|
||||
: WebPPictureImportRGB(pic, rgb, (int)stride);
|
||||
|
||||
if (!ok) {
|
||||
goto Error;
|
||||
|
@ -20,6 +20,10 @@
|
||||
#include "webp/encode.h"
|
||||
#include "./imageio_util.h"
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
WIDTH_FLAG = 1 << 0,
|
||||
HEIGHT_FLAG = 1 << 1,
|
||||
@ -111,8 +115,9 @@ static size_t ReadPAMFields(PNMInfo* const info, size_t off) {
|
||||
break;
|
||||
} else {
|
||||
static const char kEllipsis[] = " ...";
|
||||
const size_t kLen = strlen(kEllipsis) + 1; // +1 = trailing \0
|
||||
int i;
|
||||
if (out_size > 20) sprintf(out + 20 - strlen(kEllipsis), kEllipsis);
|
||||
if (out_size > 20) snprintf(out + 20 - kLen, kLen, kEllipsis);
|
||||
for (i = 0; i < (int)strlen(out); ++i) {
|
||||
// isprint() might trigger a "char-subscripts" warning if given a char.
|
||||
if (!isprint((int)out[i])) out[i] = ' ';
|
||||
|
@ -188,7 +188,9 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
||||
fprintf(stderr, "Error! Cannot retrieve TIFF samples-per-pixel info.\n");
|
||||
goto End;
|
||||
}
|
||||
if (samples_per_px < 3 || samples_per_px > 4) goto End; // not supported
|
||||
if (!(samples_per_px == 1 || samples_per_px == 3 || samples_per_px == 4)) {
|
||||
goto End; // not supported
|
||||
}
|
||||
|
||||
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width) &&
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height))) {
|
||||
@ -212,7 +214,7 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
||||
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height)) {
|
||||
if ((tile_width > 32 && tile_width / 2 > image_width) ||
|
||||
(tile_height > 32 && tile_height / 2 > image_height) ||
|
||||
ImgIoUtilCheckSizeArgumentsOverflow(
|
||||
!ImgIoUtilCheckSizeArgumentsOverflow(
|
||||
(uint64_t)tile_width * sizeof(*raster), tile_height)) {
|
||||
fprintf(stderr, "Error! TIFF tile dimension (%d x %d) is too large.\n",
|
||||
tile_width, tile_height);
|
||||
|
@ -85,10 +85,10 @@ scan_build make -j4
|
||||
|
||||
index="$(find "${OUTPUT_DIR}" -name index.html)"
|
||||
if [[ -f "${index}" ]]; then
|
||||
mv "$(dirname "${index}")/"* .
|
||||
mv "$(dirname "${index}")/"* "${OUTPUT_DIR}"
|
||||
else
|
||||
# make a empty report to wipe out any old bug reports.
|
||||
cat << EOT > index.html
|
||||
cat << EOT > "${OUTPUT_DIR}/index.html"
|
||||
<html>
|
||||
<body>
|
||||
No bugs reported.
|
||||
|
24
iosbuild.sh
24
iosbuild.sh
@ -41,6 +41,7 @@ readonly TARGETDIR="${TOPDIR}/WebP.framework"
|
||||
readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.framework"
|
||||
readonly MUXTARGETDIR="${TOPDIR}/WebPMux.framework"
|
||||
readonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.framework"
|
||||
readonly SHARPYUVTARGETDIR="${TOPDIR}/SharpYuv.framework"
|
||||
readonly DEVELOPER=$(xcode-select --print-path)
|
||||
readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
|
||||
readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
|
||||
@ -63,7 +64,8 @@ echo "Xcode Version: ${XCODE}"
|
||||
echo "iOS SDK Version: ${SDK}"
|
||||
|
||||
if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \
|
||||
|| -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" ]]; then
|
||||
|| -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" \
|
||||
|| -e "${SHARPYUVTARGETDIR}" ]]; then
|
||||
cat << EOF
|
||||
WARNING: The following directories will be deleted:
|
||||
WARNING: ${BUILDDIR}
|
||||
@ -71,14 +73,16 @@ WARNING: ${TARGETDIR}
|
||||
WARNING: ${DECTARGETDIR}
|
||||
WARNING: ${MUXTARGETDIR}
|
||||
WARNING: ${DEMUXTARGETDIR}
|
||||
WARNING: ${SHARPYUVTARGETDIR}
|
||||
WARNING: The build will continue in 5 seconds...
|
||||
EOF
|
||||
sleep 5
|
||||
fi
|
||||
rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \
|
||||
${MUXTARGETDIR} ${DEMUXTARGETDIR}
|
||||
${MUXTARGETDIR} ${DEMUXTARGETDIR} ${SHARPYUVTARGETDIR}
|
||||
mkdir -p ${BUILDDIR} ${TARGETDIR}/Headers/ ${DECTARGETDIR}/Headers/ \
|
||||
${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/
|
||||
${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/ \
|
||||
${SHARPYUVTARGETDIR}/Headers/
|
||||
|
||||
if [[ ! -e ${SRCDIR}/configure ]]; then
|
||||
if ! (cd ${SRCDIR} && sh autogen.sh); then
|
||||
@ -133,18 +137,17 @@ for PLATFORM in ${PLATFORMS}; do
|
||||
CFLAGS="${CFLAGS}"
|
||||
set +x
|
||||
|
||||
# run make only in the src/ directory to create libwebp.a/libwebpdecoder.a
|
||||
cd src/
|
||||
make V=0
|
||||
make install
|
||||
# Build only the libraries, skip the examples.
|
||||
make V=0 -C sharpyuv install
|
||||
make V=0 -C src install
|
||||
|
||||
LIBLIST+=" ${ROOTDIR}/lib/libwebp.a"
|
||||
DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a"
|
||||
MUXLIBLIST+=" ${ROOTDIR}/lib/libwebpmux.a"
|
||||
DEMUXLIBLIST+=" ${ROOTDIR}/lib/libwebpdemux.a"
|
||||
SHARPYUVLIBLIST+=" ${ROOTDIR}/lib/libsharpyuv.a"
|
||||
|
||||
make clean
|
||||
cd ..
|
||||
|
||||
export PATH=${OLDPATH}
|
||||
done
|
||||
@ -167,4 +170,9 @@ cp -a ${SRCDIR}/src/webp/{decode,types,mux_types,demux}.h \
|
||||
${DEMUXTARGETDIR}/Headers/
|
||||
${LIPO} -create ${DEMUXLIBLIST} -output ${DEMUXTARGETDIR}/WebPDemux
|
||||
|
||||
echo "SHARPYUVLIBLIST = ${SHARPYUVLIBLIST}"
|
||||
cp -a ${SRCDIR}/sharpyuv/{sharpyuv,sharpyuv_csp}.h \
|
||||
${SHARPYUVTARGETDIR}/Headers/
|
||||
${LIPO} -create ${SHARPYUVLIBLIST} -output ${SHARPYUVTARGETDIR}/SharpYuv
|
||||
|
||||
echo "SUCCESS"
|
||||
|
@ -3,7 +3,8 @@
|
||||
# It will not install the libraries system-wide, but just create the 'cwebp'
|
||||
# and 'dwebp' tools in the examples/ directory, along with the static
|
||||
# libraries 'src/libwebp.a', 'src/libwebpdecoder.a', 'src/mux/libwebpmux.a',
|
||||
# 'src/demux/libwebpdemux.a' and 'extras/libwebpextras.a'.
|
||||
# 'src/demux/libwebpdemux.a', 'extras/libwebpextras.a' and
|
||||
# 'sharpyuv/libsharpyuv.a'.
|
||||
#
|
||||
# To build the library and examples, use:
|
||||
# make -f makefile.unix
|
||||
@ -36,13 +37,13 @@ else
|
||||
endif
|
||||
|
||||
# SDL flags: use sdl-config if it exists
|
||||
SDL_CONFIG = $(shell sdl-config --version 2> /dev/null)
|
||||
SDL_CONFIG = $(shell sdl2-config --version 2> /dev/null)
|
||||
ifneq ($(SDL_CONFIG),)
|
||||
SDL_LIBS = $(shell sdl-config --libs)
|
||||
SDL_FLAGS = $(shell sdl-config --cflags)
|
||||
SDL_LIBS = $(shell sdl2-config --libs)
|
||||
SDL_FLAGS = $(shell sdl2-config --cflags)
|
||||
else
|
||||
# use best-guess
|
||||
SDL_LIBS = -lSDL
|
||||
SDL_LIBS = -lSDL2
|
||||
SDL_FLAGS =
|
||||
endif
|
||||
|
||||
@ -125,6 +126,15 @@ endif
|
||||
ANIM_UTIL_OBJS = \
|
||||
examples/anim_util.o \
|
||||
|
||||
SHARPYUV_OBJS = \
|
||||
sharpyuv/sharpyuv.o \
|
||||
sharpyuv/sharpyuv_cpu.o \
|
||||
sharpyuv/sharpyuv_csp.o \
|
||||
sharpyuv/sharpyuv_dsp.o \
|
||||
sharpyuv/sharpyuv_gamma.o \
|
||||
sharpyuv/sharpyuv_neon.o \
|
||||
sharpyuv/sharpyuv_sse2.o \
|
||||
|
||||
DEC_OBJS = \
|
||||
src/dec/alpha_dec.o \
|
||||
src/dec/buffer_dec.o \
|
||||
@ -266,6 +276,7 @@ UTILS_DEC_OBJS = \
|
||||
src/utils/color_cache_utils.o \
|
||||
src/utils/filters_utils.o \
|
||||
src/utils/huffman_utils.o \
|
||||
src/utils/palette.o \
|
||||
src/utils/quant_levels_dec_utils.o \
|
||||
src/utils/random_utils.o \
|
||||
src/utils/rescaler_utils.o \
|
||||
@ -280,13 +291,15 @@ UTILS_ENC_OBJS = \
|
||||
EXTRA_OBJS = \
|
||||
extras/extras.o \
|
||||
extras/quality_estimate.o \
|
||||
extras/sharpyuv_risk_table.o \
|
||||
|
||||
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
|
||||
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
|
||||
$(UTILS_ENC_OBJS)
|
||||
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) \
|
||||
$(DSP_ENC_OBJS) $(UTILS_ENC_OBJS)
|
||||
LIBWEBPMUX_OBJS = $(MUX_OBJS)
|
||||
LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS)
|
||||
LIBWEBPEXTRA_OBJS = $(EXTRA_OBJS)
|
||||
LIBSHARPYUV_OBJS = $(SHARPYUV_OBJS)
|
||||
|
||||
HDRS_INSTALLED = \
|
||||
src/webp/decode.h \
|
||||
@ -296,6 +309,11 @@ HDRS_INSTALLED = \
|
||||
src/webp/mux_types.h \
|
||||
src/webp/types.h \
|
||||
|
||||
SHARPYUV_HDRS_INSTALLED = \
|
||||
sharpyuv/sharpyuv.h \
|
||||
sharpyuv/sharpyuv_cpu.h \
|
||||
sharpyuv/sharpyuv_csp.h \
|
||||
|
||||
HDRS = \
|
||||
src/dec/alphai_dec.h \
|
||||
src/dec/common_dec.h \
|
||||
@ -304,6 +322,7 @@ HDRS = \
|
||||
src/dec/vp8li_dec.h \
|
||||
src/dec/webpi_dec.h \
|
||||
src/dsp/common_sse2.h \
|
||||
src/dsp/cpu.h \
|
||||
src/dsp/dsp.h \
|
||||
src/dsp/lossless.h \
|
||||
src/dsp/lossless_common.h \
|
||||
@ -326,6 +345,7 @@ HDRS = \
|
||||
src/utils/filters_utils.h \
|
||||
src/utils/huffman_utils.h \
|
||||
src/utils/huffman_encode_utils.h \
|
||||
src/utils/palette.h \
|
||||
src/utils/quant_levels_utils.h \
|
||||
src/utils/quant_levels_dec_utils.h \
|
||||
src/utils/random_utils.h \
|
||||
@ -334,6 +354,7 @@ HDRS = \
|
||||
src/utils/utils.h \
|
||||
src/webp/format_constants.h \
|
||||
$(HDRS_INSTALLED) \
|
||||
$(SHARPYUV_HDRS_INSTALLED) \
|
||||
|
||||
OUT_LIBS = examples/libexample_util.a
|
||||
OUT_LIBS += imageio/libimageio_util.a
|
||||
@ -341,6 +362,7 @@ OUT_LIBS += imageio/libimagedec.a
|
||||
OUT_LIBS += imageio/libimageenc.a
|
||||
OUT_LIBS += src/libwebpdecoder.a
|
||||
OUT_LIBS += src/libwebp.a
|
||||
OUT_LIBS += sharpyuv/libsharpyuv.a
|
||||
EXTRA_LIB = extras/libwebpextras.a
|
||||
OUT_EXAMPLES = examples/cwebp examples/dwebp
|
||||
EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux \
|
||||
@ -386,6 +408,7 @@ src/libwebpdecoder.a: $(LIBWEBPDECODER_OBJS)
|
||||
src/libwebp.a: $(LIBWEBP_OBJS)
|
||||
src/mux/libwebpmux.a: $(LIBWEBPMUX_OBJS)
|
||||
src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS)
|
||||
sharpyuv/libsharpyuv.a: $(LIBSHARPYUV_OBJS)
|
||||
|
||||
%.a:
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
@ -403,6 +426,7 @@ examples/webpinfo: examples/webpinfo.o
|
||||
examples/anim_diff: examples/libanim_util.a examples/libgifdec.a
|
||||
examples/anim_diff: src/demux/libwebpdemux.a examples/libexample_util.a
|
||||
examples/anim_diff: imageio/libimageio_util.a src/libwebp.a
|
||||
examples/anim_diff: sharpyuv/libsharpyuv.a
|
||||
examples/anim_diff: override EXTRA_LIBS += $(GIF_LIBS)
|
||||
examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF
|
||||
examples/anim_dump: examples/libanim_util.a examples/libgifdec.a
|
||||
@ -411,12 +435,14 @@ examples/anim_dump: examples/libexample_util.a
|
||||
examples/anim_dump: imageio/libimageio_util.a
|
||||
examples/anim_dump: imageio/libimageenc.a
|
||||
examples/anim_dump: src/libwebp.a
|
||||
examples/anim_dump: sharpyuv/libsharpyuv.a
|
||||
examples/anim_dump: override EXTRA_LIBS += $(GIF_LIBS) $(DWEBP_LIBS)
|
||||
examples/cwebp: examples/libexample_util.a
|
||||
examples/cwebp: imageio/libimagedec.a
|
||||
examples/cwebp: src/demux/libwebpdemux.a
|
||||
examples/cwebp: imageio/libimageio_util.a
|
||||
examples/cwebp: src/libwebp.a
|
||||
examples/cwebp: sharpyuv/libsharpyuv.a
|
||||
examples/cwebp: override EXTRA_LIBS += $(CWEBP_LIBS)
|
||||
examples/dwebp: examples/libexample_util.a
|
||||
examples/dwebp: imageio/libimagedec.a
|
||||
@ -424,13 +450,16 @@ examples/dwebp: src/demux/libwebpdemux.a
|
||||
examples/dwebp: imageio/libimageenc.a
|
||||
examples/dwebp: imageio/libimageio_util.a
|
||||
examples/dwebp: src/libwebp.a
|
||||
examples/dwebp: sharpyuv/libsharpyuv.a
|
||||
examples/dwebp: override EXTRA_LIBS += $(DWEBP_LIBS)
|
||||
examples/gif2webp: examples/libexample_util.a imageio/libimageio_util.a
|
||||
examples/gif2webp: examples/libgifdec.a src/mux/libwebpmux.a src/libwebp.a
|
||||
examples/gif2webp: sharpyuv/libsharpyuv.a
|
||||
examples/gif2webp: override EXTRA_LIBS += $(GIF_LIBS)
|
||||
examples/gif2webp: EXTRA_FLAGS += -DWEBP_HAVE_GIF
|
||||
examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a
|
||||
examples/vwebp: imageio/libimageio_util.a src/libwebp.a
|
||||
examples/vwebp: sharpyuv/libsharpyuv.a
|
||||
examples/vwebp: override EXTRA_LIBS += $(GL_LIBS)
|
||||
examples/vwebp: EXTRA_FLAGS += -DWEBP_HAVE_GL
|
||||
examples/webpmux: examples/libexample_util.a imageio/libimageio_util.a
|
||||
@ -438,7 +467,9 @@ examples/webpmux: src/mux/libwebpmux.a src/libwebpdecoder.a
|
||||
examples/img2webp: examples/libexample_util.a imageio/libimageio_util.a
|
||||
examples/img2webp: imageio/libimagedec.a
|
||||
examples/img2webp: src/demux/libwebpdemux.a
|
||||
examples/img2webp: src/mux/libwebpmux.a src/libwebp.a
|
||||
examples/img2webp: src/mux/libwebpmux.a
|
||||
examples/img2webp: src/libwebp.a
|
||||
examples/img2webp: sharpyuv/libsharpyuv.a
|
||||
examples/img2webp: override EXTRA_LIBS += $(CWEBP_LIBS)
|
||||
examples/webpinfo: examples/libexample_util.a imageio/libimageio_util.a
|
||||
examples/webpinfo: src/libwebpdecoder.a
|
||||
@ -448,16 +479,19 @@ extras/get_disto: imageio/libimagedec.a
|
||||
extras/get_disto: src/demux/libwebpdemux.a
|
||||
extras/get_disto: imageio/libimageio_util.a
|
||||
extras/get_disto: src/libwebp.a
|
||||
extras/get_disto: sharpyuv/libsharpyuv.a
|
||||
extras/get_disto: override EXTRA_LIBS += $(CWEBP_LIBS)
|
||||
|
||||
extras/webp_quality: extras/webp_quality.o
|
||||
extras/webp_quality: imageio/libimageio_util.a
|
||||
extras/webp_quality: $(EXTRA_LIB) src/libwebp.a
|
||||
extras/webp_quality: sharpyuv/libsharpyuv.a
|
||||
|
||||
extras/vwebp_sdl: extras/vwebp_sdl.o
|
||||
extras/vwebp_sdl: extras/webp_to_sdl.o
|
||||
extras/vwebp_sdl: imageio/libimageio_util.a
|
||||
extras/vwebp_sdl: src/libwebp.a
|
||||
extras/vwebp_sdl: sharpyuv/libsharpyuv.a
|
||||
extras/vwebp_sdl: EXTRA_FLAGS += -DWEBP_HAVE_SDL $(SDL_FLAGS)
|
||||
extras/vwebp_sdl: override EXTRA_LIBS += $(SDL_LIBS)
|
||||
|
||||
@ -468,12 +502,15 @@ dist: DESTDIR := dist
|
||||
dist: OUT_EXAMPLES += $(EXTRA_EXAMPLES)
|
||||
dist: all
|
||||
$(INSTALL) -m755 -d $(DESTDIR)/include/webp \
|
||||
$(DESTDIR)/bin $(DESTDIR)/doc $(DESTDIR)/lib
|
||||
$(DESTDIR)/include/webp/sharpyuv \
|
||||
$(DESTDIR)/bin $(DESTDIR)/doc $(DESTDIR)/lib
|
||||
$(INSTALL) -m755 -s $(OUT_EXAMPLES) $(DESTDIR)/bin
|
||||
$(INSTALL) -m644 $(HDRS_INSTALLED) $(DESTDIR)/include/webp
|
||||
$(INSTALL) -m644 $(SHARPYUV_HDRS_INSTALLED) $(DESTDIR)/include/webp/sharpyuv
|
||||
$(INSTALL) -m644 src/libwebp.a $(DESTDIR)/lib
|
||||
$(INSTALL) -m644 src/demux/libwebpdemux.a $(DESTDIR)/lib
|
||||
$(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib
|
||||
$(INSTALL) -m644 sharpyuv/libsharpyuv.a $(DESTDIR)/lib
|
||||
umask 022; \
|
||||
for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1 \
|
||||
man/img2webp.1 man/webpinfo.1; do \
|
||||
@ -489,6 +526,7 @@ clean:
|
||||
examples/*.o examples/*~ \
|
||||
extras/*.o extras/*~ \
|
||||
imageio/*.o imageio/*~ \
|
||||
sharpyuv/*.o sharpyuv/*~ \
|
||||
src/dec/*.o src/dec/*~ \
|
||||
src/demux/*.o src/demux/*~ \
|
||||
src/dsp/*.o src/dsp/*~ \
|
||||
|
47
man/cwebp.1
47
man/cwebp.1
@ -1,5 +1,5 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH CWEBP 1 "November 17, 2021"
|
||||
.TH CWEBP 1 "September 17, 2024"
|
||||
.SH NAME
|
||||
cwebp \- compress an image file to a WebP file
|
||||
.SH SYNOPSIS
|
||||
@ -90,15 +90,17 @@ additional encoding possibilities and decide on the quality gain.
|
||||
Lower value can result in faster processing time at the expense of
|
||||
larger file size and lower compression quality.
|
||||
.TP
|
||||
.BI \-resize " width height
|
||||
Resize the source to a rectangle with size \fBwidth\fP x \fBheight\fP.
|
||||
If either (but not both) of the \fBwidth\fP or \fBheight\fP parameters is 0,
|
||||
the value will be calculated preserving the aspect\-ratio.
|
||||
.TP
|
||||
.BI \-crop " x_position y_position width height
|
||||
Crop the source to a rectangle with top\-left corner at coordinates
|
||||
(\fBx_position\fP, \fBy_position\fP) and size \fBwidth\fP x \fBheight\fP.
|
||||
This cropping area must be fully contained within the source rectangle.
|
||||
Note: the cropping is applied \fIbefore\fP any scaling.
|
||||
.TP
|
||||
.BI \-resize " width height
|
||||
Resize the source to a rectangle with size \fBwidth\fP x \fBheight\fP.
|
||||
If either (but not both) of the \fBwidth\fP or \fBheight\fP parameters is 0,
|
||||
the value will be calculated preserving the aspect\-ratio. Note: scaling
|
||||
is applied \fIafter\fP cropping.
|
||||
.TP
|
||||
.B \-mt
|
||||
Use multi\-threading for encoding, if possible.
|
||||
@ -133,7 +135,9 @@ are used, \fB\-size\fP value will prevail.
|
||||
Set a maximum number of passes to use during the dichotomy used by
|
||||
options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10, default is 1.
|
||||
If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't
|
||||
specified, a default value of '6' passes will be used.
|
||||
specified, a default value of '6' passes will be used. If \fB\-pass\fP is
|
||||
specified, but neither \fB-size\fP nor \fB-psnr\fP are, a target PSNR of 40dB
|
||||
will be used.
|
||||
.TP
|
||||
.BI \-qrange " int int
|
||||
Specifies the permissible interval for the quality factor. This is particularly
|
||||
@ -176,8 +180,8 @@ Disable strong filtering (if filtering is being used thanks to the
|
||||
\fB\-f\fP option) and use simple filtering instead.
|
||||
.TP
|
||||
.B \-sharp_yuv
|
||||
Use more accurate and sharper RGB->YUV conversion if needed. Note that this
|
||||
process is slower than the default 'fast' RGB->YUV conversion.
|
||||
Use more accurate and sharper RGB->YUV conversion. Note that this process is
|
||||
slower than the default 'fast' RGB->YUV conversion.
|
||||
.TP
|
||||
.BI \-sns " int
|
||||
Specify the amplitude of the spatial noise shaping. Spatial noise shaping
|
||||
@ -200,7 +204,8 @@ In the VP8 format, the so\-called control partition has a limit of 512k and
|
||||
is used to store the following information: whether the macroblock is skipped,
|
||||
which segment it belongs to, whether it is coded as intra 4x4 or intra 16x16
|
||||
mode, and finally the prediction modes to use for each of the sub\-blocks.
|
||||
For a very large image, 512k only leaves room to few bits per 16x16 macroblock.
|
||||
For a very large image, 512k only leaves room for a few bits per 16x16
|
||||
macroblock.
|
||||
The absolute minimum is 4 bits per macroblock. Skip, segment, and mode
|
||||
information can use up almost all these 4 bits (although the case is unlikely),
|
||||
which is problematic for very large images. The partition_limit factor controls
|
||||
@ -209,7 +214,8 @@ useful in case the 512k limit is reached and the following message is displayed:
|
||||
\fIError code: 6 (PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k)\fP.
|
||||
If using \fB\-partition_limit\fP is not enough to meet the 512k constraint, one
|
||||
should use less segments in order to save more header bits per macroblock.
|
||||
See the \fB\-segments\fP option.
|
||||
See the \fB\-segments\fP option. Note the \fB-m\fP and \fB-q\fP options also
|
||||
influence the encoder's decisions and ability to hit this limit.
|
||||
|
||||
.SS LOGGING OPTIONS
|
||||
These options control the level of output:
|
||||
@ -293,12 +299,12 @@ Note: each input format may not support all combinations.
|
||||
.B \-noasm
|
||||
Disable all assembly optimizations.
|
||||
|
||||
.SH BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://bugs.chromium.org/p/webp
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
.SH EXIT STATUS
|
||||
If there were no problems during execution, \fBcwebp\fP exits with the value of
|
||||
the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
|
||||
.PP
|
||||
If an error occurs, \fBcwebp\fP exits with the value of the C constant
|
||||
\fBEXIT_FAILURE\fP. This is usually one.
|
||||
|
||||
.SH EXAMPLES
|
||||
cwebp \-q 50 -lossless picture.png \-o picture_lossless.webp
|
||||
@ -318,6 +324,13 @@ https://chromium.googlesource.com/webm/libwebp
|
||||
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
|
||||
for the Debian project (and may be used by others).
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://issues.webmproject.org
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR dwebp (1),
|
||||
.BR gif2webp (1)
|
||||
|
21
man/dwebp.1
21
man/dwebp.1
@ -1,5 +1,5 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH DWEBP 1 "November 17, 2021"
|
||||
.TH DWEBP 1 "July 18, 2024"
|
||||
.SH NAME
|
||||
dwebp \- decompress a WebP file to an image file
|
||||
.SH SYNOPSIS
|
||||
@ -108,12 +108,12 @@ Print extra information (decoding time in particular).
|
||||
.B \-noasm
|
||||
Disable all assembly optimizations.
|
||||
|
||||
.SH BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://bugs.chromium.org/p/webp
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
.SH EXIT STATUS
|
||||
If there were no problems during execution, \fBdwebp\fP exits with the value of
|
||||
the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
|
||||
.PP
|
||||
If an error occurs, \fBdwebp\fP exits with the value of the C constant
|
||||
\fBEXIT_FAILURE\fP. This is usually one.
|
||||
|
||||
.SH EXAMPLES
|
||||
dwebp picture.webp \-o output.png
|
||||
@ -133,6 +133,13 @@ https://chromium.googlesource.com/webm/libwebp
|
||||
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
|
||||
for the Debian project (and may be used by others).
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://issues.webmproject.org
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR cwebp (1),
|
||||
.BR gif2webp (1),
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH GIF2WEBP 1 "November 17, 2021"
|
||||
.TH GIF2WEBP 1 "July 18, 2024"
|
||||
.SH NAME
|
||||
gif2webp \- Convert a GIF image to WebP
|
||||
.SH SYNOPSIS
|
||||
@ -126,12 +126,12 @@ Print extra information.
|
||||
.B \-quiet
|
||||
Do not print anything.
|
||||
|
||||
.SH BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://bugs.chromium.org/p/webp
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
.SH EXIT STATUS
|
||||
If there were no problems during execution, \fBgif2webp\fP exits with the value
|
||||
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
|
||||
.PP
|
||||
If an error occurs, \fBgif2webp\fP exits with the value of the C constant
|
||||
\fBEXIT_FAILURE\fP. This is usually one.
|
||||
|
||||
.SH EXAMPLES
|
||||
gif2webp picture.gif \-o picture.webp
|
||||
@ -155,6 +155,13 @@ https://chromium.googlesource.com/webm/libwebp
|
||||
This manual page was written by Urvang Joshi <urvang@google.com>, for the
|
||||
Debian project (and may be used by others).
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://issues.webmproject.org
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR cwebp (1),
|
||||
.BR dwebp (1),
|
||||
|
@ -1,10 +1,10 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH IMG2WEBP 1 "January 5, 2022"
|
||||
.TH IMG2WEBP 1 "September 17, 2024"
|
||||
.SH NAME
|
||||
img2webp \- create animated WebP file from a sequence of input images.
|
||||
.SH SYNOPSIS
|
||||
.B img2webp
|
||||
[file_options] [[frame_options] frame_file]...
|
||||
[file_options] [[frame_options] frame_file]... [\-o webp_file]
|
||||
.br
|
||||
.B img2webp argument_file_name
|
||||
.br
|
||||
@ -44,6 +44,18 @@ Mixed compression mode: optimize compression of the image by picking either
|
||||
lossy or lossless compression for each frame heuristically. This global
|
||||
option disables the local option \fB-lossy\fP and \fB-lossless\fP .
|
||||
.TP
|
||||
.BI \-near_lossless " int
|
||||
Specify the level of near\-lossless image preprocessing. This option adjusts
|
||||
pixel values to help compressibility, but has minimal impact on the visual
|
||||
quality. It triggers lossless compression mode automatically. The range is 0
|
||||
(maximum preprocessing) to 100 (no preprocessing, the default). The typical
|
||||
value is around 60. Note that lossy with \fB\-q 100\fP can at times yield
|
||||
better results.
|
||||
.TP
|
||||
.B \-sharp_yuv
|
||||
Use more accurate and sharper RGB->YUV conversion. Note that this process is
|
||||
slower than the default 'fast' RGB->YUV conversion.
|
||||
.TP
|
||||
.BI \-loop " int
|
||||
Specifies the number of times the animation should loop. Using '0'
|
||||
means 'loop indefinitely'.
|
||||
@ -76,18 +88,23 @@ Specify the compression factor between 0 and 100. The default is 75.
|
||||
Specify the compression method to use. This parameter controls the
|
||||
trade off between encoding speed and the compressed file size and quality.
|
||||
Possible values range from 0 to 6. Default value is 4.
|
||||
.TP
|
||||
.B \-exact, \-noexact
|
||||
Preserve or alter RGB values in transparent area. The default is
|
||||
\fB-noexact\fP, to help compressibility. Note \fB\-noexact\fP may cause
|
||||
artifacts in frames compressed with \fB\-lossy\fP.
|
||||
|
||||
.SH EXIT STATUS
|
||||
If there were no problems during execution, \fBimg2webp\fP exits with the value
|
||||
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
|
||||
.PP
|
||||
If an error occurs, \fBimg2webp\fP exits with the value of the C constant
|
||||
\fBEXIT_FAILURE\fP. This is usually one.
|
||||
|
||||
.SH EXAMPLE
|
||||
img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp
|
||||
.br
|
||||
|
||||
.SH BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://bugs.chromium.org/p/webp
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
|
||||
.SH AUTHORS
|
||||
\fBimg2webp\fP is a part of libwebp and was written by the WebP team.
|
||||
.br
|
||||
@ -97,6 +114,13 @@ https://chromium.googlesource.com/webm/libwebp
|
||||
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
|
||||
for the Debian project (and may be used by others).
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://issues.webmproject.org
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR webpmux (1),
|
||||
.BR gif2webp (1)
|
||||
|
21
man/vwebp.1
21
man/vwebp.1
@ -1,5 +1,5 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH VWEBP 1 "November 17, 2021"
|
||||
.TH VWEBP 1 "July 18, 2024"
|
||||
.SH NAME
|
||||
vwebp \- decompress a WebP file and display it in a window
|
||||
.SH SYNOPSIS
|
||||
@ -72,12 +72,12 @@ Disable blending and disposal process, for debugging purposes.
|
||||
.B 'q' / 'Q' / ESC
|
||||
Quit.
|
||||
|
||||
.SH BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://bugs.chromium.org/p/webp
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
.SH EXIT STATUS
|
||||
If there were no problems during execution, \fBvwebp\fP exits with the value of
|
||||
the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
|
||||
.PP
|
||||
If an error occurs, \fBvwebp\fP exits with the value of the C constant
|
||||
\fBEXIT_FAILURE\fP. This is usually one.
|
||||
|
||||
.SH EXAMPLES
|
||||
vwebp picture.webp
|
||||
@ -94,6 +94,13 @@ https://chromium.googlesource.com/webm/libwebp
|
||||
.PP
|
||||
This manual page was written for the Debian project (and may be used by others).
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://issues.webmproject.org
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR dwebp (1)
|
||||
.br
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH WEBPINFO 1 "November 17, 2021"
|
||||
.TH WEBPINFO 1 "July 18, 2024"
|
||||
.SH NAME
|
||||
webpinfo \- print out the chunk level structure of WebP files
|
||||
along with basic integrity checks.
|
||||
@ -47,12 +47,12 @@ Detailed usage instructions.
|
||||
Input files in WebP format. Input files must come last, following
|
||||
options (if any). There can be multiple input files.
|
||||
|
||||
.SH BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://bugs.chromium.org/p/webp
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
.SH EXIT STATUS
|
||||
If there were no problems during execution, \fBwebpinfo\fP exits with the value
|
||||
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
|
||||
.PP
|
||||
If an error occurs, \fBwebpinfo\fP exits with the value of the C constant
|
||||
\fBEXIT_FAILURE\fP. This is usually one.
|
||||
|
||||
.SH EXAMPLES
|
||||
.br
|
||||
@ -73,6 +73,13 @@ https://chromium.googlesource.com/webm/libwebp
|
||||
This manual page was written by Hui Su <huisu@google.com>,
|
||||
for the Debian project (and may be used by others).
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://issues.webmproject.org
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR webpmux (1)
|
||||
.br
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH WEBPMUX 1 "November 17, 2021"
|
||||
.TH WEBPMUX 1 "July 18, 2024"
|
||||
.SH NAME
|
||||
webpmux \- create animated WebP files from non\-animated WebP images, extract
|
||||
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
|
||||
@ -186,12 +186,12 @@ Output file in WebP format.
|
||||
.TP
|
||||
The nature of EXIF, XMP and ICC data is not checked and is assumed to be valid.
|
||||
|
||||
.SH BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://bugs.chromium.org/p/webp
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
.SH EXIT STATUS
|
||||
If there were no problems during execution, \fBwebpmux\fP exits with the value
|
||||
of the C constant \fBEXIT_SUCCESS\fP. This is usually zero.
|
||||
.PP
|
||||
If an error occurs, \fBwebpmux\fP exits with the value of the C constant
|
||||
\fBEXIT_FAILURE\fP. This is usually one.
|
||||
|
||||
.SH EXAMPLES
|
||||
.P
|
||||
@ -262,6 +262,13 @@ https://chromium.googlesource.com/webm/libwebp
|
||||
This manual page was written by Vikas Arora <vikaas.arora@gmail.com>,
|
||||
for the Debian project (and may be used by others).
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Please report all bugs to the issue tracker:
|
||||
https://issues.webmproject.org
|
||||
.br
|
||||
Patches welcome! See this page to get started:
|
||||
https://www.webmproject.org/code/contribute/submitting\-patches/
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR cwebp (1),
|
||||
.BR dwebp (1),
|
||||
|
41
sharpyuv/Makefile.am
Normal file
41
sharpyuv/Makefile.am
Normal file
@ -0,0 +1,41 @@
|
||||
AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir)
|
||||
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
|
||||
|
||||
lib_LTLIBRARIES = libsharpyuv.la
|
||||
|
||||
noinst_LTLIBRARIES =
|
||||
noinst_LTLIBRARIES += libsharpyuv_sse2.la
|
||||
noinst_LTLIBRARIES += libsharpyuv_neon.la
|
||||
|
||||
libsharpyuvinclude_HEADERS =
|
||||
libsharpyuvinclude_HEADERS += sharpyuv.h
|
||||
libsharpyuvinclude_HEADERS += sharpyuv_csp.h
|
||||
noinst_HEADERS =
|
||||
noinst_HEADERS += ../src/dsp/cpu.c
|
||||
noinst_HEADERS += ../src/dsp/cpu.h
|
||||
noinst_HEADERS += ../src/webp/types.h
|
||||
|
||||
libsharpyuv_sse2_la_SOURCES =
|
||||
libsharpyuv_sse2_la_SOURCES += sharpyuv_sse2.c
|
||||
libsharpyuv_sse2_la_CPPFLAGS = $(libsharpyuv_la_CPPFLAGS)
|
||||
libsharpyuv_sse2_la_CFLAGS = $(AM_CFLAGS) $(SSE2_FLAGS)
|
||||
|
||||
libsharpyuv_neon_la_SOURCES =
|
||||
libsharpyuv_neon_la_SOURCES += sharpyuv_neon.c
|
||||
libsharpyuv_neon_la_CPPFLAGS = $(libsharpyuv_la_CPPFLAGS)
|
||||
libsharpyuv_neon_la_CFLAGS = $(AM_CFLAGS) $(NEON_FLAGS)
|
||||
|
||||
libsharpyuv_la_SOURCES =
|
||||
libsharpyuv_la_SOURCES += sharpyuv_cpu.c sharpyuv_cpu.h
|
||||
libsharpyuv_la_SOURCES += sharpyuv_csp.c sharpyuv_csp.h
|
||||
libsharpyuv_la_SOURCES += sharpyuv_dsp.c sharpyuv_dsp.h
|
||||
libsharpyuv_la_SOURCES += sharpyuv_gamma.c sharpyuv_gamma.h
|
||||
libsharpyuv_la_SOURCES += sharpyuv.c sharpyuv.h
|
||||
|
||||
libsharpyuv_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
libsharpyuv_la_LDFLAGS = -no-undefined -version-info 1:0:1 -lm
|
||||
libsharpyuv_la_LIBADD =
|
||||
libsharpyuv_la_LIBADD += libsharpyuv_sse2.la
|
||||
libsharpyuv_la_LIBADD += libsharpyuv_neon.la
|
||||
libsharpyuvincludedir = $(includedir)/webp/sharpyuv
|
||||
pkgconfig_DATA = libsharpyuv.pc
|
11
sharpyuv/libsharpyuv.pc.in
Normal file
11
sharpyuv/libsharpyuv.pc.in
Normal file
@ -0,0 +1,11 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@/webp
|
||||
|
||||
Name: libsharpyuv
|
||||
Description: Library for sharp RGB to YUV conversion
|
||||
Version: @PACKAGE_VERSION@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -l@webp_libname_prefix@sharpyuv
|
||||
Libs.private: -lm @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
|
41
sharpyuv/libsharpyuv.rc
Normal file
41
sharpyuv/libsharpyuv.rc
Normal file
@ -0,0 +1,41 @@
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
#include "winres.h"
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,0,4,0
|
||||
PRODUCTVERSION 0,0,4,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Google, Inc."
|
||||
VALUE "FileDescription", "libsharpyuv DLL"
|
||||
VALUE "FileVersion", "0.4.0"
|
||||
VALUE "InternalName", "libsharpyuv.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2024"
|
||||
VALUE "OriginalFilename", "libsharpyuv.dll"
|
||||
VALUE "ProductName", "SharpYuv Library"
|
||||
VALUE "ProductVersion", "0.4.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
575
sharpyuv/sharpyuv.c
Normal file
575
sharpyuv/sharpyuv.c
Normal file
@ -0,0 +1,575 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Sharp RGB to YUV conversion.
|
||||
//
|
||||
// Author: Skal (pascal.massimino@gmail.com)
|
||||
|
||||
#include "sharpyuv/sharpyuv.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "src/webp/types.h"
|
||||
#include "sharpyuv/sharpyuv_cpu.h"
|
||||
#include "sharpyuv/sharpyuv_dsp.h"
|
||||
#include "sharpyuv/sharpyuv_gamma.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int SharpYuvGetVersion(void) {
|
||||
return SHARPYUV_VERSION;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Sharp RGB->YUV conversion
|
||||
|
||||
static const int kNumIterations = 4;
|
||||
|
||||
#define YUV_FIX 16 // fixed-point precision for RGB->YUV
|
||||
static const int kYuvHalf = 1 << (YUV_FIX - 1);
|
||||
|
||||
// Max bit depth so that intermediate calculations fit in 16 bits.
|
||||
static const int kMaxBitDepth = 14;
|
||||
|
||||
// Returns the precision shift to use based on the input rgb_bit_depth.
|
||||
static int GetPrecisionShift(int rgb_bit_depth) {
|
||||
// Try to add 2 bits of precision if it fits in kMaxBitDepth. Otherwise remove
|
||||
// bits if needed.
|
||||
return ((rgb_bit_depth + 2) <= kMaxBitDepth) ? 2
|
||||
: (kMaxBitDepth - rgb_bit_depth);
|
||||
}
|
||||
|
||||
typedef int16_t fixed_t; // signed type with extra precision for UV
|
||||
typedef uint16_t fixed_y_t; // unsigned type with extra precision for W
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static uint8_t clip_8b(fixed_t v) {
|
||||
return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u;
|
||||
}
|
||||
|
||||
static uint16_t clip(fixed_t v, int max) {
|
||||
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
|
||||
}
|
||||
|
||||
static fixed_y_t clip_bit_depth(int y, int bit_depth) {
|
||||
const int max = (1 << bit_depth) - 1;
|
||||
return (!(y & ~max)) ? (fixed_y_t)y : (y < 0) ? 0 : max;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static int RGBToGray(int64_t r, int64_t g, int64_t b) {
|
||||
const int64_t luma = 13933 * r + 46871 * g + 4732 * b + kYuvHalf;
|
||||
return (int)(luma >> YUV_FIX);
|
||||
}
|
||||
|
||||
static uint32_t ScaleDown(uint16_t a, uint16_t b, uint16_t c, uint16_t d,
|
||||
int rgb_bit_depth,
|
||||
SharpYuvTransferFunctionType transfer_type) {
|
||||
const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
|
||||
const uint32_t A = SharpYuvGammaToLinear(a, bit_depth, transfer_type);
|
||||
const uint32_t B = SharpYuvGammaToLinear(b, bit_depth, transfer_type);
|
||||
const uint32_t C = SharpYuvGammaToLinear(c, bit_depth, transfer_type);
|
||||
const uint32_t D = SharpYuvGammaToLinear(d, bit_depth, transfer_type);
|
||||
return SharpYuvLinearToGamma((A + B + C + D + 2) >> 2, bit_depth,
|
||||
transfer_type);
|
||||
}
|
||||
|
||||
static WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int w,
|
||||
int rgb_bit_depth,
|
||||
SharpYuvTransferFunctionType transfer_type) {
|
||||
const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
|
||||
int i = 0;
|
||||
do {
|
||||
const uint32_t R =
|
||||
SharpYuvGammaToLinear(src[0 * w + i], bit_depth, transfer_type);
|
||||
const uint32_t G =
|
||||
SharpYuvGammaToLinear(src[1 * w + i], bit_depth, transfer_type);
|
||||
const uint32_t B =
|
||||
SharpYuvGammaToLinear(src[2 * w + i], bit_depth, transfer_type);
|
||||
const uint32_t Y = RGBToGray(R, G, B);
|
||||
dst[i] = (fixed_y_t)SharpYuvLinearToGamma(Y, bit_depth, transfer_type);
|
||||
} while (++i < w);
|
||||
}
|
||||
|
||||
static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2,
|
||||
fixed_t* dst, int uv_w, int rgb_bit_depth,
|
||||
SharpYuvTransferFunctionType transfer_type) {
|
||||
int i = 0;
|
||||
do {
|
||||
const int r =
|
||||
ScaleDown(src1[0 * uv_w + 0], src1[0 * uv_w + 1], src2[0 * uv_w + 0],
|
||||
src2[0 * uv_w + 1], rgb_bit_depth, transfer_type);
|
||||
const int g =
|
||||
ScaleDown(src1[2 * uv_w + 0], src1[2 * uv_w + 1], src2[2 * uv_w + 0],
|
||||
src2[2 * uv_w + 1], rgb_bit_depth, transfer_type);
|
||||
const int b =
|
||||
ScaleDown(src1[4 * uv_w + 0], src1[4 * uv_w + 1], src2[4 * uv_w + 0],
|
||||
src2[4 * uv_w + 1], rgb_bit_depth, transfer_type);
|
||||
const int W = RGBToGray(r, g, b);
|
||||
dst[0 * uv_w] = (fixed_t)(r - W);
|
||||
dst[1 * uv_w] = (fixed_t)(g - W);
|
||||
dst[2 * uv_w] = (fixed_t)(b - W);
|
||||
dst += 1;
|
||||
src1 += 2;
|
||||
src2 += 2;
|
||||
} while (++i < uv_w);
|
||||
}
|
||||
|
||||
static void StoreGray(const fixed_y_t* rgb, fixed_y_t* y, int w) {
|
||||
int i = 0;
|
||||
assert(w > 0);
|
||||
do {
|
||||
y[i] = RGBToGray(rgb[0 * w + i], rgb[1 * w + i], rgb[2 * w + i]);
|
||||
} while (++i < w);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static WEBP_INLINE fixed_y_t Filter2(int A, int B, int W0, int bit_depth) {
|
||||
const int v0 = (A * 3 + B + 2) >> 2;
|
||||
return clip_bit_depth(v0 + W0, bit_depth);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static WEBP_INLINE int Shift(int v, int shift) {
|
||||
return (shift >= 0) ? (v << shift) : (v >> -shift);
|
||||
}
|
||||
|
||||
static void ImportOneRow(const uint8_t* const r_ptr,
|
||||
const uint8_t* const g_ptr,
|
||||
const uint8_t* const b_ptr,
|
||||
int rgb_step,
|
||||
int rgb_bit_depth,
|
||||
int pic_width,
|
||||
fixed_y_t* const dst) {
|
||||
// Convert the rgb_step from a number of bytes to a number of uint8_t or
|
||||
// uint16_t values depending the bit depth.
|
||||
const int step = (rgb_bit_depth > 8) ? rgb_step / 2 : rgb_step;
|
||||
int i = 0;
|
||||
const int w = (pic_width + 1) & ~1;
|
||||
do {
|
||||
const int off = i * step;
|
||||
const int shift = GetPrecisionShift(rgb_bit_depth);
|
||||
if (rgb_bit_depth == 8) {
|
||||
dst[i + 0 * w] = Shift(r_ptr[off], shift);
|
||||
dst[i + 1 * w] = Shift(g_ptr[off], shift);
|
||||
dst[i + 2 * w] = Shift(b_ptr[off], shift);
|
||||
} else {
|
||||
dst[i + 0 * w] = Shift(((uint16_t*)r_ptr)[off], shift);
|
||||
dst[i + 1 * w] = Shift(((uint16_t*)g_ptr)[off], shift);
|
||||
dst[i + 2 * w] = Shift(((uint16_t*)b_ptr)[off], shift);
|
||||
}
|
||||
} while (++i < pic_width);
|
||||
if (pic_width & 1) { // replicate rightmost pixel
|
||||
dst[pic_width + 0 * w] = dst[pic_width + 0 * w - 1];
|
||||
dst[pic_width + 1 * w] = dst[pic_width + 1 * w - 1];
|
||||
dst[pic_width + 2 * w] = dst[pic_width + 2 * w - 1];
|
||||
}
|
||||
}
|
||||
|
||||
static void InterpolateTwoRows(const fixed_y_t* const best_y,
|
||||
const fixed_t* prev_uv,
|
||||
const fixed_t* cur_uv,
|
||||
const fixed_t* next_uv,
|
||||
int w,
|
||||
fixed_y_t* out1,
|
||||
fixed_y_t* out2,
|
||||
int rgb_bit_depth) {
|
||||
const int uv_w = w >> 1;
|
||||
const int len = (w - 1) >> 1; // length to filter
|
||||
int k = 3;
|
||||
const int bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
|
||||
while (k-- > 0) { // process each R/G/B segments in turn
|
||||
// special boundary case for i==0
|
||||
out1[0] = Filter2(cur_uv[0], prev_uv[0], best_y[0], bit_depth);
|
||||
out2[0] = Filter2(cur_uv[0], next_uv[0], best_y[w], bit_depth);
|
||||
|
||||
SharpYuvFilterRow(cur_uv, prev_uv, len, best_y + 0 + 1, out1 + 1,
|
||||
bit_depth);
|
||||
SharpYuvFilterRow(cur_uv, next_uv, len, best_y + w + 1, out2 + 1,
|
||||
bit_depth);
|
||||
|
||||
// special boundary case for i == w - 1 when w is even
|
||||
if (!(w & 1)) {
|
||||
out1[w - 1] = Filter2(cur_uv[uv_w - 1], prev_uv[uv_w - 1],
|
||||
best_y[w - 1 + 0], bit_depth);
|
||||
out2[w - 1] = Filter2(cur_uv[uv_w - 1], next_uv[uv_w - 1],
|
||||
best_y[w - 1 + w], bit_depth);
|
||||
}
|
||||
out1 += w;
|
||||
out2 += w;
|
||||
prev_uv += uv_w;
|
||||
cur_uv += uv_w;
|
||||
next_uv += uv_w;
|
||||
}
|
||||
}
|
||||
|
||||
static WEBP_INLINE int RGBToYUVComponent(int r, int g, int b,
|
||||
const int coeffs[4], int sfix) {
|
||||
const int srounder = 1 << (YUV_FIX + sfix - 1);
|
||||
const int luma = coeffs[0] * r + coeffs[1] * g + coeffs[2] * b +
|
||||
coeffs[3] + srounder;
|
||||
return (luma >> (YUV_FIX + sfix));
|
||||
}
|
||||
|
||||
static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv,
|
||||
uint8_t* y_ptr, int y_stride, uint8_t* u_ptr,
|
||||
int u_stride, uint8_t* v_ptr, int v_stride,
|
||||
int rgb_bit_depth,
|
||||
int yuv_bit_depth, int width, int height,
|
||||
const SharpYuvConversionMatrix* yuv_matrix) {
|
||||
int i, j;
|
||||
const fixed_t* const best_uv_base = best_uv;
|
||||
const int w = (width + 1) & ~1;
|
||||
const int h = (height + 1) & ~1;
|
||||
const int uv_w = w >> 1;
|
||||
const int uv_h = h >> 1;
|
||||
const int sfix = GetPrecisionShift(rgb_bit_depth);
|
||||
const int yuv_max = (1 << yuv_bit_depth) - 1;
|
||||
|
||||
best_uv = best_uv_base;
|
||||
j = 0;
|
||||
do {
|
||||
i = 0;
|
||||
do {
|
||||
const int off = (i >> 1);
|
||||
const int W = best_y[i];
|
||||
const int r = best_uv[off + 0 * uv_w] + W;
|
||||
const int g = best_uv[off + 1 * uv_w] + W;
|
||||
const int b = best_uv[off + 2 * uv_w] + W;
|
||||
const int y = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_y, sfix);
|
||||
if (yuv_bit_depth <= 8) {
|
||||
y_ptr[i] = clip_8b(y);
|
||||
} else {
|
||||
((uint16_t*)y_ptr)[i] = clip(y, yuv_max);
|
||||
}
|
||||
} while (++i < width);
|
||||
best_y += w;
|
||||
best_uv += (j & 1) * 3 * uv_w;
|
||||
y_ptr += y_stride;
|
||||
} while (++j < height);
|
||||
|
||||
best_uv = best_uv_base;
|
||||
j = 0;
|
||||
do {
|
||||
i = 0;
|
||||
do {
|
||||
// Note r, g and b values here are off by W, but a constant offset on all
|
||||
// 3 components doesn't change the value of u and v with a YCbCr matrix.
|
||||
const int r = best_uv[i + 0 * uv_w];
|
||||
const int g = best_uv[i + 1 * uv_w];
|
||||
const int b = best_uv[i + 2 * uv_w];
|
||||
const int u = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_u, sfix);
|
||||
const int v = RGBToYUVComponent(r, g, b, yuv_matrix->rgb_to_v, sfix);
|
||||
if (yuv_bit_depth <= 8) {
|
||||
u_ptr[i] = clip_8b(u);
|
||||
v_ptr[i] = clip_8b(v);
|
||||
} else {
|
||||
((uint16_t*)u_ptr)[i] = clip(u, yuv_max);
|
||||
((uint16_t*)v_ptr)[i] = clip(v, yuv_max);
|
||||
}
|
||||
} while (++i < uv_w);
|
||||
best_uv += 3 * uv_w;
|
||||
u_ptr += u_stride;
|
||||
v_ptr += v_stride;
|
||||
} while (++j < uv_h);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Main function
|
||||
|
||||
static void* SafeMalloc(uint64_t nmemb, size_t size) {
|
||||
const uint64_t total_size = nmemb * (uint64_t)size;
|
||||
if (total_size != (size_t)total_size) return NULL;
|
||||
return malloc((size_t)total_size);
|
||||
}
|
||||
|
||||
#define SAFE_ALLOC(W, H, T) ((T*)SafeMalloc((uint64_t)(W) * (H), sizeof(T)))
|
||||
|
||||
static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
|
||||
const uint8_t* b_ptr, int rgb_step, int rgb_stride,
|
||||
int rgb_bit_depth, uint8_t* y_ptr, int y_stride,
|
||||
uint8_t* u_ptr, int u_stride, uint8_t* v_ptr,
|
||||
int v_stride, int yuv_bit_depth, int width,
|
||||
int height,
|
||||
const SharpYuvConversionMatrix* yuv_matrix,
|
||||
SharpYuvTransferFunctionType transfer_type) {
|
||||
// we expand the right/bottom border if needed
|
||||
const int w = (width + 1) & ~1;
|
||||
const int h = (height + 1) & ~1;
|
||||
const int uv_w = w >> 1;
|
||||
const int uv_h = h >> 1;
|
||||
const int y_bit_depth = rgb_bit_depth + GetPrecisionShift(rgb_bit_depth);
|
||||
uint64_t prev_diff_y_sum = ~0;
|
||||
int j, iter;
|
||||
|
||||
// TODO(skal): allocate one big memory chunk. But for now, it's easier
|
||||
// for valgrind debugging to have several chunks.
|
||||
fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch
|
||||
fixed_y_t* const best_y_base = SAFE_ALLOC(w, h, fixed_y_t);
|
||||
fixed_y_t* const target_y_base = SAFE_ALLOC(w, h, fixed_y_t);
|
||||
fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t);
|
||||
fixed_t* const best_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
|
||||
fixed_t* const target_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
|
||||
fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t);
|
||||
fixed_y_t* best_y = best_y_base;
|
||||
fixed_y_t* target_y = target_y_base;
|
||||
fixed_t* best_uv = best_uv_base;
|
||||
fixed_t* target_uv = target_uv_base;
|
||||
const uint64_t diff_y_threshold = (uint64_t)(3.0 * w * h);
|
||||
int ok;
|
||||
assert(w > 0);
|
||||
assert(h > 0);
|
||||
|
||||
if (best_y_base == NULL || best_uv_base == NULL ||
|
||||
target_y_base == NULL || target_uv_base == NULL ||
|
||||
best_rgb_y == NULL || best_rgb_uv == NULL ||
|
||||
tmp_buffer == NULL) {
|
||||
ok = 0;
|
||||
goto End;
|
||||
}
|
||||
|
||||
// Import RGB samples to W/RGB representation.
|
||||
for (j = 0; j < height; j += 2) {
|
||||
const int is_last_row = (j == height - 1);
|
||||
fixed_y_t* const src1 = tmp_buffer + 0 * w;
|
||||
fixed_y_t* const src2 = tmp_buffer + 3 * w;
|
||||
|
||||
// prepare two rows of input
|
||||
ImportOneRow(r_ptr, g_ptr, b_ptr, rgb_step, rgb_bit_depth, width,
|
||||
src1);
|
||||
if (!is_last_row) {
|
||||
ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride,
|
||||
rgb_step, rgb_bit_depth, width, src2);
|
||||
} else {
|
||||
memcpy(src2, src1, 3 * w * sizeof(*src2));
|
||||
}
|
||||
StoreGray(src1, best_y + 0, w);
|
||||
StoreGray(src2, best_y + w, w);
|
||||
|
||||
UpdateW(src1, target_y, w, rgb_bit_depth, transfer_type);
|
||||
UpdateW(src2, target_y + w, w, rgb_bit_depth, transfer_type);
|
||||
UpdateChroma(src1, src2, target_uv, uv_w, rgb_bit_depth, transfer_type);
|
||||
memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv));
|
||||
best_y += 2 * w;
|
||||
best_uv += 3 * uv_w;
|
||||
target_y += 2 * w;
|
||||
target_uv += 3 * uv_w;
|
||||
r_ptr += 2 * rgb_stride;
|
||||
g_ptr += 2 * rgb_stride;
|
||||
b_ptr += 2 * rgb_stride;
|
||||
}
|
||||
|
||||
// Iterate and resolve clipping conflicts.
|
||||
for (iter = 0; iter < kNumIterations; ++iter) {
|
||||
const fixed_t* cur_uv = best_uv_base;
|
||||
const fixed_t* prev_uv = best_uv_base;
|
||||
uint64_t diff_y_sum = 0;
|
||||
|
||||
best_y = best_y_base;
|
||||
best_uv = best_uv_base;
|
||||
target_y = target_y_base;
|
||||
target_uv = target_uv_base;
|
||||
j = 0;
|
||||
do {
|
||||
fixed_y_t* const src1 = tmp_buffer + 0 * w;
|
||||
fixed_y_t* const src2 = tmp_buffer + 3 * w;
|
||||
{
|
||||
const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0);
|
||||
InterpolateTwoRows(best_y, prev_uv, cur_uv, next_uv, w,
|
||||
src1, src2, rgb_bit_depth);
|
||||
prev_uv = cur_uv;
|
||||
cur_uv = next_uv;
|
||||
}
|
||||
|
||||
UpdateW(src1, best_rgb_y + 0 * w, w, rgb_bit_depth, transfer_type);
|
||||
UpdateW(src2, best_rgb_y + 1 * w, w, rgb_bit_depth, transfer_type);
|
||||
UpdateChroma(src1, src2, best_rgb_uv, uv_w, rgb_bit_depth, transfer_type);
|
||||
|
||||
// update two rows of Y and one row of RGB
|
||||
diff_y_sum +=
|
||||
SharpYuvUpdateY(target_y, best_rgb_y, best_y, 2 * w, y_bit_depth);
|
||||
SharpYuvUpdateRGB(target_uv, best_rgb_uv, best_uv, 3 * uv_w);
|
||||
|
||||
best_y += 2 * w;
|
||||
best_uv += 3 * uv_w;
|
||||
target_y += 2 * w;
|
||||
target_uv += 3 * uv_w;
|
||||
j += 2;
|
||||
} while (j < h);
|
||||
// test exit condition
|
||||
if (iter > 0) {
|
||||
if (diff_y_sum < diff_y_threshold) break;
|
||||
if (diff_y_sum > prev_diff_y_sum) break;
|
||||
}
|
||||
prev_diff_y_sum = diff_y_sum;
|
||||
}
|
||||
|
||||
// final reconstruction
|
||||
ok = ConvertWRGBToYUV(best_y_base, best_uv_base, y_ptr, y_stride, u_ptr,
|
||||
u_stride, v_ptr, v_stride, rgb_bit_depth, yuv_bit_depth,
|
||||
width, height, yuv_matrix);
|
||||
|
||||
End:
|
||||
free(best_y_base);
|
||||
free(best_uv_base);
|
||||
free(target_y_base);
|
||||
free(target_uv_base);
|
||||
free(best_rgb_y);
|
||||
free(best_rgb_uv);
|
||||
free(tmp_buffer);
|
||||
return ok;
|
||||
}
|
||||
|
||||
#undef SAFE_ALLOC
|
||||
|
||||
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
||||
#include <pthread.h> // NOLINT
|
||||
|
||||
#define LOCK_ACCESS \
|
||||
static pthread_mutex_t sharpyuv_lock = PTHREAD_MUTEX_INITIALIZER; \
|
||||
if (pthread_mutex_lock(&sharpyuv_lock)) return
|
||||
#define UNLOCK_ACCESS_AND_RETURN \
|
||||
do { \
|
||||
(void)pthread_mutex_unlock(&sharpyuv_lock); \
|
||||
return; \
|
||||
} while (0)
|
||||
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
|
||||
#define LOCK_ACCESS do {} while (0)
|
||||
#define UNLOCK_ACCESS_AND_RETURN return
|
||||
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
|
||||
|
||||
// Hidden exported init function.
|
||||
// By default SharpYuvConvert calls it with SharpYuvGetCPUInfo. If needed,
|
||||
// users can declare it as extern and call it with an alternate VP8CPUInfo
|
||||
// function.
|
||||
extern VP8CPUInfo SharpYuvGetCPUInfo;
|
||||
SHARPYUV_EXTERN void SharpYuvInit(VP8CPUInfo cpu_info_func);
|
||||
void SharpYuvInit(VP8CPUInfo cpu_info_func) {
|
||||
static volatile VP8CPUInfo sharpyuv_last_cpuinfo_used =
|
||||
(VP8CPUInfo)&sharpyuv_last_cpuinfo_used;
|
||||
LOCK_ACCESS;
|
||||
// Only update SharpYuvGetCPUInfo when called from external code to avoid a
|
||||
// race on reading the value in SharpYuvConvert().
|
||||
if (cpu_info_func != (VP8CPUInfo)&SharpYuvGetCPUInfo) {
|
||||
SharpYuvGetCPUInfo = cpu_info_func;
|
||||
}
|
||||
if (sharpyuv_last_cpuinfo_used == SharpYuvGetCPUInfo) {
|
||||
UNLOCK_ACCESS_AND_RETURN;
|
||||
}
|
||||
|
||||
SharpYuvInitDsp();
|
||||
SharpYuvInitGammaTables();
|
||||
|
||||
sharpyuv_last_cpuinfo_used = SharpYuvGetCPUInfo;
|
||||
UNLOCK_ACCESS_AND_RETURN;
|
||||
}
|
||||
|
||||
int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr,
|
||||
int rgb_step, int rgb_stride, int rgb_bit_depth,
|
||||
void* y_ptr, int y_stride, void* u_ptr, int u_stride,
|
||||
void* v_ptr, int v_stride, int yuv_bit_depth, int width,
|
||||
int height, const SharpYuvConversionMatrix* yuv_matrix) {
|
||||
SharpYuvOptions options;
|
||||
options.yuv_matrix = yuv_matrix;
|
||||
options.transfer_type = kSharpYuvTransferFunctionSrgb;
|
||||
return SharpYuvConvertWithOptions(
|
||||
r_ptr, g_ptr, b_ptr, rgb_step, rgb_stride, rgb_bit_depth, y_ptr, y_stride,
|
||||
u_ptr, u_stride, v_ptr, v_stride, yuv_bit_depth, width, height, &options);
|
||||
}
|
||||
|
||||
int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix* yuv_matrix,
|
||||
SharpYuvOptions* options, int version) {
|
||||
const int major = (version >> 24);
|
||||
const int minor = (version >> 16) & 0xff;
|
||||
if (options == NULL || yuv_matrix == NULL ||
|
||||
(major == SHARPYUV_VERSION_MAJOR && major == 0 &&
|
||||
minor != SHARPYUV_VERSION_MINOR) ||
|
||||
(major != SHARPYUV_VERSION_MAJOR)) {
|
||||
return 0;
|
||||
}
|
||||
options->yuv_matrix = yuv_matrix;
|
||||
options->transfer_type = kSharpYuvTransferFunctionSrgb;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SharpYuvConvertWithOptions(const void* r_ptr, const void* g_ptr,
|
||||
const void* b_ptr, int rgb_step, int rgb_stride,
|
||||
int rgb_bit_depth, void* y_ptr, int y_stride,
|
||||
void* u_ptr, int u_stride, void* v_ptr,
|
||||
int v_stride, int yuv_bit_depth, int width,
|
||||
int height, const SharpYuvOptions* options) {
|
||||
const SharpYuvConversionMatrix* yuv_matrix = options->yuv_matrix;
|
||||
SharpYuvTransferFunctionType transfer_type = options->transfer_type;
|
||||
SharpYuvConversionMatrix scaled_matrix;
|
||||
const int rgb_max = (1 << rgb_bit_depth) - 1;
|
||||
const int rgb_round = 1 << (rgb_bit_depth - 1);
|
||||
const int yuv_max = (1 << yuv_bit_depth) - 1;
|
||||
const int sfix = GetPrecisionShift(rgb_bit_depth);
|
||||
|
||||
if (width < 1 || height < 1 || width == INT_MAX || height == INT_MAX ||
|
||||
r_ptr == NULL || g_ptr == NULL || b_ptr == NULL || y_ptr == NULL ||
|
||||
u_ptr == NULL || v_ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (rgb_bit_depth != 8 && rgb_bit_depth != 10 && rgb_bit_depth != 12 &&
|
||||
rgb_bit_depth != 16) {
|
||||
return 0;
|
||||
}
|
||||
if (yuv_bit_depth != 8 && yuv_bit_depth != 10 && yuv_bit_depth != 12) {
|
||||
return 0;
|
||||
}
|
||||
if (rgb_bit_depth > 8 && (rgb_step % 2 != 0 || rgb_stride % 2 != 0)) {
|
||||
// Step/stride should be even for uint16_t buffers.
|
||||
return 0;
|
||||
}
|
||||
if (yuv_bit_depth > 8 &&
|
||||
(y_stride % 2 != 0 || u_stride % 2 != 0 || v_stride % 2 != 0)) {
|
||||
// Stride should be even for uint16_t buffers.
|
||||
return 0;
|
||||
}
|
||||
// The address of the function pointer is used to avoid a read race.
|
||||
SharpYuvInit((VP8CPUInfo)&SharpYuvGetCPUInfo);
|
||||
|
||||
// Add scaling factor to go from rgb_bit_depth to yuv_bit_depth, to the
|
||||
// rgb->yuv conversion matrix.
|
||||
if (rgb_bit_depth == yuv_bit_depth) {
|
||||
memcpy(&scaled_matrix, yuv_matrix, sizeof(scaled_matrix));
|
||||
} else {
|
||||
int i;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
scaled_matrix.rgb_to_y[i] =
|
||||
(yuv_matrix->rgb_to_y[i] * yuv_max + rgb_round) / rgb_max;
|
||||
scaled_matrix.rgb_to_u[i] =
|
||||
(yuv_matrix->rgb_to_u[i] * yuv_max + rgb_round) / rgb_max;
|
||||
scaled_matrix.rgb_to_v[i] =
|
||||
(yuv_matrix->rgb_to_v[i] * yuv_max + rgb_round) / rgb_max;
|
||||
}
|
||||
}
|
||||
// Also incorporate precision change scaling.
|
||||
scaled_matrix.rgb_to_y[3] = Shift(yuv_matrix->rgb_to_y[3], sfix);
|
||||
scaled_matrix.rgb_to_u[3] = Shift(yuv_matrix->rgb_to_u[3], sfix);
|
||||
scaled_matrix.rgb_to_v[3] = Shift(yuv_matrix->rgb_to_v[3], sfix);
|
||||
|
||||
return DoSharpArgbToYuv(
|
||||
(const uint8_t*)r_ptr, (const uint8_t*)g_ptr, (const uint8_t*)b_ptr,
|
||||
rgb_step, rgb_stride, rgb_bit_depth, (uint8_t*)y_ptr, y_stride,
|
||||
(uint8_t*)u_ptr, u_stride, (uint8_t*)v_ptr, v_stride, yuv_bit_depth,
|
||||
width, height, &scaled_matrix, transfer_type);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
181
sharpyuv/sharpyuv.h
Normal file
181
sharpyuv/sharpyuv.h
Normal file
@ -0,0 +1,181 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Sharp RGB to YUV conversion.
|
||||
|
||||
#ifndef WEBP_SHARPYUV_SHARPYUV_H_
|
||||
#define WEBP_SHARPYUV_SHARPYUV_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef SHARPYUV_EXTERN
|
||||
#ifdef WEBP_EXTERN
|
||||
#define SHARPYUV_EXTERN WEBP_EXTERN
|
||||
#else
|
||||
// This explicitly marks library functions and allows for changing the
|
||||
// signature for e.g., Windows DLL builds.
|
||||
#if defined(_WIN32) && defined(WEBP_DLL)
|
||||
#define SHARPYUV_EXTERN __declspec(dllexport)
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define SHARPYUV_EXTERN extern __attribute__((visibility("default")))
|
||||
#else
|
||||
#define SHARPYUV_EXTERN extern
|
||||
#endif /* defined(_WIN32) && defined(WEBP_DLL) */
|
||||
#endif /* WEBP_EXTERN */
|
||||
#endif /* SHARPYUV_EXTERN */
|
||||
|
||||
#ifndef SHARPYUV_INLINE
|
||||
#ifdef WEBP_INLINE
|
||||
#define SHARPYUV_INLINE WEBP_INLINE
|
||||
#else
|
||||
#ifndef _MSC_VER
|
||||
#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \
|
||||
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
|
||||
#define SHARPYUV_INLINE inline
|
||||
#else
|
||||
#define SHARPYUV_INLINE
|
||||
#endif
|
||||
#else
|
||||
#define SHARPYUV_INLINE __forceinline
|
||||
#endif /* _MSC_VER */
|
||||
#endif /* WEBP_INLINE */
|
||||
#endif /* SHARPYUV_INLINE */
|
||||
|
||||
// SharpYUV API version following the convention from semver.org
|
||||
#define SHARPYUV_VERSION_MAJOR 0
|
||||
#define SHARPYUV_VERSION_MINOR 4
|
||||
#define SHARPYUV_VERSION_PATCH 0
|
||||
// Version as a uint32_t. The major number is the high 8 bits.
|
||||
// The minor number is the middle 8 bits. The patch number is the low 16 bits.
|
||||
#define SHARPYUV_MAKE_VERSION(MAJOR, MINOR, PATCH) \
|
||||
(((MAJOR) << 24) | ((MINOR) << 16) | (PATCH))
|
||||
#define SHARPYUV_VERSION \
|
||||
SHARPYUV_MAKE_VERSION(SHARPYUV_VERSION_MAJOR, SHARPYUV_VERSION_MINOR, \
|
||||
SHARPYUV_VERSION_PATCH)
|
||||
|
||||
// Returns the library's version number, packed in hexadecimal. See
|
||||
// SHARPYUV_VERSION.
|
||||
SHARPYUV_EXTERN int SharpYuvGetVersion(void);
|
||||
|
||||
// RGB to YUV conversion matrix, in 16 bit fixed point.
|
||||
// y_ = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3]
|
||||
// u_ = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3]
|
||||
// v_ = rgb_to_v[0] * r + rgb_to_v[1] * g + rgb_to_v[2] * b + rgb_to_v[3]
|
||||
// Then the values are divided by 1<<16 and rounded.
|
||||
// y = (y_ + (1 << 15)) >> 16
|
||||
// u = (u_ + (1 << 15)) >> 16
|
||||
// v = (v_ + (1 << 15)) >> 16
|
||||
//
|
||||
// Typically, the offset values rgb_to_y[3], rgb_to_u[3] and rgb_to_v[3] depend
|
||||
// on the input's bit depth, e.g., rgb_to_u[3] = 1 << (rgb_bit_depth - 1 + 16).
|
||||
// See also sharpyuv_csp.h to get a predefined matrix or generate a matrix.
|
||||
typedef struct {
|
||||
int rgb_to_y[4];
|
||||
int rgb_to_u[4];
|
||||
int rgb_to_v[4];
|
||||
} SharpYuvConversionMatrix;
|
||||
|
||||
typedef struct SharpYuvOptions SharpYuvOptions;
|
||||
|
||||
// Enums for transfer functions, as defined in H.273,
|
||||
// https://www.itu.int/rec/T-REC-H.273-202107-I/en
|
||||
typedef enum SharpYuvTransferFunctionType {
|
||||
// 0 is reserved
|
||||
kSharpYuvTransferFunctionBt709 = 1,
|
||||
// 2 is unspecified
|
||||
// 3 is reserved
|
||||
kSharpYuvTransferFunctionBt470M = 4,
|
||||
kSharpYuvTransferFunctionBt470Bg = 5,
|
||||
kSharpYuvTransferFunctionBt601 = 6,
|
||||
kSharpYuvTransferFunctionSmpte240 = 7,
|
||||
kSharpYuvTransferFunctionLinear = 8,
|
||||
kSharpYuvTransferFunctionLog100 = 9,
|
||||
kSharpYuvTransferFunctionLog100_Sqrt10 = 10,
|
||||
kSharpYuvTransferFunctionIec61966 = 11,
|
||||
kSharpYuvTransferFunctionBt1361 = 12,
|
||||
kSharpYuvTransferFunctionSrgb = 13,
|
||||
kSharpYuvTransferFunctionBt2020_10Bit = 14,
|
||||
kSharpYuvTransferFunctionBt2020_12Bit = 15,
|
||||
kSharpYuvTransferFunctionSmpte2084 = 16, // PQ
|
||||
kSharpYuvTransferFunctionSmpte428 = 17,
|
||||
kSharpYuvTransferFunctionHlg = 18,
|
||||
kSharpYuvTransferFunctionNum
|
||||
} SharpYuvTransferFunctionType;
|
||||
|
||||
// Converts RGB to YUV420 using a downsampling algorithm that minimizes
|
||||
// artefacts caused by chroma subsampling.
|
||||
// This is slower than standard downsampling (averaging of 4 UV values).
|
||||
// Assumes that the image will be upsampled using a bilinear filter. If nearest
|
||||
// neighbor is used instead, the upsampled image might look worse than with
|
||||
// standard downsampling.
|
||||
// r_ptr, g_ptr, b_ptr: pointers to the source r, g and b channels. Should point
|
||||
// to uint8_t buffers if rgb_bit_depth is 8, or uint16_t buffers otherwise.
|
||||
// rgb_step: distance in bytes between two horizontally adjacent pixels on the
|
||||
// r, g and b channels. If rgb_bit_depth is > 8, it should be a
|
||||
// multiple of 2.
|
||||
// rgb_stride: distance in bytes between two vertically adjacent pixels on the
|
||||
// r, g, and b channels. If rgb_bit_depth is > 8, it should be a
|
||||
// multiple of 2.
|
||||
// rgb_bit_depth: number of bits for each r/g/b value. One of: 8, 10, 12, 16.
|
||||
// Note: 16 bit input is truncated to 14 bits before conversion to yuv.
|
||||
// yuv_bit_depth: number of bits for each y/u/v value. One of: 8, 10, 12.
|
||||
// y_ptr, u_ptr, v_ptr: pointers to the destination y, u and v channels. Should
|
||||
// point to uint8_t buffers if yuv_bit_depth is 8, or uint16_t buffers
|
||||
// otherwise.
|
||||
// y_stride, u_stride, v_stride: distance in bytes between two vertically
|
||||
// adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they
|
||||
// should be multiples of 2.
|
||||
// width, height: width and height of the image in pixels
|
||||
// yuv_matrix: RGB to YUV conversion matrix. The matrix values typically
|
||||
// depend on the input's rgb_bit_depth.
|
||||
// This function calls SharpYuvConvertWithOptions with a default transfer
|
||||
// function of kSharpYuvTransferFunctionSrgb.
|
||||
SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
|
||||
const void* b_ptr, int rgb_step,
|
||||
int rgb_stride, int rgb_bit_depth,
|
||||
void* y_ptr, int y_stride, void* u_ptr,
|
||||
int u_stride, void* v_ptr, int v_stride,
|
||||
int yuv_bit_depth, int width, int height,
|
||||
const SharpYuvConversionMatrix* yuv_matrix);
|
||||
|
||||
struct SharpYuvOptions {
|
||||
// This matrix cannot be NULL and can be initialized by
|
||||
// SharpYuvComputeConversionMatrix.
|
||||
const SharpYuvConversionMatrix* yuv_matrix;
|
||||
SharpYuvTransferFunctionType transfer_type;
|
||||
};
|
||||
|
||||
// Internal, version-checked, entry point
|
||||
SHARPYUV_EXTERN int SharpYuvOptionsInitInternal(const SharpYuvConversionMatrix*,
|
||||
SharpYuvOptions*, int);
|
||||
|
||||
// Should always be called, to initialize a fresh SharpYuvOptions
|
||||
// structure before modification. SharpYuvOptionsInit() must have succeeded
|
||||
// before using the 'options' object.
|
||||
static SHARPYUV_INLINE int SharpYuvOptionsInit(
|
||||
const SharpYuvConversionMatrix* yuv_matrix, SharpYuvOptions* options) {
|
||||
return SharpYuvOptionsInitInternal(yuv_matrix, options, SHARPYUV_VERSION);
|
||||
}
|
||||
|
||||
SHARPYUV_EXTERN int SharpYuvConvertWithOptions(
|
||||
const void* r_ptr, const void* g_ptr, const void* b_ptr, int rgb_step,
|
||||
int rgb_stride, int rgb_bit_depth, void* y_ptr, int y_stride, void* u_ptr,
|
||||
int u_stride, void* v_ptr, int v_stride, int yuv_bit_depth, int width,
|
||||
int height, const SharpYuvOptions* options);
|
||||
|
||||
// TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422
|
||||
// support (it's rarely used in practice, especially for images).
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WEBP_SHARPYUV_SHARPYUV_H_
|
14
sharpyuv/sharpyuv_cpu.c
Normal file
14
sharpyuv/sharpyuv_cpu.c
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
#include "sharpyuv/sharpyuv_cpu.h"
|
||||
|
||||
// Include src/dsp/cpu.c to create SharpYuvGetCPUInfo from VP8GetCPUInfo. The
|
||||
// function pointer is renamed in sharpyuv_cpu.h.
|
||||
#include "src/dsp/cpu.c"
|
22
sharpyuv/sharpyuv_cpu.h
Normal file
22
sharpyuv/sharpyuv_cpu.h
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
#ifndef WEBP_SHARPYUV_SHARPYUV_CPU_H_
|
||||
#define WEBP_SHARPYUV_SHARPYUV_CPU_H_
|
||||
|
||||
#include "sharpyuv/sharpyuv.h"
|
||||
|
||||
// Avoid exporting SharpYuvGetCPUInfo in shared object / DLL builds.
|
||||
// SharpYuvInit() replaces the use of the function pointer.
|
||||
#undef WEBP_EXTERN
|
||||
#define WEBP_EXTERN extern
|
||||
#define VP8GetCPUInfo SharpYuvGetCPUInfo
|
||||
#include "src/dsp/cpu.h"
|
||||
|
||||
#endif // WEBP_SHARPYUV_SHARPYUV_CPU_H_
|
110
sharpyuv/sharpyuv_csp.c
Normal file
110
sharpyuv/sharpyuv_csp.c
Normal file
@ -0,0 +1,110 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Colorspace utilities.
|
||||
|
||||
#include "sharpyuv/sharpyuv_csp.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); }
|
||||
|
||||
void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space,
|
||||
SharpYuvConversionMatrix* matrix) {
|
||||
const float kr = yuv_color_space->kr;
|
||||
const float kb = yuv_color_space->kb;
|
||||
const float kg = 1.0f - kr - kb;
|
||||
const float cr = 0.5f / (1.0f - kb);
|
||||
const float cb = 0.5f / (1.0f - kr);
|
||||
|
||||
const int shift = yuv_color_space->bit_depth - 8;
|
||||
|
||||
const float denom = (float)((1 << yuv_color_space->bit_depth) - 1);
|
||||
float scale_y = 1.0f;
|
||||
float add_y = 0.0f;
|
||||
float scale_u = cr;
|
||||
float scale_v = cb;
|
||||
float add_uv = (float)(128 << shift);
|
||||
assert(yuv_color_space->bit_depth >= 8);
|
||||
|
||||
if (yuv_color_space->range == kSharpYuvRangeLimited) {
|
||||
scale_y *= (219 << shift) / denom;
|
||||
scale_u *= (224 << shift) / denom;
|
||||
scale_v *= (224 << shift) / denom;
|
||||
add_y = (float)(16 << shift);
|
||||
}
|
||||
|
||||
matrix->rgb_to_y[0] = ToFixed16(kr * scale_y);
|
||||
matrix->rgb_to_y[1] = ToFixed16(kg * scale_y);
|
||||
matrix->rgb_to_y[2] = ToFixed16(kb * scale_y);
|
||||
matrix->rgb_to_y[3] = ToFixed16(add_y);
|
||||
|
||||
matrix->rgb_to_u[0] = ToFixed16(-kr * scale_u);
|
||||
matrix->rgb_to_u[1] = ToFixed16(-kg * scale_u);
|
||||
matrix->rgb_to_u[2] = ToFixed16((1 - kb) * scale_u);
|
||||
matrix->rgb_to_u[3] = ToFixed16(add_uv);
|
||||
|
||||
matrix->rgb_to_v[0] = ToFixed16((1 - kr) * scale_v);
|
||||
matrix->rgb_to_v[1] = ToFixed16(-kg * scale_v);
|
||||
matrix->rgb_to_v[2] = ToFixed16(-kb * scale_v);
|
||||
matrix->rgb_to_v[3] = ToFixed16(add_uv);
|
||||
}
|
||||
|
||||
// Matrices are in YUV_FIX fixed point precision.
|
||||
// WebP's matrix, similar but not identical to kRec601LimitedMatrix
|
||||
static const SharpYuvConversionMatrix kWebpMatrix = {
|
||||
{16839, 33059, 6420, 16 << 16},
|
||||
{-9719, -19081, 28800, 128 << 16},
|
||||
{28800, -24116, -4684, 128 << 16},
|
||||
};
|
||||
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeLimited
|
||||
static const SharpYuvConversionMatrix kRec601LimitedMatrix = {
|
||||
{16829, 33039, 6416, 16 << 16},
|
||||
{-9714, -19071, 28784, 128 << 16},
|
||||
{28784, -24103, -4681, 128 << 16},
|
||||
};
|
||||
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeFull
|
||||
static const SharpYuvConversionMatrix kRec601FullMatrix = {
|
||||
{19595, 38470, 7471, 0},
|
||||
{-11058, -21710, 32768, 128 << 16},
|
||||
{32768, -27439, -5329, 128 << 16},
|
||||
};
|
||||
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeLimited
|
||||
static const SharpYuvConversionMatrix kRec709LimitedMatrix = {
|
||||
{11966, 40254, 4064, 16 << 16},
|
||||
{-6596, -22189, 28784, 128 << 16},
|
||||
{28784, -26145, -2639, 128 << 16},
|
||||
};
|
||||
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeFull
|
||||
static const SharpYuvConversionMatrix kRec709FullMatrix = {
|
||||
{13933, 46871, 4732, 0},
|
||||
{-7509, -25259, 32768, 128 << 16},
|
||||
{32768, -29763, -3005, 128 << 16},
|
||||
};
|
||||
|
||||
const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
|
||||
SharpYuvMatrixType matrix_type) {
|
||||
switch (matrix_type) {
|
||||
case kSharpYuvMatrixWebp:
|
||||
return &kWebpMatrix;
|
||||
case kSharpYuvMatrixRec601Limited:
|
||||
return &kRec601LimitedMatrix;
|
||||
case kSharpYuvMatrixRec601Full:
|
||||
return &kRec601FullMatrix;
|
||||
case kSharpYuvMatrixRec709Limited:
|
||||
return &kRec709LimitedMatrix;
|
||||
case kSharpYuvMatrixRec709Full:
|
||||
return &kRec709FullMatrix;
|
||||
case kSharpYuvMatrixNum:
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
65
sharpyuv/sharpyuv_csp.h
Normal file
65
sharpyuv/sharpyuv_csp.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Colorspace utilities.
|
||||
|
||||
#ifndef WEBP_SHARPYUV_SHARPYUV_CSP_H_
|
||||
#define WEBP_SHARPYUV_SHARPYUV_CSP_H_
|
||||
|
||||
#include "sharpyuv/sharpyuv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Range of YUV values.
|
||||
typedef enum {
|
||||
kSharpYuvRangeFull, // YUV values between [0;255] (for 8 bit)
|
||||
kSharpYuvRangeLimited // Y in [16;235], YUV in [16;240] (for 8 bit)
|
||||
} SharpYuvRange;
|
||||
|
||||
// Constants that define a YUV color space.
|
||||
typedef struct {
|
||||
// Kr and Kb are defined such that:
|
||||
// Y = Kr * r + Kg * g + Kb * b where Kg = 1 - Kr - Kb.
|
||||
float kr;
|
||||
float kb;
|
||||
int bit_depth; // 8, 10 or 12
|
||||
SharpYuvRange range;
|
||||
} SharpYuvColorSpace;
|
||||
|
||||
// Fills in 'matrix' for the given YUVColorSpace.
|
||||
SHARPYUV_EXTERN void SharpYuvComputeConversionMatrix(
|
||||
const SharpYuvColorSpace* yuv_color_space,
|
||||
SharpYuvConversionMatrix* matrix);
|
||||
|
||||
// Enums for precomputed conversion matrices.
|
||||
typedef enum {
|
||||
// WebP's matrix, similar but not identical to kSharpYuvMatrixRec601Limited
|
||||
kSharpYuvMatrixWebp = 0,
|
||||
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeLimited
|
||||
kSharpYuvMatrixRec601Limited,
|
||||
// Kr=0.2990f Kb=0.1140f bit_depth=8 range=kSharpYuvRangeFull
|
||||
kSharpYuvMatrixRec601Full,
|
||||
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeLimited
|
||||
kSharpYuvMatrixRec709Limited,
|
||||
// Kr=0.2126f Kb=0.0722f bit_depth=8 range=kSharpYuvRangeFull
|
||||
kSharpYuvMatrixRec709Full,
|
||||
kSharpYuvMatrixNum
|
||||
} SharpYuvMatrixType;
|
||||
|
||||
// Returns a pointer to a matrix for one of the predefined colorspaces.
|
||||
SHARPYUV_EXTERN const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
|
||||
SharpYuvMatrixType matrix_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WEBP_SHARPYUV_SHARPYUV_CSP_H_
|
104
sharpyuv/sharpyuv_dsp.c
Normal file
104
sharpyuv/sharpyuv_dsp.c
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Speed-critical functions for Sharp YUV.
|
||||
//
|
||||
// Author: Skal (pascal.massimino@gmail.com)
|
||||
|
||||
#include "sharpyuv/sharpyuv_dsp.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sharpyuv/sharpyuv_cpu.h"
|
||||
#include "src/webp/types.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if !WEBP_NEON_OMIT_C_CODE
|
||||
static uint16_t clip(int v, int max) {
|
||||
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
|
||||
}
|
||||
|
||||
static uint64_t SharpYuvUpdateY_C(const uint16_t* ref, const uint16_t* src,
|
||||
uint16_t* dst, int len, int bit_depth) {
|
||||
uint64_t diff = 0;
|
||||
int i;
|
||||
const int max_y = (1 << bit_depth) - 1;
|
||||
for (i = 0; i < len; ++i) {
|
||||
const int diff_y = ref[i] - src[i];
|
||||
const int new_y = (int)dst[i] + diff_y;
|
||||
dst[i] = clip(new_y, max_y);
|
||||
diff += (uint64_t)abs(diff_y);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static void SharpYuvUpdateRGB_C(const int16_t* ref, const int16_t* src,
|
||||
int16_t* dst, int len) {
|
||||
int i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
const int diff_uv = ref[i] - src[i];
|
||||
dst[i] += diff_uv;
|
||||
}
|
||||
}
|
||||
|
||||
static void SharpYuvFilterRow_C(const int16_t* A, const int16_t* B, int len,
|
||||
const uint16_t* best_y, uint16_t* out,
|
||||
int bit_depth) {
|
||||
int i;
|
||||
const int max_y = (1 << bit_depth) - 1;
|
||||
for (i = 0; i < len; ++i, ++A, ++B) {
|
||||
const int v0 = (A[0] * 9 + A[1] * 3 + B[0] * 3 + B[1] + 8) >> 4;
|
||||
const int v1 = (A[1] * 9 + A[0] * 3 + B[1] * 3 + B[0] + 8) >> 4;
|
||||
out[2 * i + 0] = clip(best_y[2 * i + 0] + v0, max_y);
|
||||
out[2 * i + 1] = clip(best_y[2 * i + 1] + v1, max_y);
|
||||
}
|
||||
}
|
||||
#endif // !WEBP_NEON_OMIT_C_CODE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref,
|
||||
uint16_t* dst, int len, int bit_depth);
|
||||
void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, int16_t* dst,
|
||||
int len);
|
||||
void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len,
|
||||
const uint16_t* best_y, uint16_t* out, int bit_depth);
|
||||
|
||||
extern VP8CPUInfo SharpYuvGetCPUInfo;
|
||||
extern void InitSharpYuvSSE2(void);
|
||||
extern void InitSharpYuvNEON(void);
|
||||
|
||||
void SharpYuvInitDsp(void) {
|
||||
#if !WEBP_NEON_OMIT_C_CODE
|
||||
SharpYuvUpdateY = SharpYuvUpdateY_C;
|
||||
SharpYuvUpdateRGB = SharpYuvUpdateRGB_C;
|
||||
SharpYuvFilterRow = SharpYuvFilterRow_C;
|
||||
#endif
|
||||
|
||||
if (SharpYuvGetCPUInfo != NULL) {
|
||||
#if defined(WEBP_HAVE_SSE2)
|
||||
if (SharpYuvGetCPUInfo(kSSE2)) {
|
||||
InitSharpYuvSSE2();
|
||||
}
|
||||
#endif // WEBP_HAVE_SSE2
|
||||
}
|
||||
|
||||
#if defined(WEBP_HAVE_NEON)
|
||||
if (WEBP_NEON_OMIT_C_CODE ||
|
||||
(SharpYuvGetCPUInfo != NULL && SharpYuvGetCPUInfo(kNEON))) {
|
||||
InitSharpYuvNEON();
|
||||
}
|
||||
#endif // WEBP_HAVE_NEON
|
||||
|
||||
assert(SharpYuvUpdateY != NULL);
|
||||
assert(SharpYuvUpdateRGB != NULL);
|
||||
assert(SharpYuvFilterRow != NULL);
|
||||
}
|
28
sharpyuv/sharpyuv_dsp.h
Normal file
28
sharpyuv/sharpyuv_dsp.h
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Speed-critical functions for Sharp YUV.
|
||||
|
||||
#ifndef WEBP_SHARPYUV_SHARPYUV_DSP_H_
|
||||
#define WEBP_SHARPYUV_SHARPYUV_DSP_H_
|
||||
|
||||
#include "sharpyuv/sharpyuv_cpu.h"
|
||||
#include "src/webp/types.h"
|
||||
|
||||
extern uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref,
|
||||
uint16_t* dst, int len, int bit_depth);
|
||||
extern void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref,
|
||||
int16_t* dst, int len);
|
||||
extern void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len,
|
||||
const uint16_t* best_y, uint16_t* out,
|
||||
int bit_depth);
|
||||
|
||||
void SharpYuvInitDsp(void);
|
||||
|
||||
#endif // WEBP_SHARPYUV_SHARPYUV_DSP_H_
|
419
sharpyuv/sharpyuv_gamma.c
Normal file
419
sharpyuv/sharpyuv_gamma.c
Normal file
@ -0,0 +1,419 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Gamma correction utilities.
|
||||
|
||||
#include "sharpyuv/sharpyuv_gamma.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "src/webp/types.h"
|
||||
|
||||
// Gamma correction compensates loss of resolution during chroma subsampling.
|
||||
// Size of pre-computed table for converting from gamma to linear.
|
||||
#define GAMMA_TO_LINEAR_TAB_BITS 10
|
||||
#define GAMMA_TO_LINEAR_TAB_SIZE (1 << GAMMA_TO_LINEAR_TAB_BITS)
|
||||
static uint32_t kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE + 2];
|
||||
#define LINEAR_TO_GAMMA_TAB_BITS 9
|
||||
#define LINEAR_TO_GAMMA_TAB_SIZE (1 << LINEAR_TO_GAMMA_TAB_BITS)
|
||||
static uint32_t kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 2];
|
||||
|
||||
static const double kGammaF = 1. / 0.45;
|
||||
#define GAMMA_TO_LINEAR_BITS 16
|
||||
|
||||
static volatile int kGammaTablesSOk = 0;
|
||||
void SharpYuvInitGammaTables(void) {
|
||||
assert(GAMMA_TO_LINEAR_BITS <= 16);
|
||||
if (!kGammaTablesSOk) {
|
||||
int v;
|
||||
const double a = 0.09929682680944;
|
||||
const double thresh = 0.018053968510807;
|
||||
const double final_scale = 1 << GAMMA_TO_LINEAR_BITS;
|
||||
// Precompute gamma to linear table.
|
||||
{
|
||||
const double norm = 1. / GAMMA_TO_LINEAR_TAB_SIZE;
|
||||
const double a_rec = 1. / (1. + a);
|
||||
for (v = 0; v <= GAMMA_TO_LINEAR_TAB_SIZE; ++v) {
|
||||
const double g = norm * v;
|
||||
double value;
|
||||
if (g <= thresh * 4.5) {
|
||||
value = g / 4.5;
|
||||
} else {
|
||||
value = pow(a_rec * (g + a), kGammaF);
|
||||
}
|
||||
kGammaToLinearTabS[v] = (uint32_t)(value * final_scale + .5);
|
||||
}
|
||||
// to prevent small rounding errors to cause read-overflow:
|
||||
kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE + 1] =
|
||||
kGammaToLinearTabS[GAMMA_TO_LINEAR_TAB_SIZE];
|
||||
}
|
||||
// Precompute linear to gamma table.
|
||||
{
|
||||
const double scale = 1. / LINEAR_TO_GAMMA_TAB_SIZE;
|
||||
for (v = 0; v <= LINEAR_TO_GAMMA_TAB_SIZE; ++v) {
|
||||
const double g = scale * v;
|
||||
double value;
|
||||
if (g <= thresh) {
|
||||
value = 4.5 * g;
|
||||
} else {
|
||||
value = (1. + a) * pow(g, 1. / kGammaF) - a;
|
||||
}
|
||||
kLinearToGammaTabS[v] =
|
||||
(uint32_t)(final_scale * value + 0.5);
|
||||
}
|
||||
// to prevent small rounding errors to cause read-overflow:
|
||||
kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE + 1] =
|
||||
kLinearToGammaTabS[LINEAR_TO_GAMMA_TAB_SIZE];
|
||||
}
|
||||
kGammaTablesSOk = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static WEBP_INLINE int Shift(int v, int shift) {
|
||||
return (shift >= 0) ? (v << shift) : (v >> -shift);
|
||||
}
|
||||
|
||||
static WEBP_INLINE uint32_t FixedPointInterpolation(int v, uint32_t* tab,
|
||||
int tab_pos_shift_right,
|
||||
int tab_value_shift) {
|
||||
const uint32_t tab_pos = Shift(v, -tab_pos_shift_right);
|
||||
// fractional part, in 'tab_pos_shift' fixed-point precision
|
||||
const uint32_t x = v - (tab_pos << tab_pos_shift_right); // fractional part
|
||||
// v0 / v1 are in kGammaToLinearBits fixed-point precision (range [0..1])
|
||||
const uint32_t v0 = Shift(tab[tab_pos + 0], tab_value_shift);
|
||||
const uint32_t v1 = Shift(tab[tab_pos + 1], tab_value_shift);
|
||||
// Final interpolation.
|
||||
const uint32_t v2 = (v1 - v0) * x; // note: v1 >= v0.
|
||||
const int half =
|
||||
(tab_pos_shift_right > 0) ? 1 << (tab_pos_shift_right - 1) : 0;
|
||||
const uint32_t result = v0 + ((v2 + half) >> tab_pos_shift_right);
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t ToLinearSrgb(uint16_t v, int bit_depth) {
|
||||
const int shift = GAMMA_TO_LINEAR_TAB_BITS - bit_depth;
|
||||
if (shift > 0) {
|
||||
return kGammaToLinearTabS[v << shift];
|
||||
}
|
||||
return FixedPointInterpolation(v, kGammaToLinearTabS, -shift, 0);
|
||||
}
|
||||
|
||||
static uint16_t FromLinearSrgb(uint32_t value, int bit_depth) {
|
||||
return FixedPointInterpolation(
|
||||
value, kLinearToGammaTabS,
|
||||
(GAMMA_TO_LINEAR_BITS - LINEAR_TO_GAMMA_TAB_BITS),
|
||||
bit_depth - GAMMA_TO_LINEAR_BITS);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define CLAMP(x, low, high) \
|
||||
(((x) < (low)) ? (low) : (((high) < (x)) ? (high) : (x)))
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
static WEBP_INLINE float Roundf(float x) {
|
||||
if (x < 0)
|
||||
return (float)ceil((double)(x - 0.5f));
|
||||
else
|
||||
return (float)floor((double)(x + 0.5f));
|
||||
}
|
||||
|
||||
static WEBP_INLINE float Powf(float base, float exp) {
|
||||
return (float)pow((double)base, (double)exp);
|
||||
}
|
||||
|
||||
static WEBP_INLINE float Log10f(float x) { return (float)log10((double)x); }
|
||||
|
||||
static float ToLinear709(float gamma) {
|
||||
if (gamma < 0.f) {
|
||||
return 0.f;
|
||||
} else if (gamma < 4.5f * 0.018053968510807f) {
|
||||
return gamma / 4.5f;
|
||||
} else if (gamma < 1.f) {
|
||||
return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f);
|
||||
}
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
static float FromLinear709(float linear) {
|
||||
if (linear < 0.f) {
|
||||
return 0.f;
|
||||
} else if (linear < 0.018053968510807f) {
|
||||
return linear * 4.5f;
|
||||
} else if (linear < 1.f) {
|
||||
return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f;
|
||||
}
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
static float ToLinear470M(float gamma) {
|
||||
return Powf(CLAMP(gamma, 0.f, 1.f), 2.2f);
|
||||
}
|
||||
|
||||
static float FromLinear470M(float linear) {
|
||||
return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.2f);
|
||||
}
|
||||
|
||||
static float ToLinear470Bg(float gamma) {
|
||||
return Powf(CLAMP(gamma, 0.f, 1.f), 2.8f);
|
||||
}
|
||||
|
||||
static float FromLinear470Bg(float linear) {
|
||||
return Powf(CLAMP(linear, 0.f, 1.f), 1.f / 2.8f);
|
||||
}
|
||||
|
||||
static float ToLinearSmpte240(float gamma) {
|
||||
if (gamma < 0.f) {
|
||||
return 0.f;
|
||||
} else if (gamma < 4.f * 0.022821585529445f) {
|
||||
return gamma / 4.f;
|
||||
} else if (gamma < 1.f) {
|
||||
return Powf((gamma + 0.111572195921731f) / 1.111572195921731f, 1.f / 0.45f);
|
||||
}
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
static float FromLinearSmpte240(float linear) {
|
||||
if (linear < 0.f) {
|
||||
return 0.f;
|
||||
} else if (linear < 0.022821585529445f) {
|
||||
return linear * 4.f;
|
||||
} else if (linear < 1.f) {
|
||||
return 1.111572195921731f * Powf(linear, 0.45f) - 0.111572195921731f;
|
||||
}
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
static float ToLinearLog100(float gamma) {
|
||||
// The function is non-bijective so choose the middle of [0, 0.01].
|
||||
const float mid_interval = 0.01f / 2.f;
|
||||
return (gamma <= 0.0f) ? mid_interval
|
||||
: Powf(10.0f, 2.f * (MIN(gamma, 1.f) - 1.0f));
|
||||
}
|
||||
|
||||
static float FromLinearLog100(float linear) {
|
||||
return (linear < 0.01f) ? 0.0f : 1.0f + Log10f(MIN(linear, 1.f)) / 2.0f;
|
||||
}
|
||||
|
||||
static float ToLinearLog100Sqrt10(float gamma) {
|
||||
// The function is non-bijective so choose the middle of [0, 0.00316227766f[.
|
||||
const float mid_interval = 0.00316227766f / 2.f;
|
||||
return (gamma <= 0.0f) ? mid_interval
|
||||
: Powf(10.0f, 2.5f * (MIN(gamma, 1.f) - 1.0f));
|
||||
}
|
||||
|
||||
static float FromLinearLog100Sqrt10(float linear) {
|
||||
return (linear < 0.00316227766f) ? 0.0f
|
||||
: 1.0f + Log10f(MIN(linear, 1.f)) / 2.5f;
|
||||
}
|
||||
|
||||
static float ToLinearIec61966(float gamma) {
|
||||
if (gamma <= -4.5f * 0.018053968510807f) {
|
||||
return Powf((-gamma + 0.09929682680944f) / -1.09929682680944f, 1.f / 0.45f);
|
||||
} else if (gamma < 4.5f * 0.018053968510807f) {
|
||||
return gamma / 4.5f;
|
||||
}
|
||||
return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f);
|
||||
}
|
||||
|
||||
static float FromLinearIec61966(float linear) {
|
||||
if (linear <= -0.018053968510807f) {
|
||||
return -1.09929682680944f * Powf(-linear, 0.45f) + 0.09929682680944f;
|
||||
} else if (linear < 0.018053968510807f) {
|
||||
return linear * 4.5f;
|
||||
}
|
||||
return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f;
|
||||
}
|
||||
|
||||
static float ToLinearBt1361(float gamma) {
|
||||
if (gamma < -0.25f) {
|
||||
return -0.25f;
|
||||
} else if (gamma < 0.f) {
|
||||
return Powf((gamma - 0.02482420670236f) / -0.27482420670236f, 1.f / 0.45f) /
|
||||
-4.f;
|
||||
} else if (gamma < 4.5f * 0.018053968510807f) {
|
||||
return gamma / 4.5f;
|
||||
} else if (gamma < 1.f) {
|
||||
return Powf((gamma + 0.09929682680944f) / 1.09929682680944f, 1.f / 0.45f);
|
||||
}
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
static float FromLinearBt1361(float linear) {
|
||||
if (linear < -0.25f) {
|
||||
return -0.25f;
|
||||
} else if (linear < 0.f) {
|
||||
return -0.27482420670236f * Powf(-4.f * linear, 0.45f) + 0.02482420670236f;
|
||||
} else if (linear < 0.018053968510807f) {
|
||||
return linear * 4.5f;
|
||||
} else if (linear < 1.f) {
|
||||
return 1.09929682680944f * Powf(linear, 0.45f) - 0.09929682680944f;
|
||||
}
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
static float ToLinearPq(float gamma) {
|
||||
if (gamma > 0.f) {
|
||||
const float pow_gamma = Powf(gamma, 32.f / 2523.f);
|
||||
const float num = MAX(pow_gamma - 107.f / 128.f, 0.0f);
|
||||
const float den = MAX(2413.f / 128.f - 2392.f / 128.f * pow_gamma, FLT_MIN);
|
||||
return Powf(num / den, 4096.f / 653.f);
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
static float FromLinearPq(float linear) {
|
||||
if (linear > 0.f) {
|
||||
const float pow_linear = Powf(linear, 653.f / 4096.f);
|
||||
const float num = 107.f / 128.f + 2413.f / 128.f * pow_linear;
|
||||
const float den = 1.0f + 2392.f / 128.f * pow_linear;
|
||||
return Powf(num / den, 2523.f / 32.f);
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
static float ToLinearSmpte428(float gamma) {
|
||||
return Powf(MAX(gamma, 0.f), 2.6f) / 0.91655527974030934f;
|
||||
}
|
||||
|
||||
static float FromLinearSmpte428(float linear) {
|
||||
return Powf(0.91655527974030934f * MAX(linear, 0.f), 1.f / 2.6f);
|
||||
}
|
||||
|
||||
// Conversion in BT.2100 requires RGB info. Simplify to gamma correction here.
|
||||
static float ToLinearHlg(float gamma) {
|
||||
if (gamma < 0.f) {
|
||||
return 0.f;
|
||||
} else if (gamma <= 0.5f) {
|
||||
return Powf((gamma * gamma) * (1.f / 3.f), 1.2f);
|
||||
}
|
||||
return Powf((expf((gamma - 0.55991073f) / 0.17883277f) + 0.28466892f) / 12.0f,
|
||||
1.2f);
|
||||
}
|
||||
|
||||
static float FromLinearHlg(float linear) {
|
||||
linear = Powf(linear, 1.f / 1.2f);
|
||||
if (linear < 0.f) {
|
||||
return 0.f;
|
||||
} else if (linear <= (1.f / 12.f)) {
|
||||
return sqrtf(3.f * linear);
|
||||
}
|
||||
return 0.17883277f * logf(12.f * linear - 0.28466892f) + 0.55991073f;
|
||||
}
|
||||
|
||||
uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth,
|
||||
SharpYuvTransferFunctionType transfer_type) {
|
||||
float v_float, linear;
|
||||
if (transfer_type == kSharpYuvTransferFunctionSrgb) {
|
||||
return ToLinearSrgb(v, bit_depth);
|
||||
}
|
||||
v_float = (float)v / ((1 << bit_depth) - 1);
|
||||
switch (transfer_type) {
|
||||
case kSharpYuvTransferFunctionBt709:
|
||||
case kSharpYuvTransferFunctionBt601:
|
||||
case kSharpYuvTransferFunctionBt2020_10Bit:
|
||||
case kSharpYuvTransferFunctionBt2020_12Bit:
|
||||
linear = ToLinear709(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionBt470M:
|
||||
linear = ToLinear470M(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionBt470Bg:
|
||||
linear = ToLinear470Bg(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionSmpte240:
|
||||
linear = ToLinearSmpte240(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionLinear:
|
||||
return v;
|
||||
case kSharpYuvTransferFunctionLog100:
|
||||
linear = ToLinearLog100(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionLog100_Sqrt10:
|
||||
linear = ToLinearLog100Sqrt10(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionIec61966:
|
||||
linear = ToLinearIec61966(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionBt1361:
|
||||
linear = ToLinearBt1361(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionSmpte2084:
|
||||
linear = ToLinearPq(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionSmpte428:
|
||||
linear = ToLinearSmpte428(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionHlg:
|
||||
linear = ToLinearHlg(v_float);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
linear = 0;
|
||||
break;
|
||||
}
|
||||
return (uint32_t)Roundf(linear * ((1 << 16) - 1));
|
||||
}
|
||||
|
||||
uint16_t SharpYuvLinearToGamma(uint32_t v, int bit_depth,
|
||||
SharpYuvTransferFunctionType transfer_type) {
|
||||
float v_float, linear;
|
||||
if (transfer_type == kSharpYuvTransferFunctionSrgb) {
|
||||
return FromLinearSrgb(v, bit_depth);
|
||||
}
|
||||
v_float = (float)v / ((1 << 16) - 1);
|
||||
switch (transfer_type) {
|
||||
case kSharpYuvTransferFunctionBt709:
|
||||
case kSharpYuvTransferFunctionBt601:
|
||||
case kSharpYuvTransferFunctionBt2020_10Bit:
|
||||
case kSharpYuvTransferFunctionBt2020_12Bit:
|
||||
linear = FromLinear709(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionBt470M:
|
||||
linear = FromLinear470M(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionBt470Bg:
|
||||
linear = FromLinear470Bg(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionSmpte240:
|
||||
linear = FromLinearSmpte240(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionLinear:
|
||||
return v;
|
||||
case kSharpYuvTransferFunctionLog100:
|
||||
linear = FromLinearLog100(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionLog100_Sqrt10:
|
||||
linear = FromLinearLog100Sqrt10(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionIec61966:
|
||||
linear = FromLinearIec61966(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionBt1361:
|
||||
linear = FromLinearBt1361(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionSmpte2084:
|
||||
linear = FromLinearPq(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionSmpte428:
|
||||
linear = FromLinearSmpte428(v_float);
|
||||
break;
|
||||
case kSharpYuvTransferFunctionHlg:
|
||||
linear = FromLinearHlg(v_float);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
linear = 0;
|
||||
break;
|
||||
}
|
||||
return (uint16_t)Roundf(linear * ((1 << bit_depth) - 1));
|
||||
}
|
38
sharpyuv/sharpyuv_gamma.h
Normal file
38
sharpyuv/sharpyuv_gamma.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Gamma correction utilities.
|
||||
|
||||
#ifndef WEBP_SHARPYUV_SHARPYUV_GAMMA_H_
|
||||
#define WEBP_SHARPYUV_SHARPYUV_GAMMA_H_
|
||||
|
||||
#include "sharpyuv/sharpyuv.h"
|
||||
#include "src/webp/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Initializes precomputed tables. Must be called once before calling
|
||||
// SharpYuvGammaToLinear or SharpYuvLinearToGamma.
|
||||
void SharpYuvInitGammaTables(void);
|
||||
|
||||
// Converts a 'bit_depth'-bit gamma color value to a 16-bit linear value.
|
||||
uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth,
|
||||
SharpYuvTransferFunctionType transfer_type);
|
||||
|
||||
// Converts a 16-bit linear color value to a 'bit_depth'-bit gamma value.
|
||||
uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth,
|
||||
SharpYuvTransferFunctionType transfer_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WEBP_SHARPYUV_SHARPYUV_GAMMA_H_
|
181
sharpyuv/sharpyuv_neon.c
Normal file
181
sharpyuv/sharpyuv_neon.c
Normal file
@ -0,0 +1,181 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Speed-critical functions for Sharp YUV.
|
||||
//
|
||||
// Author: Skal (pascal.massimino@gmail.com)
|
||||
|
||||
#include "sharpyuv/sharpyuv_dsp.h"
|
||||
|
||||
#if defined(WEBP_USE_NEON)
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <arm_neon.h>
|
||||
|
||||
static uint16_t clip_NEON(int v, int max) {
|
||||
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
|
||||
}
|
||||
|
||||
static uint64_t SharpYuvUpdateY_NEON(const uint16_t* ref, const uint16_t* src,
|
||||
uint16_t* dst, int len, int bit_depth) {
|
||||
const int max_y = (1 << bit_depth) - 1;
|
||||
int i;
|
||||
const int16x8_t zero = vdupq_n_s16(0);
|
||||
const int16x8_t max = vdupq_n_s16(max_y);
|
||||
uint64x2_t sum = vdupq_n_u64(0);
|
||||
uint64_t diff;
|
||||
|
||||
for (i = 0; i + 8 <= len; i += 8) {
|
||||
const int16x8_t A = vreinterpretq_s16_u16(vld1q_u16(ref + i));
|
||||
const int16x8_t B = vreinterpretq_s16_u16(vld1q_u16(src + i));
|
||||
const int16x8_t C = vreinterpretq_s16_u16(vld1q_u16(dst + i));
|
||||
const int16x8_t D = vsubq_s16(A, B); // diff_y
|
||||
const int16x8_t F = vaddq_s16(C, D); // new_y
|
||||
const uint16x8_t H =
|
||||
vreinterpretq_u16_s16(vmaxq_s16(vminq_s16(F, max), zero));
|
||||
const int16x8_t I = vabsq_s16(D); // abs(diff_y)
|
||||
vst1q_u16(dst + i, H);
|
||||
sum = vpadalq_u32(sum, vpaddlq_u16(vreinterpretq_u16_s16(I)));
|
||||
}
|
||||
diff = vgetq_lane_u64(sum, 0) + vgetq_lane_u64(sum, 1);
|
||||
for (; i < len; ++i) {
|
||||
const int diff_y = ref[i] - src[i];
|
||||
const int new_y = (int)(dst[i]) + diff_y;
|
||||
dst[i] = clip_NEON(new_y, max_y);
|
||||
diff += (uint64_t)(abs(diff_y));
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static void SharpYuvUpdateRGB_NEON(const int16_t* ref, const int16_t* src,
|
||||
int16_t* dst, int len) {
|
||||
int i;
|
||||
for (i = 0; i + 8 <= len; i += 8) {
|
||||
const int16x8_t A = vld1q_s16(ref + i);
|
||||
const int16x8_t B = vld1q_s16(src + i);
|
||||
const int16x8_t C = vld1q_s16(dst + i);
|
||||
const int16x8_t D = vsubq_s16(A, B); // diff_uv
|
||||
const int16x8_t E = vaddq_s16(C, D); // new_uv
|
||||
vst1q_s16(dst + i, E);
|
||||
}
|
||||
for (; i < len; ++i) {
|
||||
const int diff_uv = ref[i] - src[i];
|
||||
dst[i] += diff_uv;
|
||||
}
|
||||
}
|
||||
|
||||
static void SharpYuvFilterRow16_NEON(const int16_t* A, const int16_t* B,
|
||||
int len, const uint16_t* best_y,
|
||||
uint16_t* out, int bit_depth) {
|
||||
const int max_y = (1 << bit_depth) - 1;
|
||||
int i;
|
||||
const int16x8_t max = vdupq_n_s16(max_y);
|
||||
const int16x8_t zero = vdupq_n_s16(0);
|
||||
for (i = 0; i + 8 <= len; i += 8) {
|
||||
const int16x8_t a0 = vld1q_s16(A + i + 0);
|
||||
const int16x8_t a1 = vld1q_s16(A + i + 1);
|
||||
const int16x8_t b0 = vld1q_s16(B + i + 0);
|
||||
const int16x8_t b1 = vld1q_s16(B + i + 1);
|
||||
const int16x8_t a0b1 = vaddq_s16(a0, b1);
|
||||
const int16x8_t a1b0 = vaddq_s16(a1, b0);
|
||||
const int16x8_t a0a1b0b1 = vaddq_s16(a0b1, a1b0); // A0+A1+B0+B1
|
||||
const int16x8_t a0b1_2 = vaddq_s16(a0b1, a0b1); // 2*(A0+B1)
|
||||
const int16x8_t a1b0_2 = vaddq_s16(a1b0, a1b0); // 2*(A1+B0)
|
||||
const int16x8_t c0 = vshrq_n_s16(vaddq_s16(a0b1_2, a0a1b0b1), 3);
|
||||
const int16x8_t c1 = vshrq_n_s16(vaddq_s16(a1b0_2, a0a1b0b1), 3);
|
||||
const int16x8_t e0 = vrhaddq_s16(c1, a0);
|
||||
const int16x8_t e1 = vrhaddq_s16(c0, a1);
|
||||
const int16x8x2_t f = vzipq_s16(e0, e1);
|
||||
const int16x8_t g0 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 0));
|
||||
const int16x8_t g1 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 8));
|
||||
const int16x8_t h0 = vaddq_s16(g0, f.val[0]);
|
||||
const int16x8_t h1 = vaddq_s16(g1, f.val[1]);
|
||||
const int16x8_t i0 = vmaxq_s16(vminq_s16(h0, max), zero);
|
||||
const int16x8_t i1 = vmaxq_s16(vminq_s16(h1, max), zero);
|
||||
vst1q_u16(out + 2 * i + 0, vreinterpretq_u16_s16(i0));
|
||||
vst1q_u16(out + 2 * i + 8, vreinterpretq_u16_s16(i1));
|
||||
}
|
||||
for (; i < len; ++i) {
|
||||
const int a0b1 = A[i + 0] + B[i + 1];
|
||||
const int a1b0 = A[i + 1] + B[i + 0];
|
||||
const int a0a1b0b1 = a0b1 + a1b0 + 8;
|
||||
const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4;
|
||||
const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4;
|
||||
out[2 * i + 0] = clip_NEON(best_y[2 * i + 0] + v0, max_y);
|
||||
out[2 * i + 1] = clip_NEON(best_y[2 * i + 1] + v1, max_y);
|
||||
}
|
||||
}
|
||||
|
||||
static void SharpYuvFilterRow32_NEON(const int16_t* A, const int16_t* B,
|
||||
int len, const uint16_t* best_y,
|
||||
uint16_t* out, int bit_depth) {
|
||||
const int max_y = (1 << bit_depth) - 1;
|
||||
int i;
|
||||
const uint16x8_t max = vdupq_n_u16(max_y);
|
||||
for (i = 0; i + 4 <= len; i += 4) {
|
||||
const int16x4_t a0 = vld1_s16(A + i + 0);
|
||||
const int16x4_t a1 = vld1_s16(A + i + 1);
|
||||
const int16x4_t b0 = vld1_s16(B + i + 0);
|
||||
const int16x4_t b1 = vld1_s16(B + i + 1);
|
||||
const int32x4_t a0b1 = vaddl_s16(a0, b1);
|
||||
const int32x4_t a1b0 = vaddl_s16(a1, b0);
|
||||
const int32x4_t a0a1b0b1 = vaddq_s32(a0b1, a1b0); // A0+A1+B0+B1
|
||||
const int32x4_t a0b1_2 = vaddq_s32(a0b1, a0b1); // 2*(A0+B1)
|
||||
const int32x4_t a1b0_2 = vaddq_s32(a1b0, a1b0); // 2*(A1+B0)
|
||||
const int32x4_t c0 = vshrq_n_s32(vaddq_s32(a0b1_2, a0a1b0b1), 3);
|
||||
const int32x4_t c1 = vshrq_n_s32(vaddq_s32(a1b0_2, a0a1b0b1), 3);
|
||||
const int32x4_t e0 = vrhaddq_s32(c1, vmovl_s16(a0));
|
||||
const int32x4_t e1 = vrhaddq_s32(c0, vmovl_s16(a1));
|
||||
const int32x4x2_t f = vzipq_s32(e0, e1);
|
||||
|
||||
const int16x8_t g = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i));
|
||||
const int32x4_t h0 = vaddw_s16(f.val[0], vget_low_s16(g));
|
||||
const int32x4_t h1 = vaddw_s16(f.val[1], vget_high_s16(g));
|
||||
const uint16x8_t i_16 = vcombine_u16(vqmovun_s32(h0), vqmovun_s32(h1));
|
||||
const uint16x8_t i_clamped = vminq_u16(i_16, max);
|
||||
vst1q_u16(out + 2 * i + 0, i_clamped);
|
||||
}
|
||||
for (; i < len; ++i) {
|
||||
const int a0b1 = A[i + 0] + B[i + 1];
|
||||
const int a1b0 = A[i + 1] + B[i + 0];
|
||||
const int a0a1b0b1 = a0b1 + a1b0 + 8;
|
||||
const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4;
|
||||
const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4;
|
||||
out[2 * i + 0] = clip_NEON(best_y[2 * i + 0] + v0, max_y);
|
||||
out[2 * i + 1] = clip_NEON(best_y[2 * i + 1] + v1, max_y);
|
||||
}
|
||||
}
|
||||
|
||||
static void SharpYuvFilterRow_NEON(const int16_t* A, const int16_t* B, int len,
|
||||
const uint16_t* best_y, uint16_t* out,
|
||||
int bit_depth) {
|
||||
if (bit_depth <= 10) {
|
||||
SharpYuvFilterRow16_NEON(A, B, len, best_y, out, bit_depth);
|
||||
} else {
|
||||
SharpYuvFilterRow32_NEON(A, B, len, best_y, out, bit_depth);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
extern void InitSharpYuvNEON(void);
|
||||
|
||||
WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvNEON(void) {
|
||||
SharpYuvUpdateY = SharpYuvUpdateY_NEON;
|
||||
SharpYuvUpdateRGB = SharpYuvUpdateRGB_NEON;
|
||||
SharpYuvFilterRow = SharpYuvFilterRow_NEON;
|
||||
}
|
||||
|
||||
#else // !WEBP_USE_NEON
|
||||
|
||||
extern void InitSharpYuvNEON(void);
|
||||
|
||||
void InitSharpYuvNEON(void) {}
|
||||
|
||||
#endif // WEBP_USE_NEON
|
201
sharpyuv/sharpyuv_sse2.c
Normal file
201
sharpyuv/sharpyuv_sse2.c
Normal file
@ -0,0 +1,201 @@
|
||||
// Copyright 2022 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Speed-critical functions for Sharp YUV.
|
||||
//
|
||||
// Author: Skal (pascal.massimino@gmail.com)
|
||||
|
||||
#include "sharpyuv/sharpyuv_dsp.h"
|
||||
|
||||
#if defined(WEBP_USE_SSE2)
|
||||
#include <stdlib.h>
|
||||
#include <emmintrin.h>
|
||||
|
||||
static uint16_t clip_SSE2(int v, int max) {
|
||||
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
|
||||
}
|
||||
|
||||
static uint64_t SharpYuvUpdateY_SSE2(const uint16_t* ref, const uint16_t* src,
|
||||
uint16_t* dst, int len, int bit_depth) {
|
||||
const int max_y = (1 << bit_depth) - 1;
|
||||
uint64_t diff = 0;
|
||||
uint32_t tmp[4];
|
||||
int i;
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
const __m128i max = _mm_set1_epi16(max_y);
|
||||
const __m128i one = _mm_set1_epi16(1);
|
||||
__m128i sum = zero;
|
||||
|
||||
for (i = 0; i + 8 <= len; i += 8) {
|
||||
const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i));
|
||||
const __m128i B = _mm_loadu_si128((const __m128i*)(src + i));
|
||||
const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i));
|
||||
const __m128i D = _mm_sub_epi16(A, B); // diff_y
|
||||
const __m128i E = _mm_cmpgt_epi16(zero, D); // sign (-1 or 0)
|
||||
const __m128i F = _mm_add_epi16(C, D); // new_y
|
||||
const __m128i G = _mm_or_si128(E, one); // -1 or 1
|
||||
const __m128i H = _mm_max_epi16(_mm_min_epi16(F, max), zero);
|
||||
const __m128i I = _mm_madd_epi16(D, G); // sum(abs(...))
|
||||
_mm_storeu_si128((__m128i*)(dst + i), H);
|
||||
sum = _mm_add_epi32(sum, I);
|
||||
}
|
||||
_mm_storeu_si128((__m128i*)tmp, sum);
|
||||
diff = tmp[3] + tmp[2] + tmp[1] + tmp[0];
|
||||
for (; i < len; ++i) {
|
||||
const int diff_y = ref[i] - src[i];
|
||||
const int new_y = (int)dst[i] + diff_y;
|
||||
dst[i] = clip_SSE2(new_y, max_y);
|
||||
diff += (uint64_t)abs(diff_y);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
static void SharpYuvUpdateRGB_SSE2(const int16_t* ref, const int16_t* src,
|
||||
int16_t* dst, int len) {
|
||||
int i = 0;
|
||||
for (i = 0; i + 8 <= len; i += 8) {
|
||||
const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i));
|
||||
const __m128i B = _mm_loadu_si128((const __m128i*)(src + i));
|
||||
const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i));
|
||||
const __m128i D = _mm_sub_epi16(A, B); // diff_uv
|
||||
const __m128i E = _mm_add_epi16(C, D); // new_uv
|
||||
_mm_storeu_si128((__m128i*)(dst + i), E);
|
||||
}
|
||||
for (; i < len; ++i) {
|
||||
const int diff_uv = ref[i] - src[i];
|
||||
dst[i] += diff_uv;
|
||||
}
|
||||
}
|
||||
|
||||
static void SharpYuvFilterRow16_SSE2(const int16_t* A, const int16_t* B,
|
||||
int len, const uint16_t* best_y,
|
||||
uint16_t* out, int bit_depth) {
|
||||
const int max_y = (1 << bit_depth) - 1;
|
||||
int i;
|
||||
const __m128i kCst8 = _mm_set1_epi16(8);
|
||||
const __m128i max = _mm_set1_epi16(max_y);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
for (i = 0; i + 8 <= len; i += 8) {
|
||||
const __m128i a0 = _mm_loadu_si128((const __m128i*)(A + i + 0));
|
||||
const __m128i a1 = _mm_loadu_si128((const __m128i*)(A + i + 1));
|
||||
const __m128i b0 = _mm_loadu_si128((const __m128i*)(B + i + 0));
|
||||
const __m128i b1 = _mm_loadu_si128((const __m128i*)(B + i + 1));
|
||||
const __m128i a0b1 = _mm_add_epi16(a0, b1);
|
||||
const __m128i a1b0 = _mm_add_epi16(a1, b0);
|
||||
const __m128i a0a1b0b1 = _mm_add_epi16(a0b1, a1b0); // A0+A1+B0+B1
|
||||
const __m128i a0a1b0b1_8 = _mm_add_epi16(a0a1b0b1, kCst8);
|
||||
const __m128i a0b1_2 = _mm_add_epi16(a0b1, a0b1); // 2*(A0+B1)
|
||||
const __m128i a1b0_2 = _mm_add_epi16(a1b0, a1b0); // 2*(A1+B0)
|
||||
const __m128i c0 = _mm_srai_epi16(_mm_add_epi16(a0b1_2, a0a1b0b1_8), 3);
|
||||
const __m128i c1 = _mm_srai_epi16(_mm_add_epi16(a1b0_2, a0a1b0b1_8), 3);
|
||||
const __m128i d0 = _mm_add_epi16(c1, a0);
|
||||
const __m128i d1 = _mm_add_epi16(c0, a1);
|
||||
const __m128i e0 = _mm_srai_epi16(d0, 1);
|
||||
const __m128i e1 = _mm_srai_epi16(d1, 1);
|
||||
const __m128i f0 = _mm_unpacklo_epi16(e0, e1);
|
||||
const __m128i f1 = _mm_unpackhi_epi16(e0, e1);
|
||||
const __m128i g0 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 0));
|
||||
const __m128i g1 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 8));
|
||||
const __m128i h0 = _mm_add_epi16(g0, f0);
|
||||
const __m128i h1 = _mm_add_epi16(g1, f1);
|
||||
const __m128i i0 = _mm_max_epi16(_mm_min_epi16(h0, max), zero);
|
||||
const __m128i i1 = _mm_max_epi16(_mm_min_epi16(h1, max), zero);
|
||||
_mm_storeu_si128((__m128i*)(out + 2 * i + 0), i0);
|
||||
_mm_storeu_si128((__m128i*)(out + 2 * i + 8), i1);
|
||||
}
|
||||
for (; i < len; ++i) {
|
||||
// (9 * A0 + 3 * A1 + 3 * B0 + B1 + 8) >> 4 =
|
||||
// = (8 * A0 + 2 * (A1 + B0) + (A0 + A1 + B0 + B1 + 8)) >> 4
|
||||
// We reuse the common sub-expressions.
|
||||
const int a0b1 = A[i + 0] + B[i + 1];
|
||||
const int a1b0 = A[i + 1] + B[i + 0];
|
||||
const int a0a1b0b1 = a0b1 + a1b0 + 8;
|
||||
const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4;
|
||||
const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4;
|
||||
out[2 * i + 0] = clip_SSE2(best_y[2 * i + 0] + v0, max_y);
|
||||
out[2 * i + 1] = clip_SSE2(best_y[2 * i + 1] + v1, max_y);
|
||||
}
|
||||
}
|
||||
|
||||
static WEBP_INLINE __m128i s16_to_s32(__m128i in) {
|
||||
return _mm_srai_epi32(_mm_unpacklo_epi16(in, in), 16);
|
||||
}
|
||||
|
||||
static void SharpYuvFilterRow32_SSE2(const int16_t* A, const int16_t* B,
|
||||
int len, const uint16_t* best_y,
|
||||
uint16_t* out, int bit_depth) {
|
||||
const int max_y = (1 << bit_depth) - 1;
|
||||
int i;
|
||||
const __m128i kCst8 = _mm_set1_epi32(8);
|
||||
const __m128i max = _mm_set1_epi16(max_y);
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
for (i = 0; i + 4 <= len; i += 4) {
|
||||
const __m128i a0 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(A + i + 0)));
|
||||
const __m128i a1 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(A + i + 1)));
|
||||
const __m128i b0 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(B + i + 0)));
|
||||
const __m128i b1 = s16_to_s32(_mm_loadl_epi64((const __m128i*)(B + i + 1)));
|
||||
const __m128i a0b1 = _mm_add_epi32(a0, b1);
|
||||
const __m128i a1b0 = _mm_add_epi32(a1, b0);
|
||||
const __m128i a0a1b0b1 = _mm_add_epi32(a0b1, a1b0); // A0+A1+B0+B1
|
||||
const __m128i a0a1b0b1_8 = _mm_add_epi32(a0a1b0b1, kCst8);
|
||||
const __m128i a0b1_2 = _mm_add_epi32(a0b1, a0b1); // 2*(A0+B1)
|
||||
const __m128i a1b0_2 = _mm_add_epi32(a1b0, a1b0); // 2*(A1+B0)
|
||||
const __m128i c0 = _mm_srai_epi32(_mm_add_epi32(a0b1_2, a0a1b0b1_8), 3);
|
||||
const __m128i c1 = _mm_srai_epi32(_mm_add_epi32(a1b0_2, a0a1b0b1_8), 3);
|
||||
const __m128i d0 = _mm_add_epi32(c1, a0);
|
||||
const __m128i d1 = _mm_add_epi32(c0, a1);
|
||||
const __m128i e0 = _mm_srai_epi32(d0, 1);
|
||||
const __m128i e1 = _mm_srai_epi32(d1, 1);
|
||||
const __m128i f0 = _mm_unpacklo_epi32(e0, e1);
|
||||
const __m128i f1 = _mm_unpackhi_epi32(e0, e1);
|
||||
const __m128i g = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 0));
|
||||
const __m128i h_16 = _mm_add_epi16(g, _mm_packs_epi32(f0, f1));
|
||||
const __m128i final = _mm_max_epi16(_mm_min_epi16(h_16, max), zero);
|
||||
_mm_storeu_si128((__m128i*)(out + 2 * i + 0), final);
|
||||
}
|
||||
for (; i < len; ++i) {
|
||||
// (9 * A0 + 3 * A1 + 3 * B0 + B1 + 8) >> 4 =
|
||||
// = (8 * A0 + 2 * (A1 + B0) + (A0 + A1 + B0 + B1 + 8)) >> 4
|
||||
// We reuse the common sub-expressions.
|
||||
const int a0b1 = A[i + 0] + B[i + 1];
|
||||
const int a1b0 = A[i + 1] + B[i + 0];
|
||||
const int a0a1b0b1 = a0b1 + a1b0 + 8;
|
||||
const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4;
|
||||
const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4;
|
||||
out[2 * i + 0] = clip_SSE2(best_y[2 * i + 0] + v0, max_y);
|
||||
out[2 * i + 1] = clip_SSE2(best_y[2 * i + 1] + v1, max_y);
|
||||
}
|
||||
}
|
||||
|
||||
static void SharpYuvFilterRow_SSE2(const int16_t* A, const int16_t* B, int len,
|
||||
const uint16_t* best_y, uint16_t* out,
|
||||
int bit_depth) {
|
||||
if (bit_depth <= 10) {
|
||||
SharpYuvFilterRow16_SSE2(A, B, len, best_y, out, bit_depth);
|
||||
} else {
|
||||
SharpYuvFilterRow32_SSE2(A, B, len, best_y, out, bit_depth);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
extern void InitSharpYuvSSE2(void);
|
||||
|
||||
WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvSSE2(void) {
|
||||
SharpYuvUpdateY = SharpYuvUpdateY_SSE2;
|
||||
SharpYuvUpdateRGB = SharpYuvUpdateRGB_SSE2;
|
||||
SharpYuvFilterRow = SharpYuvFilterRow_SSE2;
|
||||
}
|
||||
#else // !WEBP_USE_SSE2
|
||||
|
||||
extern void InitSharpYuvSSE2(void);
|
||||
|
||||
void InitSharpYuvSSE2(void) {}
|
||||
|
||||
#endif // WEBP_USE_SSE2
|
@ -36,7 +36,7 @@ libwebp_la_LIBADD += utils/libwebputils.la
|
||||
# other than the ones listed on the command line, i.e., after linking, it will
|
||||
# not have unresolved symbols. Some platforms (Windows among them) require all
|
||||
# symbols in shared libraries to be resolved at library creation.
|
||||
libwebp_la_LDFLAGS = -no-undefined -version-info 8:3:1
|
||||
libwebp_la_LDFLAGS = -no-undefined -version-info 8:9:1
|
||||
libwebpincludedir = $(includedir)/webp
|
||||
pkgconfig_DATA = libwebp.pc
|
||||
|
||||
@ -48,7 +48,7 @@ if BUILD_LIBWEBPDECODER
|
||||
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
|
||||
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
||||
|
||||
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:3:1
|
||||
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:9:1
|
||||
pkgconfig_DATA += libwebpdecoder.pc
|
||||
endif
|
||||
|
||||
|
@ -13,18 +13,20 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "src/dec/alphai_dec.h"
|
||||
#include "src/dec/vp8_dec.h"
|
||||
#include "src/dec/vp8i_dec.h"
|
||||
#include "src/dec/vp8li_dec.h"
|
||||
#include "src/dsp/dsp.h"
|
||||
#include "src/utils/quant_levels_dec_utils.h"
|
||||
#include "src/utils/utils.h"
|
||||
#include "src/webp/format_constants.h"
|
||||
#include "src/webp/types.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// ALPHDecoder object.
|
||||
|
||||
// Allocates a new alpha decoder instance.
|
||||
static ALPHDecoder* ALPHNew(void) {
|
||||
WEBP_NODISCARD static ALPHDecoder* ALPHNew(void) {
|
||||
ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
|
||||
return dec;
|
||||
}
|
||||
@ -45,9 +47,9 @@ static void ALPHDelete(ALPHDecoder* const dec) {
|
||||
// header for alpha data stored using lossless compression.
|
||||
// Returns false in case of error in alpha header (data too short, invalid
|
||||
// compression method or filter, error in lossless header data etc).
|
||||
static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
|
||||
size_t data_size, const VP8Io* const src_io,
|
||||
uint8_t* output) {
|
||||
WEBP_NODISCARD static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
|
||||
size_t data_size, const VP8Io* const src_io,
|
||||
uint8_t* output) {
|
||||
int ok = 0;
|
||||
const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
|
||||
const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
|
||||
@ -79,7 +81,9 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
|
||||
}
|
||||
|
||||
// Copy the necessary parameters from src_io to io
|
||||
VP8InitIo(io);
|
||||
if (!VP8InitIo(io)) {
|
||||
return 0;
|
||||
}
|
||||
WebPInitCustomIo(NULL, io);
|
||||
io->opaque = dec;
|
||||
io->width = src_io->width;
|
||||
@ -107,7 +111,8 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
|
||||
// starting from row number 'row'. It assumes that rows up to (row - 1) have
|
||||
// already been decoded.
|
||||
// Returns false in case of bitstream error.
|
||||
static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
|
||||
WEBP_NODISCARD static int ALPHDecode(VP8Decoder* const dec, int row,
|
||||
int num_rows) {
|
||||
ALPHDecoder* const alph_dec = dec->alph_dec_;
|
||||
const int width = alph_dec->width_;
|
||||
const int height = alph_dec->io_.crop_bottom;
|
||||
@ -117,21 +122,12 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
|
||||
const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width;
|
||||
uint8_t* dst = dec->alpha_plane_ + row * width;
|
||||
assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]);
|
||||
if (alph_dec->filter_ != WEBP_FILTER_NONE) {
|
||||
assert(WebPUnfilters[alph_dec->filter_] != NULL);
|
||||
for (y = 0; y < num_rows; ++y) {
|
||||
WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width);
|
||||
prev_line = dst;
|
||||
dst += width;
|
||||
deltas += width;
|
||||
}
|
||||
} else {
|
||||
for (y = 0; y < num_rows; ++y) {
|
||||
memcpy(dst, deltas, width * sizeof(*dst));
|
||||
prev_line = dst;
|
||||
dst += width;
|
||||
deltas += width;
|
||||
}
|
||||
assert(WebPUnfilters[alph_dec->filter_] != NULL);
|
||||
for (y = 0; y < num_rows; ++y) {
|
||||
WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width);
|
||||
prev_line = dst;
|
||||
dst += width;
|
||||
deltas += width;
|
||||
}
|
||||
dec->alpha_prev_line_ = prev_line;
|
||||
} else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
|
||||
@ -147,7 +143,8 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) {
|
||||
WEBP_NODISCARD static int AllocateAlphaPlane(VP8Decoder* const dec,
|
||||
const VP8Io* const io) {
|
||||
const int stride = io->width;
|
||||
const int height = io->crop_bottom;
|
||||
const uint64_t alpha_size = (uint64_t)stride * height;
|
||||
@ -155,7 +152,8 @@ static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) {
|
||||
dec->alpha_plane_mem_ =
|
||||
(uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_));
|
||||
if (dec->alpha_plane_mem_ == NULL) {
|
||||
return 0;
|
||||
return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
|
||||
"Alpha decoder initialization failed.");
|
||||
}
|
||||
dec->alpha_plane_ = dec->alpha_plane_mem_;
|
||||
dec->alpha_prev_line_ = NULL;
|
||||
@ -174,9 +172,9 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec) {
|
||||
//------------------------------------------------------------------------------
|
||||
// Main entry point.
|
||||
|
||||
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
||||
const VP8Io* const io,
|
||||
int row, int num_rows) {
|
||||
WEBP_NODISCARD const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
||||
const VP8Io* const io,
|
||||
int row, int num_rows) {
|
||||
const int width = io->width;
|
||||
const int height = io->crop_bottom;
|
||||
|
||||
@ -189,10 +187,19 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
||||
if (!dec->is_alpha_decoded_) {
|
||||
if (dec->alph_dec_ == NULL) { // Initialize decoder.
|
||||
dec->alph_dec_ = ALPHNew();
|
||||
if (dec->alph_dec_ == NULL) return NULL;
|
||||
if (dec->alph_dec_ == NULL) {
|
||||
VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
|
||||
"Alpha decoder initialization failed.");
|
||||
return NULL;
|
||||
}
|
||||
if (!AllocateAlphaPlane(dec, io)) goto Error;
|
||||
if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
|
||||
io, dec->alpha_plane_)) {
|
||||
VP8LDecoder* const vp8l_dec = dec->alph_dec_->vp8l_dec_;
|
||||
VP8SetError(dec,
|
||||
(vp8l_dec == NULL) ? VP8_STATUS_OUT_OF_MEMORY
|
||||
: vp8l_dec->status_,
|
||||
"Alpha decoder initialization failed.");
|
||||
goto Error;
|
||||
}
|
||||
// if we allowed use of alpha dithering, check whether it's needed at all
|
||||
|
@ -75,7 +75,7 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
|
||||
const WebPRGBABuffer* const buf = &buffer->u.RGBA;
|
||||
const int stride = abs(buf->stride);
|
||||
const uint64_t size =
|
||||
MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride);
|
||||
MIN_BUFFER_SIZE((uint64_t)width * kModeBpp[mode], height, stride);
|
||||
ok &= (size <= buf->size);
|
||||
ok &= (stride >= width * kModeBpp[mode]);
|
||||
ok &= (buf->rgba != NULL);
|
||||
|
@ -17,8 +17,10 @@
|
||||
|
||||
#include "src/dec/alphai_dec.h"
|
||||
#include "src/dec/webpi_dec.h"
|
||||
#include "src/dec/vp8_dec.h"
|
||||
#include "src/dec/vp8i_dec.h"
|
||||
#include "src/utils/utils.h"
|
||||
#include "src/webp/decode.h"
|
||||
|
||||
// In append mode, buffer allocations increase as multiples of this value.
|
||||
// Needs to be a power of 2.
|
||||
@ -161,8 +163,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
|
||||
|
||||
// Appends data to the end of MemBuffer->buf_. It expands the allocated memory
|
||||
// size if required and also updates VP8BitReader's if new memory is allocated.
|
||||
static int AppendToMemBuffer(WebPIDecoder* const idec,
|
||||
const uint8_t* const data, size_t data_size) {
|
||||
WEBP_NODISCARD static int AppendToMemBuffer(WebPIDecoder* const idec,
|
||||
const uint8_t* const data,
|
||||
size_t data_size) {
|
||||
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
|
||||
MemBuffer* const mem = &idec->mem_;
|
||||
const int need_compressed_alpha = NeedCompressedAlpha(idec);
|
||||
@ -203,8 +206,9 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int RemapMemBuffer(WebPIDecoder* const idec,
|
||||
const uint8_t* const data, size_t data_size) {
|
||||
WEBP_NODISCARD static int RemapMemBuffer(WebPIDecoder* const idec,
|
||||
const uint8_t* const data,
|
||||
size_t data_size) {
|
||||
MemBuffer* const mem = &idec->mem_;
|
||||
const uint8_t* const old_buf = mem->buf_;
|
||||
const uint8_t* const old_start =
|
||||
@ -237,7 +241,8 @@ static void ClearMemBuffer(MemBuffer* const mem) {
|
||||
}
|
||||
}
|
||||
|
||||
static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) {
|
||||
WEBP_NODISCARD static int CheckMemBufferMode(MemBuffer* const mem,
|
||||
MemBufferMode expected) {
|
||||
if (mem->mode_ == MEM_MODE_NONE) {
|
||||
mem->mode_ = expected; // switch to the expected mode
|
||||
} else if (mem->mode_ != expected) {
|
||||
@ -248,7 +253,7 @@ static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) {
|
||||
}
|
||||
|
||||
// To be called last.
|
||||
static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) {
|
||||
WEBP_NODISCARD static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) {
|
||||
const WebPDecoderOptions* const options = idec->params_.options;
|
||||
WebPDecBuffer* const output = idec->params_.output;
|
||||
|
||||
@ -258,8 +263,10 @@ static VP8StatusCode FinishDecoding(WebPIDecoder* const idec) {
|
||||
if (status != VP8_STATUS_OK) return status;
|
||||
}
|
||||
if (idec->final_output_ != NULL) {
|
||||
WebPCopyDecBufferPixels(output, idec->final_output_); // do the slow-copy
|
||||
const VP8StatusCode status = WebPCopyDecBufferPixels(
|
||||
output, idec->final_output_); // do the slow-copy
|
||||
WebPFreeDecBuffer(&idec->output_);
|
||||
if (status != VP8_STATUS_OK) return status;
|
||||
*output = *idec->final_output_;
|
||||
idec->final_output_ = NULL;
|
||||
}
|
||||
@ -288,7 +295,7 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
|
||||
static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
|
||||
if (idec->state_ == STATE_VP8_DATA) {
|
||||
// Synchronize the thread, clean-up and check for errors.
|
||||
VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
|
||||
(void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
|
||||
}
|
||||
idec->state_ = STATE_ERROR;
|
||||
return error;
|
||||
@ -329,6 +336,7 @@ static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) {
|
||||
if (dec == NULL) {
|
||||
return VP8_STATUS_OUT_OF_MEMORY;
|
||||
}
|
||||
dec->incremental_ = 1;
|
||||
idec->dec_ = dec;
|
||||
dec->alpha_data_ = headers.alpha_data;
|
||||
dec->alpha_data_size_ = headers.alpha_data_size;
|
||||
@ -601,8 +609,9 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) {
|
||||
//------------------------------------------------------------------------------
|
||||
// Internal constructor
|
||||
|
||||
static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer,
|
||||
const WebPBitstreamFeatures* const features) {
|
||||
WEBP_NODISCARD static WebPIDecoder* NewDecoder(
|
||||
WebPDecBuffer* const output_buffer,
|
||||
const WebPBitstreamFeatures* const features) {
|
||||
WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec));
|
||||
if (idec == NULL) {
|
||||
return NULL;
|
||||
@ -614,8 +623,10 @@ static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer,
|
||||
idec->last_mb_y_ = -1;
|
||||
|
||||
InitMemBuffer(&idec->mem_);
|
||||
WebPInitDecBuffer(&idec->output_);
|
||||
VP8InitIo(&idec->io_);
|
||||
if (!WebPInitDecBuffer(&idec->output_) || !VP8InitIo(&idec->io_)) {
|
||||
WebPSafeFree(idec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WebPResetDecParams(&idec->params_);
|
||||
if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) {
|
||||
@ -674,7 +685,8 @@ void WebPIDelete(WebPIDecoder* idec) {
|
||||
if (!idec->is_lossless_) {
|
||||
if (idec->state_ == STATE_VP8_DATA) {
|
||||
// Synchronize the thread, clean-up and check for errors.
|
||||
VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
|
||||
// TODO(vrabaud) do we care about the return result?
|
||||
(void)VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_);
|
||||
}
|
||||
VP8Delete((VP8Decoder*)idec->dec_);
|
||||
} else {
|
||||
@ -851,8 +863,8 @@ const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec,
|
||||
return src;
|
||||
}
|
||||
|
||||
uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
|
||||
int* width, int* height, int* stride) {
|
||||
WEBP_NODISCARD uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
|
||||
int* width, int* height, int* stride) {
|
||||
const WebPDecBuffer* const src = GetOutputBuffer(idec);
|
||||
if (src == NULL) return NULL;
|
||||
if (src->colorspace >= MODE_YUV) {
|
||||
@ -867,10 +879,10 @@ uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
|
||||
return src->u.RGBA.rgba;
|
||||
}
|
||||
|
||||
uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y,
|
||||
uint8_t** u, uint8_t** v, uint8_t** a,
|
||||
int* width, int* height,
|
||||
int* stride, int* uv_stride, int* a_stride) {
|
||||
WEBP_NODISCARD uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y,
|
||||
uint8_t** u, uint8_t** v, uint8_t** a,
|
||||
int* width, int* height, int* stride,
|
||||
int* uv_stride, int* a_stride) {
|
||||
const WebPDecBuffer* const src = GetOutputBuffer(idec);
|
||||
if (src == NULL) return NULL;
|
||||
if (src->colorspace < MODE_YUV) {
|
||||
|
@ -12,10 +12,12 @@
|
||||
// Author: Skal (pascal.massimino@gmail.com)
|
||||
|
||||
#include "src/dec/vp8i_dec.h"
|
||||
#include "src/dsp/cpu.h"
|
||||
#include "src/utils/bit_reader_inl_utils.h"
|
||||
|
||||
#if !defined(USE_GENERIC_TREE)
|
||||
#if !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__)
|
||||
#if !defined(__arm__) && !defined(_M_ARM) && !WEBP_AARCH64 && \
|
||||
!defined(__wasm__)
|
||||
// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then.
|
||||
#define USE_GENERIC_TREE 1 // ALTERNATE_CODE
|
||||
#else
|
||||
|
@ -86,6 +86,8 @@ void VP8Delete(VP8Decoder* const dec) {
|
||||
|
||||
int VP8SetError(VP8Decoder* const dec,
|
||||
VP8StatusCode error, const char* const msg) {
|
||||
// VP8_STATUS_SUSPENDED is only meaningful in incremental decoding.
|
||||
assert(dec->incremental_ || error != VP8_STATUS_SUSPENDED);
|
||||
// The oldest error reported takes precedence over the new one.
|
||||
if (dec->status_ == VP8_STATUS_OK) {
|
||||
dec->status_ = error;
|
||||
@ -190,12 +192,12 @@ static int ParseSegmentHeader(VP8BitReader* br,
|
||||
}
|
||||
|
||||
// Paragraph 9.5
|
||||
// This function returns VP8_STATUS_SUSPENDED if we don't have all the
|
||||
// necessary data in 'buf'.
|
||||
// This case is not necessarily an error (for incremental decoding).
|
||||
// Still, no bitreader is ever initialized to make it possible to read
|
||||
// unavailable memory.
|
||||
// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA
|
||||
// If we don't have all the necessary data in 'buf', this function returns
|
||||
// VP8_STATUS_SUSPENDED in incremental decoding, VP8_STATUS_NOT_ENOUGH_DATA
|
||||
// otherwise.
|
||||
// In incremental decoding, this case is not necessarily an error. Still, no
|
||||
// bitreader is ever initialized to make it possible to read unavailable memory.
|
||||
// If we don't even have the partitions' sizes, then VP8_STATUS_NOT_ENOUGH_DATA
|
||||
// is returned, and this is an unrecoverable error.
|
||||
// If the partitions were positioned ok, VP8_STATUS_OK is returned.
|
||||
static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
|
||||
@ -225,8 +227,10 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
|
||||
sz += 3;
|
||||
}
|
||||
VP8InitBitReader(dec->parts_ + last_part, part_start, size_left);
|
||||
return (part_start < buf_end) ? VP8_STATUS_OK :
|
||||
VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data
|
||||
if (part_start < buf_end) return VP8_STATUS_OK;
|
||||
return dec->incremental_
|
||||
? VP8_STATUS_SUSPENDED // Init is ok, but there's not enough data
|
||||
: VP8_STATUS_NOT_ENOUGH_DATA;
|
||||
}
|
||||
|
||||
// Paragraph 9.4
|
||||
@ -494,6 +498,8 @@ static int GetCoeffsAlt(VP8BitReader* const br,
|
||||
return 16;
|
||||
}
|
||||
|
||||
extern VP8CPUInfo VP8GetCPUInfo;
|
||||
|
||||
WEBP_DSP_INIT_FUNC(InitGetCoeffs) {
|
||||
if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
|
||||
GetCoeffs = GetCoeffsAlt;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define WEBP_DEC_VP8_DEC_H_
|
||||
|
||||
#include "src/webp/decode.h"
|
||||
#include "src/webp/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -108,16 +109,14 @@ struct VP8Io {
|
||||
};
|
||||
|
||||
// Internal, version-checked, entry point
|
||||
int VP8InitIoInternal(VP8Io* const, int);
|
||||
WEBP_NODISCARD int VP8InitIoInternal(VP8Io* const, int);
|
||||
|
||||
// Set the custom IO function pointers and user-data. The setter for IO hooks
|
||||
// should be called before initiating incremental decoding. Returns true if
|
||||
// WebPIDecoder object is successfully modified, false otherwise.
|
||||
int WebPISetIOHooks(WebPIDecoder* const idec,
|
||||
VP8IoPutHook put,
|
||||
VP8IoSetupHook setup,
|
||||
VP8IoTeardownHook teardown,
|
||||
void* user_data);
|
||||
WEBP_NODISCARD int WebPISetIOHooks(WebPIDecoder* const idec, VP8IoPutHook put,
|
||||
VP8IoSetupHook setup,
|
||||
VP8IoTeardownHook teardown, void* user_data);
|
||||
|
||||
// Main decoding object. This is an opaque structure.
|
||||
typedef struct VP8Decoder VP8Decoder;
|
||||
@ -128,17 +127,17 @@ VP8Decoder* VP8New(void);
|
||||
// Must be called to make sure 'io' is initialized properly.
|
||||
// Returns false in case of version mismatch. Upon such failure, no other
|
||||
// decoding function should be called (VP8Decode, VP8GetHeaders, ...)
|
||||
static WEBP_INLINE int VP8InitIo(VP8Io* const io) {
|
||||
WEBP_NODISCARD static WEBP_INLINE int VP8InitIo(VP8Io* const io) {
|
||||
return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION);
|
||||
}
|
||||
|
||||
// Decode the VP8 frame header. Returns true if ok.
|
||||
// Note: 'io->data' must be pointing to the start of the VP8 frame header.
|
||||
int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io);
|
||||
WEBP_NODISCARD int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io);
|
||||
|
||||
// Decode a picture. Will call VP8GetHeaders() if it wasn't done already.
|
||||
// Returns false in case of error.
|
||||
int VP8Decode(VP8Decoder* const dec, VP8Io* const io);
|
||||
WEBP_NODISCARD int VP8Decode(VP8Decoder* const dec, VP8Io* const io);
|
||||
|
||||
// Return current status of the decoder:
|
||||
VP8StatusCode VP8Status(VP8Decoder* const dec);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "src/utils/random_utils.h"
|
||||
#include "src/utils/thread_utils.h"
|
||||
#include "src/dsp/dsp.h"
|
||||
#include "src/webp/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -31,8 +32,8 @@ extern "C" {
|
||||
|
||||
// version numbers
|
||||
#define DEC_MAJ_VERSION 1
|
||||
#define DEC_MIN_VERSION 2
|
||||
#define DEC_REV_VERSION 2
|
||||
#define DEC_MIN_VERSION 4
|
||||
#define DEC_REV_VERSION 0
|
||||
|
||||
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
|
||||
// Constraints are: We need to store one 16x16 block of luma samples (y),
|
||||
@ -186,6 +187,7 @@ struct VP8Decoder {
|
||||
|
||||
// Main data source
|
||||
VP8BitReader br_;
|
||||
int incremental_; // if true, incremental decoding is expected
|
||||
|
||||
// headers
|
||||
VP8FrameHeader frm_hdr_;
|
||||
@ -281,7 +283,7 @@ int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec);
|
||||
void VP8ParseQuant(VP8Decoder* const dec);
|
||||
|
||||
// in frame.c
|
||||
int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io);
|
||||
WEBP_NODISCARD int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io);
|
||||
// Call io->setup() and finish setting up scan parameters.
|
||||
// After this call returns, one must always call VP8ExitCritical() with the
|
||||
// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK
|
||||
@ -289,7 +291,7 @@ int VP8InitFrame(VP8Decoder* const dec, VP8Io* const io);
|
||||
VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io);
|
||||
// Must always be called in pair with VP8EnterCritical().
|
||||
// Returns false in case of error.
|
||||
int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
|
||||
WEBP_NODISCARD int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
|
||||
// Return the multi-threading method to use (0=off), depending
|
||||
// on options and bitstream size. Only for lossy decoding.
|
||||
int VP8GetThreadMethod(const WebPDecoderOptions* const options,
|
||||
@ -299,11 +301,12 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options,
|
||||
void VP8InitDithering(const WebPDecoderOptions* const options,
|
||||
VP8Decoder* const dec);
|
||||
// Process the last decoded row (filtering + output).
|
||||
int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io);
|
||||
WEBP_NODISCARD int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io);
|
||||
// To be called at the start of a new scanline, to initialize predictors.
|
||||
void VP8InitScanline(VP8Decoder* const dec);
|
||||
// Decode one macroblock. Returns false if there is not enough data.
|
||||
int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br);
|
||||
WEBP_NODISCARD int VP8DecodeMB(VP8Decoder* const dec,
|
||||
VP8BitReader* const token_br);
|
||||
|
||||
// in alpha.c
|
||||
const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
||||
|
@ -12,6 +12,7 @@
|
||||
// Authors: Vikas Arora (vikaas.arora@gmail.com)
|
||||
// Jyrki Alakuijala (jyrki@google.com)
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "src/dec/alphai_dec.h"
|
||||
@ -19,10 +20,9 @@
|
||||
#include "src/dsp/dsp.h"
|
||||
#include "src/dsp/lossless.h"
|
||||
#include "src/dsp/lossless_common.h"
|
||||
#include "src/dsp/yuv.h"
|
||||
#include "src/utils/endian_inl_utils.h"
|
||||
#include "src/utils/huffman_utils.h"
|
||||
#include "src/utils/utils.h"
|
||||
#include "src/webp/format_constants.h"
|
||||
|
||||
#define NUM_ARGB_CACHE_ROWS 16
|
||||
|
||||
@ -101,6 +101,14 @@ static const uint16_t kTableSize[12] = {
|
||||
FIXED_TABLE_SIZE + 2704
|
||||
};
|
||||
|
||||
static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) {
|
||||
// The oldest error reported takes precedence over the new one.
|
||||
if (dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED) {
|
||||
dec->status_ = error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DecodeImageStream(int xsize, int ysize,
|
||||
int is_level0,
|
||||
VP8LDecoder* const dec,
|
||||
@ -178,7 +186,7 @@ static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Decodes the next Huffman code from bit-stream.
|
||||
// FillBitWindow(br) needs to be called at minimum every second call
|
||||
// VP8LFillBitWindow(br) needs to be called at minimum every second call
|
||||
// to ReadSymbol, in order to pre-fetch enough bits.
|
||||
static WEBP_INLINE int ReadSymbol(const HuffmanCode* table,
|
||||
VP8LBitReader* const br) {
|
||||
@ -253,11 +261,11 @@ static int ReadHuffmanCodeLengths(
|
||||
int symbol;
|
||||
int max_symbol;
|
||||
int prev_code_len = DEFAULT_CODE_LENGTH;
|
||||
HuffmanCode table[1 << LENGTHS_TABLE_BITS];
|
||||
HuffmanTables tables;
|
||||
|
||||
if (!VP8LBuildHuffmanTable(table, LENGTHS_TABLE_BITS,
|
||||
code_length_code_lengths,
|
||||
NUM_CODE_LENGTH_CODES)) {
|
||||
if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||
|
||||
!VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,
|
||||
code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {
|
||||
goto End;
|
||||
}
|
||||
|
||||
@ -277,7 +285,7 @@ static int ReadHuffmanCodeLengths(
|
||||
int code_len;
|
||||
if (max_symbol-- == 0) break;
|
||||
VP8LFillBitWindow(br);
|
||||
p = &table[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
|
||||
p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
|
||||
VP8LSetBitPos(br, br->bit_pos_ + p->bits);
|
||||
code_len = p->value;
|
||||
if (code_len < kCodeLengthLiterals) {
|
||||
@ -300,14 +308,16 @@ static int ReadHuffmanCodeLengths(
|
||||
ok = 1;
|
||||
|
||||
End:
|
||||
if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
VP8LHuffmanTablesDeallocate(&tables);
|
||||
if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
|
||||
// tree.
|
||||
static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
|
||||
int* const code_lengths, HuffmanCode* const table) {
|
||||
int* const code_lengths,
|
||||
HuffmanTables* const table) {
|
||||
int ok = 0;
|
||||
int size = 0;
|
||||
VP8LBitReader* const br = &dec->br_;
|
||||
@ -321,7 +331,7 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
|
||||
// The first code is either 1 bit or 8 bit code.
|
||||
int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
|
||||
code_lengths[symbol] = 1;
|
||||
// The second code (if present), is always 8 bit long.
|
||||
// The second code (if present), is always 8 bits long.
|
||||
if (num_symbols == 2) {
|
||||
symbol = VP8LReadBits(br, 8);
|
||||
code_lengths[symbol] = 1;
|
||||
@ -331,10 +341,7 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
|
||||
int i;
|
||||
int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
|
||||
const int num_codes = VP8LReadBits(br, 4) + 4;
|
||||
if (num_codes > NUM_CODE_LENGTH_CODES) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
assert(num_codes <= NUM_CODE_LENGTH_CODES);
|
||||
|
||||
for (i = 0; i < num_codes; ++i) {
|
||||
code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
|
||||
@ -349,36 +356,36 @@ static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
|
||||
code_lengths, alphabet_size);
|
||||
}
|
||||
if (!ok || size == 0) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
return 0;
|
||||
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
int color_cache_bits, int allow_recursion) {
|
||||
int i, j;
|
||||
int i;
|
||||
VP8LBitReader* const br = &dec->br_;
|
||||
VP8LMetadata* const hdr = &dec->hdr_;
|
||||
uint32_t* huffman_image = NULL;
|
||||
HTreeGroup* htree_groups = NULL;
|
||||
HuffmanCode* huffman_tables = NULL;
|
||||
HuffmanCode* huffman_table = NULL;
|
||||
HuffmanTables* huffman_tables = &hdr->huffman_tables_;
|
||||
int num_htree_groups = 1;
|
||||
int num_htree_groups_max = 1;
|
||||
int max_alphabet_size = 0;
|
||||
int* code_lengths = NULL;
|
||||
const int table_size = kTableSize[color_cache_bits];
|
||||
int* mapping = NULL;
|
||||
int ok = 0;
|
||||
|
||||
// Check the table has been 0 initialized (through InitMetadata).
|
||||
assert(huffman_tables->root.start == NULL);
|
||||
assert(huffman_tables->curr_segment == NULL);
|
||||
|
||||
if (allow_recursion && VP8LReadBits(br, 1)) {
|
||||
// use meta Huffman codes.
|
||||
const int huffman_precision = VP8LReadBits(br, 3) + 2;
|
||||
const int huffman_precision =
|
||||
MIN_HUFFMAN_BITS + VP8LReadBits(br, NUM_HUFFMAN_BITS);
|
||||
const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
|
||||
const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
|
||||
const int huffman_pixs = huffman_xsize * huffman_ysize;
|
||||
if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
|
||||
if (!DecodeImageStream(huffman_xsize, huffman_ysize, /*is_level0=*/0, dec,
|
||||
&huffman_image)) {
|
||||
goto Error;
|
||||
}
|
||||
@ -402,7 +409,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
// values [0, num_htree_groups)
|
||||
mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));
|
||||
if (mapping == NULL) {
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
|
||||
goto Error;
|
||||
}
|
||||
// -1 means a value is unmapped, and therefore unused in the Huffman
|
||||
@ -421,29 +428,55 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
|
||||
if (br->eos_) goto Error;
|
||||
|
||||
// Find maximum alphabet size for the htree group.
|
||||
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
|
||||
int alphabet_size = kAlphabetSize[j];
|
||||
if (j == 0 && color_cache_bits > 0) {
|
||||
alphabet_size += 1 << color_cache_bits;
|
||||
}
|
||||
if (max_alphabet_size < alphabet_size) {
|
||||
max_alphabet_size = alphabet_size;
|
||||
}
|
||||
if (!ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups,
|
||||
num_htree_groups_max, mapping, dec,
|
||||
huffman_tables, &htree_groups)) {
|
||||
goto Error;
|
||||
}
|
||||
ok = 1;
|
||||
|
||||
code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
|
||||
sizeof(*code_lengths));
|
||||
huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
|
||||
sizeof(*huffman_tables));
|
||||
htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
|
||||
// All OK. Finalize pointers.
|
||||
hdr->huffman_image_ = huffman_image;
|
||||
hdr->num_htree_groups_ = num_htree_groups;
|
||||
hdr->htree_groups_ = htree_groups;
|
||||
|
||||
if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
Error:
|
||||
WebPSafeFree(mapping);
|
||||
if (!ok) {
|
||||
WebPSafeFree(huffman_image);
|
||||
VP8LHuffmanTablesDeallocate(huffman_tables);
|
||||
VP8LHtreeGroupsFree(htree_groups);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups,
|
||||
int num_htree_groups_max, const int* const mapping,
|
||||
VP8LDecoder* const dec,
|
||||
HuffmanTables* const huffman_tables,
|
||||
HTreeGroup** const htree_groups) {
|
||||
int i, j, ok = 0;
|
||||
const int max_alphabet_size =
|
||||
kAlphabetSize[0] + ((color_cache_bits > 0) ? 1 << color_cache_bits : 0);
|
||||
const int table_size = kTableSize[color_cache_bits];
|
||||
int* code_lengths = NULL;
|
||||
|
||||
if ((mapping == NULL && num_htree_groups != num_htree_groups_max) ||
|
||||
num_htree_groups > num_htree_groups_max) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
code_lengths =
|
||||
(int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths));
|
||||
*htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
|
||||
|
||||
if (*htree_groups == NULL || code_lengths == NULL ||
|
||||
!VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
|
||||
huffman_tables)) {
|
||||
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
|
||||
goto Error;
|
||||
}
|
||||
|
||||
huffman_table = huffman_tables;
|
||||
for (i = 0; i < num_htree_groups_max; ++i) {
|
||||
// If the index "i" is unused in the Huffman image, just make sure the
|
||||
// coefficients are valid but do not store them.
|
||||
@ -460,7 +493,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
}
|
||||
} else {
|
||||
HTreeGroup* const htree_group =
|
||||
&htree_groups[(mapping == NULL) ? i : mapping[i]];
|
||||
&(*htree_groups)[(mapping == NULL) ? i : mapping[i]];
|
||||
HuffmanCode** const htrees = htree_group->htrees;
|
||||
int size;
|
||||
int total_size = 0;
|
||||
@ -468,19 +501,20 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
int max_bits = 0;
|
||||
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
|
||||
int alphabet_size = kAlphabetSize[j];
|
||||
htrees[j] = huffman_table;
|
||||
if (j == 0 && color_cache_bits > 0) {
|
||||
alphabet_size += (1 << color_cache_bits);
|
||||
}
|
||||
size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table);
|
||||
size =
|
||||
ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
|
||||
htrees[j] = huffman_tables->curr_segment->curr_table;
|
||||
if (size == 0) {
|
||||
goto Error;
|
||||
}
|
||||
if (is_trivial_literal && kLiteralMap[j] == 1) {
|
||||
is_trivial_literal = (huffman_table->bits == 0);
|
||||
is_trivial_literal = (htrees[j]->bits == 0);
|
||||
}
|
||||
total_size += huffman_table->bits;
|
||||
huffman_table += size;
|
||||
total_size += htrees[j]->bits;
|
||||
huffman_tables->curr_segment->curr_table += size;
|
||||
if (j <= ALPHA) {
|
||||
int local_max_bits = code_lengths[0];
|
||||
int k;
|
||||
@ -511,19 +545,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
}
|
||||
ok = 1;
|
||||
|
||||
// All OK. Finalize pointers.
|
||||
hdr->huffman_image_ = huffman_image;
|
||||
hdr->num_htree_groups_ = num_htree_groups;
|
||||
hdr->htree_groups_ = htree_groups;
|
||||
hdr->huffman_tables_ = huffman_tables;
|
||||
|
||||
Error:
|
||||
WebPSafeFree(code_lengths);
|
||||
WebPSafeFree(mapping);
|
||||
if (!ok) {
|
||||
WebPSafeFree(huffman_image);
|
||||
WebPSafeFree(huffman_tables);
|
||||
VP8LHtreeGroupsFree(htree_groups);
|
||||
VP8LHuffmanTablesDeallocate(huffman_tables);
|
||||
VP8LHtreeGroupsFree(*htree_groups);
|
||||
*htree_groups = NULL;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
@ -547,8 +574,7 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
|
||||
scaled_data_size * sizeof(*scaled_data);
|
||||
uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory));
|
||||
if (memory == NULL) {
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
|
||||
}
|
||||
assert(dec->rescaler_memory == NULL);
|
||||
dec->rescaler_memory = memory;
|
||||
@ -1082,12 +1108,10 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
|
||||
End:
|
||||
br->eos_ = VP8LIsEndOfStream(br);
|
||||
if (!ok || (br->eos_ && pos < end)) {
|
||||
ok = 0;
|
||||
dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
|
||||
: VP8_STATUS_BITSTREAM_ERROR;
|
||||
} else {
|
||||
dec->last_pixel_ = pos;
|
||||
return VP8LSetError(
|
||||
dec, br->eos_ ? VP8_STATUS_SUSPENDED : VP8_STATUS_BITSTREAM_ERROR);
|
||||
}
|
||||
dec->last_pixel_ = pos;
|
||||
return ok;
|
||||
}
|
||||
|
||||
@ -1237,9 +1261,20 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
|
||||
}
|
||||
|
||||
br->eos_ = VP8LIsEndOfStream(br);
|
||||
if (dec->incremental_ && br->eos_ && src < src_end) {
|
||||
// In incremental decoding:
|
||||
// br->eos_ && src < src_last: if 'br' reached the end of the buffer and
|
||||
// 'src_last' has not been reached yet, there is not enough data. 'dec' has to
|
||||
// be reset until there is more data.
|
||||
// !br->eos_ && src < src_last: this cannot happen as either the buffer is
|
||||
// fully read, either enough has been read to reach 'src_last'.
|
||||
// src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go
|
||||
// beyond 'src_last' in case the image is cropped and an LZ77 goes further.
|
||||
// The buffer might have been enough or there is some left. 'br->eos_' does
|
||||
// not matter.
|
||||
assert(!dec->incremental_ || (br->eos_ && src < src_last) || src >= src_last);
|
||||
if (dec->incremental_ && br->eos_ && src < src_last) {
|
||||
RestoreState(dec);
|
||||
} else if (!br->eos_) {
|
||||
} else if ((dec->incremental_ && src >= src_last) || !br->eos_) {
|
||||
// Process the remaining rows corresponding to last row-block.
|
||||
if (process_func != NULL) {
|
||||
process_func(dec, row > last_row ? last_row : row);
|
||||
@ -1254,8 +1289,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
|
||||
return 1;
|
||||
|
||||
Error:
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
return 0;
|
||||
return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -1281,7 +1315,7 @@ static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
|
||||
uint8_t* const new_data = (uint8_t*)new_color_map;
|
||||
new_color_map[0] = transform->data_[0];
|
||||
for (i = 4; i < 4 * num_colors; ++i) {
|
||||
// Equivalent to AddPixelEq(), on a byte-basis.
|
||||
// Equivalent to VP8LAddPixels(), on a byte-basis.
|
||||
new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
|
||||
}
|
||||
for (; i < 4 * final_num_colors; ++i) {
|
||||
@ -1317,12 +1351,13 @@ static int ReadTransform(int* const xsize, int const* ysize,
|
||||
switch (type) {
|
||||
case PREDICTOR_TRANSFORM:
|
||||
case CROSS_COLOR_TRANSFORM:
|
||||
transform->bits_ = VP8LReadBits(br, 3) + 2;
|
||||
transform->bits_ =
|
||||
MIN_TRANSFORM_BITS + VP8LReadBits(br, NUM_TRANSFORM_BITS);
|
||||
ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
|
||||
transform->bits_),
|
||||
VP8LSubSampleSize(transform->ysize_,
|
||||
transform->bits_),
|
||||
0, dec, &transform->data_);
|
||||
/*is_level0=*/0, dec, &transform->data_);
|
||||
break;
|
||||
case COLOR_INDEXING_TRANSFORM: {
|
||||
const int num_colors = VP8LReadBits(br, 8) + 1;
|
||||
@ -1332,11 +1367,14 @@ static int ReadTransform(int* const xsize, int const* ysize,
|
||||
: 3;
|
||||
*xsize = VP8LSubSampleSize(transform->xsize_, bits);
|
||||
transform->bits_ = bits;
|
||||
ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_);
|
||||
ok = ok && ExpandColorMap(num_colors, transform);
|
||||
ok = DecodeImageStream(num_colors, /*ysize=*/1, /*is_level0=*/0, dec,
|
||||
&transform->data_);
|
||||
if (ok && !ExpandColorMap(num_colors, transform)) {
|
||||
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SUBTRACT_GREEN:
|
||||
case SUBTRACT_GREEN_TRANSFORM:
|
||||
break;
|
||||
default:
|
||||
assert(0); // can't happen
|
||||
@ -1358,7 +1396,7 @@ static void ClearMetadata(VP8LMetadata* const hdr) {
|
||||
assert(hdr != NULL);
|
||||
|
||||
WebPSafeFree(hdr->huffman_image_);
|
||||
WebPSafeFree(hdr->huffman_tables_);
|
||||
VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);
|
||||
VP8LHtreeGroupsFree(hdr->htree_groups_);
|
||||
VP8LColorCacheClear(&hdr->color_cache_);
|
||||
VP8LColorCacheClear(&hdr->saved_color_cache_);
|
||||
@ -1379,7 +1417,9 @@ VP8LDecoder* VP8LNew(void) {
|
||||
return dec;
|
||||
}
|
||||
|
||||
void VP8LClear(VP8LDecoder* const dec) {
|
||||
// Resets the decoder in its initial state, reclaiming memory.
|
||||
// Preserves the dec->status_ value.
|
||||
static void VP8LClear(VP8LDecoder* const dec) {
|
||||
int i;
|
||||
if (dec == NULL) return;
|
||||
ClearMetadata(&dec->hdr_);
|
||||
@ -1439,7 +1479,7 @@ static int DecodeImageStream(int xsize, int ysize,
|
||||
color_cache_bits = VP8LReadBits(br, 4);
|
||||
ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
|
||||
if (!ok) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
@ -1448,7 +1488,7 @@ static int DecodeImageStream(int xsize, int ysize,
|
||||
ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
|
||||
color_cache_bits, is_level0);
|
||||
if (!ok) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
||||
goto End;
|
||||
}
|
||||
|
||||
@ -1456,8 +1496,7 @@ static int DecodeImageStream(int xsize, int ysize,
|
||||
if (color_cache_bits > 0) {
|
||||
hdr->color_cache_size_ = 1 << color_cache_bits;
|
||||
if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
ok = 0;
|
||||
ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
|
||||
goto End;
|
||||
}
|
||||
} else {
|
||||
@ -1474,8 +1513,7 @@ static int DecodeImageStream(int xsize, int ysize,
|
||||
const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
|
||||
data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
|
||||
if (data == NULL) {
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
ok = 0;
|
||||
ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
@ -1520,8 +1558,7 @@ static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
|
||||
dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
|
||||
if (dec->pixels_ == NULL) {
|
||||
dec->argb_cache_ = NULL; // for soundness
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
|
||||
}
|
||||
dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
|
||||
return 1;
|
||||
@ -1532,8 +1569,7 @@ static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
|
||||
dec->argb_cache_ = NULL; // for soundness
|
||||
dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
|
||||
if (dec->pixels_ == NULL) {
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -1588,7 +1624,8 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
|
||||
dec->status_ = VP8_STATUS_OK;
|
||||
VP8LInitBitReader(&dec->br_, data, data_size);
|
||||
|
||||
if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
|
||||
if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, /*is_level0=*/1,
|
||||
dec, /*decoded_data=*/NULL)) {
|
||||
goto Err;
|
||||
}
|
||||
|
||||
@ -1643,22 +1680,24 @@ int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
|
||||
|
||||
if (dec == NULL) return 0;
|
||||
if (io == NULL) {
|
||||
dec->status_ = VP8_STATUS_INVALID_PARAM;
|
||||
return 0;
|
||||
return VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
|
||||
}
|
||||
|
||||
dec->io_ = io;
|
||||
dec->status_ = VP8_STATUS_OK;
|
||||
VP8LInitBitReader(&dec->br_, io->data, io->data_size);
|
||||
if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
|
||||
goto Error;
|
||||
}
|
||||
dec->state_ = READ_DIM;
|
||||
io->width = width;
|
||||
io->height = height;
|
||||
|
||||
if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
|
||||
if (!DecodeImageStream(width, height, /*is_level0=*/1, dec,
|
||||
/*decoded_data=*/NULL)) {
|
||||
goto Error;
|
||||
}
|
||||
return 1;
|
||||
|
||||
Error:
|
||||
@ -1673,7 +1712,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
|
||||
|
||||
if (dec == NULL) return 0;
|
||||
|
||||
assert(dec->hdr_.huffman_tables_ != NULL);
|
||||
assert(dec->hdr_.huffman_tables_.root.start != NULL);
|
||||
assert(dec->hdr_.htree_groups_ != NULL);
|
||||
assert(dec->hdr_.num_htree_groups_ > 0);
|
||||
|
||||
@ -1688,7 +1727,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
|
||||
assert(dec->output_ != NULL);
|
||||
|
||||
if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
|
||||
dec->status_ = VP8_STATUS_INVALID_PARAM;
|
||||
VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
|
||||
goto Err;
|
||||
}
|
||||
|
||||
@ -1698,7 +1737,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
|
||||
if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
|
||||
#else
|
||||
if (io->use_scaling) {
|
||||
dec->status_ = VP8_STATUS_INVALID_PARAM;
|
||||
VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
|
||||
goto Err;
|
||||
}
|
||||
#endif
|
||||
@ -1716,7 +1755,7 @@ int VP8LDecodeImage(VP8LDecoder* const dec) {
|
||||
dec->hdr_.saved_color_cache_.colors_ == NULL) {
|
||||
if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_,
|
||||
dec->hdr_.color_cache_.hash_bits_)) {
|
||||
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
|
||||
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
|
||||
goto Err;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "src/utils/bit_reader_utils.h"
|
||||
#include "src/utils/color_cache_utils.h"
|
||||
#include "src/utils/huffman_utils.h"
|
||||
#include "src/webp/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -51,7 +52,7 @@ typedef struct {
|
||||
uint32_t* huffman_image_;
|
||||
int num_htree_groups_;
|
||||
HTreeGroup* htree_groups_;
|
||||
HuffmanCode* huffman_tables_;
|
||||
HuffmanTables huffman_tables_;
|
||||
} VP8LMetadata;
|
||||
|
||||
typedef struct VP8LDecoder VP8LDecoder;
|
||||
@ -99,33 +100,42 @@ struct ALPHDecoder; // Defined in dec/alphai.h.
|
||||
|
||||
// Decodes image header for alpha data stored using lossless compression.
|
||||
// Returns false in case of error.
|
||||
int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec,
|
||||
const uint8_t* const data, size_t data_size);
|
||||
WEBP_NODISCARD int VP8LDecodeAlphaHeader(struct ALPHDecoder* const alph_dec,
|
||||
const uint8_t* const data,
|
||||
size_t data_size);
|
||||
|
||||
// Decodes *at least* 'last_row' rows of alpha. If some of the initial rows are
|
||||
// already decoded in previous call(s), it will resume decoding from where it
|
||||
// was paused.
|
||||
// Returns false in case of bitstream error.
|
||||
int VP8LDecodeAlphaImageStream(struct ALPHDecoder* const alph_dec,
|
||||
int last_row);
|
||||
WEBP_NODISCARD int VP8LDecodeAlphaImageStream(
|
||||
struct ALPHDecoder* const alph_dec, int last_row);
|
||||
|
||||
// Allocates and initialize a new lossless decoder instance.
|
||||
VP8LDecoder* VP8LNew(void);
|
||||
WEBP_NODISCARD VP8LDecoder* VP8LNew(void);
|
||||
|
||||
// Decodes the image header. Returns false in case of error.
|
||||
int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io);
|
||||
WEBP_NODISCARD int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io);
|
||||
|
||||
// Decodes an image. It's required to decode the lossless header before calling
|
||||
// this function. Returns false in case of error, with updated dec->status_.
|
||||
int VP8LDecodeImage(VP8LDecoder* const dec);
|
||||
|
||||
// Resets the decoder in its initial state, reclaiming memory.
|
||||
// Preserves the dec->status_ value.
|
||||
void VP8LClear(VP8LDecoder* const dec);
|
||||
WEBP_NODISCARD int VP8LDecodeImage(VP8LDecoder* const dec);
|
||||
|
||||
// Clears and deallocate a lossless decoder instance.
|
||||
void VP8LDelete(VP8LDecoder* const dec);
|
||||
|
||||
// Helper function for reading the different Huffman codes and storing them in
|
||||
// 'huffman_tables' and 'htree_groups'.
|
||||
// If mapping is NULL 'num_htree_groups_max' must equal 'num_htree_groups'.
|
||||
// If it is not NULL, it maps 'num_htree_groups_max' indices to the
|
||||
// 'num_htree_groups' groups. If 'num_htree_groups_max' > 'num_htree_groups',
|
||||
// some of those indices map to -1. This is used for non-balanced codes to
|
||||
// limit memory usage.
|
||||
WEBP_NODISCARD int ReadHuffmanCodesHelper(
|
||||
int color_cache_bits, int num_htree_groups, int num_htree_groups_max,
|
||||
const int* const mapping, VP8LDecoder* const dec,
|
||||
HuffmanTables* const huffman_tables, HTreeGroup** const htree_groups);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user