mirror of
https://github.com/webmproject/libwebp.git
synced 2025-12-24 14:06:27 +01:00
Compare commits
1334 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4422702d0 | ||
|
|
ed665a15e8 | ||
|
|
6b1d18c362 | ||
|
|
3368d8768a | ||
|
|
f213abf620 | ||
|
|
50c97c301d | ||
|
|
2c206aaf96 | ||
|
|
96e3dfef26 | ||
|
|
0e0f74b7e3 | ||
|
|
35b7436a21 | ||
|
|
21d24b4c08 | ||
|
|
cdcf89020e | ||
|
|
dc683cdef5 | ||
|
|
0858494e96 | ||
|
|
c2cf6a93b0 | ||
|
|
df0e808fed | ||
|
|
676c57dba4 | ||
|
|
7bb7f7474e | ||
|
|
abcd1797a1 | ||
|
|
edaf08952d | ||
|
|
b96220636b | ||
|
|
e23cd5481c | ||
|
|
3875c7de07 | ||
|
|
1a8f0d45d3 | ||
|
|
934801604e | ||
|
|
45eaacc939 | ||
|
|
42592af875 | ||
|
|
e298e05f66 | ||
|
|
29148919e0 | ||
|
|
9ce5843dba | ||
|
|
d9191588ab | ||
|
|
c5bc36243a | ||
|
|
53b6f76209 | ||
|
|
d2caaba435 | ||
|
|
731246ba3b | ||
|
|
d250f01d95 | ||
|
|
1fe3162541 | ||
|
|
3a4d3ecd40 | ||
|
|
b2bc809346 | ||
|
|
e542fc7a8a | ||
|
|
e024115490 | ||
|
|
edea64442c | ||
|
|
ece18e5520 | ||
|
|
a89a3230c9 | ||
|
|
26f4aa0115 | ||
|
|
8f5946634e | ||
|
|
46d844e6cf | ||
|
|
298d26eac2 | ||
|
|
a1e5dae0f0 | ||
|
|
327ef24fbd | ||
|
|
f70819de51 | ||
|
|
dc7e2b42e7 | ||
|
|
9df23dddc2 | ||
|
|
a2e18f10eb | ||
|
|
e1a8d4f3fe | ||
|
|
4de35f4383 | ||
|
|
0f13eec7bf | ||
|
|
277d30749f | ||
|
|
97adbba513 | ||
|
|
b60d460318 | ||
|
|
72fe52f623 | ||
|
|
116d235c30 | ||
|
|
6f445b3e3d | ||
|
|
b1cf887f86 | ||
|
|
3e26513656 | ||
|
|
f6d2924757 | ||
|
|
de3b4ba813 | ||
|
|
7f09d3d132 | ||
|
|
4edea4a695 | ||
|
|
c9e26bdb35 | ||
|
|
28d488e6f1 | ||
|
|
695bdaa2f6 | ||
|
|
685d073ee1 | ||
|
|
d38bd0dda0 | ||
|
|
109ff0f100 | ||
|
|
a2fce86744 | ||
|
|
776983d427 | ||
|
|
315abbd60b | ||
|
|
eae815d0d1 | ||
|
|
afbca5a152 | ||
|
|
3320416b2e | ||
|
|
29145ed692 | ||
|
|
1f5791398c | ||
|
|
29b6129c78 | ||
|
|
b60869a18e | ||
|
|
6fb4cddc93 | ||
|
|
05b72d4205 | ||
|
|
b6513fbaa8 | ||
|
|
98bbe35b51 | ||
|
|
b1674240f9 | ||
|
|
88c90c4528 | ||
|
|
6a9916d734 | ||
|
|
b6cf52d5b8 | ||
|
|
3b12b7f4b4 | ||
|
|
595fa13f83 | ||
|
|
8fdaecb09d | ||
|
|
8933bac212 | ||
|
|
7d416ff085 | ||
|
|
ec6cfeb51e | ||
|
|
7e58a1a260 | ||
|
|
5651a6b2ed | ||
|
|
25ae67b3de | ||
|
|
5d4ee4c3c0 | ||
|
|
01b38ee19a | ||
|
|
652aa34424 | ||
|
|
0320e1e36f | ||
|
|
8886f620c0 | ||
|
|
fae416179e | ||
|
|
5bd2704e30 | ||
|
|
fee642870e | ||
|
|
33ddb894b1 | ||
|
|
b27ea8525a | ||
|
|
b78494a933 | ||
|
|
e79974cd6a | ||
|
|
a885339448 | ||
|
|
a09a647241 | ||
|
|
401da22bd6 | ||
|
|
2690782292 | ||
|
|
06c1e72e71 | ||
|
|
8f0d41aac0 | ||
|
|
373eb170f1 | ||
|
|
759b9d5a06 | ||
|
|
926ce921f3 | ||
|
|
9c367bc602 | ||
|
|
47f64f6edd | ||
|
|
cc3577e9b9 | ||
|
|
004d77ffab | ||
|
|
fedac6cc69 | ||
|
|
170a871202 | ||
|
|
ceddb5fc8d | ||
|
|
8599571935 | ||
|
|
289757fe1e | ||
|
|
8af7436f10 | ||
|
|
e56c3c5be3 | ||
|
|
8696147da4 | ||
|
|
13b8e9fe16 | ||
|
|
a92254107e | ||
|
|
d6c2285d7c | ||
|
|
8df77fb1b1 | ||
|
|
52ce633388 | ||
|
|
28c4982064 | ||
|
|
7363dff25c | ||
|
|
826aafa570 | ||
|
|
6325882327 | ||
|
|
9eb2638119 | ||
|
|
2e7bed7925 | ||
|
|
cccf5e337a | ||
|
|
c9a3f6a1d0 | ||
|
|
319f56f1a1 | ||
|
|
e8e8db985a | ||
|
|
ae54553461 | ||
|
|
fef789f366 | ||
|
|
fc14fc038b | ||
|
|
7656f0b335 | ||
|
|
d2e245ea9e | ||
|
|
96099a79a8 | ||
|
|
5abb55823b | ||
|
|
8484a1204c | ||
|
|
d7bf01c954 | ||
|
|
36c81ff6a9 | ||
|
|
988b02abfd | ||
|
|
26faf7706b | ||
|
|
ab2d08a842 | ||
|
|
52273943c6 | ||
|
|
8870ba7f06 | ||
|
|
4b3c6953ef | ||
|
|
17fd4ba820 | ||
|
|
411d3677ca | ||
|
|
3700ffd7e1 | ||
|
|
83604bf3ac | ||
|
|
eb44119c3d | ||
|
|
9f6055fcb2 | ||
|
|
695788e7f5 | ||
|
|
906c1fcd61 | ||
|
|
8cb7e536d2 | ||
|
|
443db47d91 | ||
|
|
36a6eea3bc | ||
|
|
ec5f12c11a | ||
|
|
64425a0884 | ||
|
|
bd94090a11 | ||
|
|
cf847cba58 | ||
|
|
55a080e50a | ||
|
|
84739717d6 | ||
|
|
def64e920f | ||
|
|
cf2f88b38f | ||
|
|
f0110baec0 | ||
|
|
749a8b99f7 | ||
|
|
4f9f00ccf4 | ||
|
|
7658c68613 | ||
|
|
133ff0e374 | ||
|
|
e3c259a278 | ||
|
|
b3ff0bdec1 | ||
|
|
f9b30586eb | ||
|
|
1d58dcfc17 | ||
|
|
4407026621 | ||
|
|
2565fa8ffb | ||
|
|
47309ef52d | ||
|
|
687ab00e6e | ||
|
|
1b92fe75a1 | ||
|
|
53f3d8cf7e | ||
|
|
27d082403c | ||
|
|
69776e3832 | ||
|
|
a99078c1cf | ||
|
|
22e404ccbd | ||
|
|
71690b524e | ||
|
|
6a0ff35872 | ||
|
|
0fa56f307f | ||
|
|
6cf504d018 | ||
|
|
d7844e9762 | ||
|
|
7f0064361a | ||
|
|
cf047e8347 | ||
|
|
c074c65368 | ||
|
|
30f0955160 | ||
|
|
a76694a1d6 | ||
|
|
6e3ef7b326 | ||
|
|
47178dbd45 | ||
|
|
22cbae33e5 | ||
|
|
290dd0b426 | ||
|
|
0df474ac9e | ||
|
|
c6b75a1966 | ||
|
|
295e5e3801 | ||
|
|
e2575e05cb | ||
|
|
b0e09e346f | ||
|
|
cf0e903c89 | ||
|
|
bb7bc40b6d | ||
|
|
78881b769c | ||
|
|
9f750f7a06 | ||
|
|
17850e74ce | ||
|
|
2fa2552db1 | ||
|
|
a4df4aae73 | ||
|
|
853ea3d846 | ||
|
|
af650c0bd2 | ||
|
|
601ef17cf6 | ||
|
|
0e48d889eb | ||
|
|
24d2ccb4e0 | ||
|
|
fab8f9cfcf | ||
|
|
94138e0e0d | ||
|
|
0fe1a89dbf | ||
|
|
2ad0916d5a | ||
|
|
1287362b9a | ||
|
|
7b968cc2d5 | ||
|
|
9d6988f44d | ||
|
|
312f74d010 | ||
|
|
92dbf23775 | ||
|
|
a277d197a2 | ||
|
|
804540f183 | ||
|
|
bf00c15b23 | ||
|
|
a788b49897 | ||
|
|
e6a92c5e15 | ||
|
|
ec1cc40a59 | ||
|
|
1106478f42 | ||
|
|
812a6b49fc | ||
|
|
4627c1c91b | ||
|
|
c84673a62f | ||
|
|
776a775709 | ||
|
|
bd39c063ce | ||
|
|
0550576faa | ||
|
|
6682f2c415 | ||
|
|
e78dea7587 | ||
|
|
9acf18ba46 | ||
|
|
b9be7e65f8 | ||
|
|
1394a2bb86 | ||
|
|
dd3e7f8a2f | ||
|
|
32cf880132 | ||
|
|
e1c8acb5bd | ||
|
|
cbd23dd5b4 | ||
|
|
2e672351aa | ||
|
|
1326988d10 | ||
|
|
0e7f854897 | ||
|
|
17ed143879 | ||
|
|
24686538be | ||
|
|
153bb3a0ef | ||
|
|
ab2dc8939f | ||
|
|
aa65f89a8f | ||
|
|
af0bac643a | ||
|
|
6d2e11ec8b | ||
|
|
8c3f04febb | ||
|
|
fcfd9c71b4 | ||
|
|
067031eaed | ||
|
|
01ac46bae6 | ||
|
|
d9a662e1aa | ||
|
|
62eb3f087a | ||
|
|
e05f785a66 | ||
|
|
63c9a69fbd | ||
|
|
2b7214ab99 | ||
|
|
bf424b46a3 | ||
|
|
7d05d6ca91 | ||
|
|
6bcf876980 | ||
|
|
2b98df90cb | ||
|
|
61e372b7e3 | ||
|
|
7ae658a026 | ||
|
|
51c4907d32 | ||
|
|
666bd6c654 | ||
|
|
561cdce5bd | ||
|
|
aec2cf02d1 | ||
|
|
928a75deca | ||
|
|
5173d4ee6f | ||
|
|
5b081219c9 | ||
|
|
381b7b54a0 | ||
|
|
6ed15ea1cd | ||
|
|
22bbb24ea8 | ||
|
|
8b3fb2389b | ||
|
|
f435de9575 | ||
|
|
41521aed47 | ||
|
|
9f4d4a3f49 | ||
|
|
0fd7514b55 | ||
|
|
f95a996c64 | ||
|
|
e85d3313d6 | ||
|
|
fa8210e43c | ||
|
|
fd198f7370 | ||
|
|
825389acba | ||
|
|
3be698c3d3 | ||
|
|
485ff86fbb | ||
|
|
4cd0582d50 | ||
|
|
4cbb4caf49 | ||
|
|
f5a5918d13 | ||
|
|
d61385db35 | ||
|
|
6752904b2f | ||
|
|
0c57031629 | ||
|
|
301a2ddae5 | ||
|
|
f0abab9217 | ||
|
|
f2dfd92557 | ||
|
|
06b7bc7dec | ||
|
|
b6284d8247 | ||
|
|
decf6f6b87 | ||
|
|
dea3e89983 | ||
|
|
632798ae6f | ||
|
|
dc1a9518bc | ||
|
|
9cf9841b5e | ||
|
|
981794958b | ||
|
|
a376e7b96a | ||
|
|
cbf82cc04d | ||
|
|
5030e90278 | ||
|
|
ac5433118a | ||
|
|
123d330699 | ||
|
|
ef1094b0fe | ||
|
|
b911fbc980 | ||
|
|
eee00b6627 | ||
|
|
ac3ec8c91d | ||
|
|
3e13da7b4f | ||
|
|
5c395f1d71 | ||
|
|
e7a697297b | ||
|
|
e52485d6db | ||
|
|
92dc0f0937 | ||
|
|
39952de265 | ||
|
|
382af7a2dd | ||
|
|
14d020f6e6 | ||
|
|
0d92ff25f2 | ||
|
|
556cb1b45e | ||
|
|
da26ee49a6 | ||
|
|
b2a867c038 | ||
|
|
637141bc7c | ||
|
|
bc5092b162 | ||
|
|
50d8345ae6 | ||
|
|
6aa3e8aaf3 | ||
|
|
d71df4e2ee | ||
|
|
de08d72741 | ||
|
|
009562b403 | ||
|
|
423f257930 | ||
|
|
907208f97e | ||
|
|
4649b3c422 | ||
|
|
78ad57a36a | ||
|
|
da96d8d9ab | ||
|
|
2563db4759 | ||
|
|
211f37ee63 | ||
|
|
5f0f5c07c4 | ||
|
|
de98732b04 | ||
|
|
4338cd36fe | ||
|
|
e00af13ef4 | ||
|
|
a9ceda7ff1 | ||
|
|
2281bbf6f7 | ||
|
|
39cb9aad85 | ||
|
|
89cc9d3787 | ||
|
|
95fd650706 | ||
|
|
9e729fe19b | ||
|
|
29fb8562c6 | ||
|
|
eb82ce76dd | ||
|
|
1344a2e947 | ||
|
|
be738c6d39 | ||
|
|
2c70ad76c9 | ||
|
|
569001f19f | ||
|
|
c56a02d971 | ||
|
|
1579559662 | ||
|
|
1a44c233b9 | ||
|
|
e9569ad708 | ||
|
|
35c7de6fc4 | ||
|
|
0f25e61c13 | ||
|
|
5d8985de47 | ||
|
|
895fd28f9b | ||
|
|
5cf3e2afb5 | ||
|
|
2a9de5b9d3 | ||
|
|
71ed73cf86 | ||
|
|
af0e4fbb06 | ||
|
|
dce5d76431 | ||
|
|
f9df0081a7 | ||
|
|
dc39b16fe4 | ||
|
|
c7aa1264f0 | ||
|
|
53aa51e9a3 | ||
|
|
698b8844e3 | ||
|
|
8d510751da | ||
|
|
e6b2164e3a | ||
|
|
094b3b285b | ||
|
|
71c39a06c8 | ||
|
|
fd3d5756cb | ||
|
|
b0c966fb66 | ||
|
|
d20b770713 | ||
|
|
0d5fad46cf | ||
|
|
d77bf512bd | ||
|
|
c1cb86af5f | ||
|
|
e577feb7c2 | ||
|
|
99be34b3a8 | ||
|
|
e122e511cf | ||
|
|
f5565ca84a | ||
|
|
d898dc14a5 | ||
|
|
1c8f358df4 | ||
|
|
a0215fb7dc | ||
|
|
882784b03d | ||
|
|
2f930e0872 | ||
|
|
8165e8fb3b | ||
|
|
3f157dd5e7 | ||
|
|
abb4776006 | ||
|
|
cd758a1745 | ||
|
|
e155dda0cc | ||
|
|
b892b8ba8b | ||
|
|
64a57d0587 | ||
|
|
994be82d00 | ||
|
|
4033e1d70d | ||
|
|
fc1b8e3a8b | ||
|
|
15aa48d905 | ||
|
|
e607dabcf2 | ||
|
|
38410c082f | ||
|
|
978eec2507 | ||
|
|
c57b273698 | ||
|
|
cba2885375 | ||
|
|
c909d53182 | ||
|
|
217443c71a | ||
|
|
b672bdfaad | ||
|
|
daa9fcaf5b | ||
|
|
dd174caeff | ||
|
|
641cedccd3 | ||
|
|
065b2ce10e | ||
|
|
c4cc114785 | ||
|
|
09333097ed | ||
|
|
e03f0ec319 | ||
|
|
b2db361ca6 | ||
|
|
74e82ec64a | ||
|
|
645d04ca7f | ||
|
|
120f58c3aa | ||
|
|
a7fe9412d0 | ||
|
|
e26fe06680 | ||
|
|
9df64e28dd | ||
|
|
8043504f95 | ||
|
|
1e3dfc48fb | ||
|
|
3b07d32712 | ||
|
|
551948e45f | ||
|
|
3005237a5d | ||
|
|
499c395a35 | ||
|
|
f69dcd692a | ||
|
|
07d884d59b | ||
|
|
f4dd92565e | ||
|
|
94a8377b3e | ||
|
|
fc09e6e252 | ||
|
|
6de58603b7 | ||
|
|
cbde5728c8 | ||
|
|
cf1c5054c7 | ||
|
|
45a8b5eb59 | ||
|
|
cff38e8f4d | ||
|
|
59cb1a48c1 | ||
|
|
78318b30e5 | ||
|
|
664c21dd01 | ||
|
|
815652de03 | ||
|
|
aec45cec33 | ||
|
|
5715dfce2e | ||
|
|
c2d04f3eb2 | ||
|
|
96bf07c560 | ||
|
|
1c59020b93 | ||
|
|
7a8e814b57 | ||
|
|
05f6fe24c3 | ||
|
|
b4cf5597f4 | ||
|
|
ccbeb32c04 | ||
|
|
55403a9a5a | ||
|
|
807b53c47e | ||
|
|
84101a8165 | ||
|
|
8bebd2a32e | ||
|
|
a7f93fe32d | ||
|
|
b69f18a73a | ||
|
|
72d530c01d | ||
|
|
296c7dc4ac | ||
|
|
0d5d029c18 | ||
|
|
ae568ce7c4 | ||
|
|
796b5a8a8a | ||
|
|
6b7a95fd83 | ||
|
|
f66955de5f | ||
|
|
1af0df7662 | ||
|
|
6de20df02c | ||
|
|
a289d8e774 | ||
|
|
c10a493caf | ||
|
|
0d4466c2b4 | ||
|
|
1b27bf8b76 | ||
|
|
126be10950 | ||
|
|
0df22b9eed | ||
|
|
9add62b581 | ||
|
|
d3e2614493 | ||
|
|
2edda639b2 | ||
|
|
9ca568ef82 | ||
|
|
31f1995cc5 | ||
|
|
a80c46bd87 | ||
|
|
083507f244 | ||
|
|
2e5785b233 | ||
|
|
b299c47eac | ||
|
|
f593d71a64 | ||
|
|
541179a9a5 | ||
|
|
5755a7ec53 | ||
|
|
eab5bab74f | ||
|
|
8052c585b3 | ||
|
|
c245343dcb | ||
|
|
b9e734fd5c | ||
|
|
c188d546b3 | ||
|
|
28c5ac8104 | ||
|
|
e65b72a368 | ||
|
|
b94cee98fb | ||
|
|
44a0ee3fa7 | ||
|
|
aebf59ac50 | ||
|
|
c184665ecd | ||
|
|
3daf7509c2 | ||
|
|
80285d97ad | ||
|
|
650eac5542 | ||
|
|
c462cd0065 | ||
|
|
01a98217ad | ||
|
|
3c49fc47e7 | ||
|
|
fde2782ecb | ||
|
|
2a270c1df5 | ||
|
|
f1f437cc89 | ||
|
|
3879074d99 | ||
|
|
04b029d236 | ||
|
|
b7971d0e22 | ||
|
|
6ba98764e8 | ||
|
|
5cfb3b0f6c | ||
|
|
f433205ee3 | ||
|
|
8d033b14d7 | ||
|
|
0295e9815d | ||
|
|
d572c4e52b | ||
|
|
ab9c2500db | ||
|
|
93e0ce27f4 | ||
|
|
22fbc50edd | ||
|
|
447875b47b | ||
|
|
e51bdd439c | ||
|
|
785da7eadd | ||
|
|
bc1a251fcf | ||
|
|
61e535f1ac | ||
|
|
68b2eab7df | ||
|
|
30042faa9a | ||
|
|
0a17f4712c | ||
|
|
a439972175 | ||
|
|
0827570873 | ||
|
|
d361a6a733 | ||
|
|
6921aa6f0c | ||
|
|
08c67d3ed1 | ||
|
|
582a1b572a | ||
|
|
2c1b18ba2f | ||
|
|
0ac46e818b | ||
|
|
bc634d57c2 | ||
|
|
bcb7347c2b | ||
|
|
e14ad93c0a | ||
|
|
7038ca8d52 | ||
|
|
fb3daad604 | ||
|
|
be590e0644 | ||
|
|
35f736e1ec | ||
|
|
a5216efc8c | ||
|
|
a9c8916b87 | ||
|
|
3c74c645ca | ||
|
|
c7f295d30c | ||
|
|
b4e046778d | ||
|
|
f78da3dea6 | ||
|
|
01c426f1e7 | ||
|
|
8635973dc3 | ||
|
|
e9459382b0 | ||
|
|
4a9d788e40 | ||
|
|
4fbdc9fb12 | ||
|
|
a80fcc4ae1 | ||
|
|
3993af127e | ||
|
|
f66f94ef36 | ||
|
|
6eba857b75 | ||
|
|
c5e34fba66 | ||
|
|
3822762a6c | ||
|
|
501ef6e4e9 | ||
|
|
f8bdc26821 | ||
|
|
23bfc652fe | ||
|
|
8dc3d71ba0 | ||
|
|
5bd40066cc | ||
|
|
7945575c92 | ||
|
|
8729fa1102 | ||
|
|
f324b7f9ba | ||
|
|
869eb36983 | ||
|
|
289e62a313 | ||
|
|
20a94186ce | ||
|
|
34130afe8b | ||
|
|
42c79aa66b | ||
|
|
b09307dcde | ||
|
|
bed0456d58 | ||
|
|
54f6a3cf3a | ||
|
|
088f1dcce8 | ||
|
|
86fc4dd9f4 | ||
|
|
08ea9ecde3 | ||
|
|
6f9daa4a3a | ||
|
|
a0f72a4fe0 | ||
|
|
8c934902cd | ||
|
|
622242aaba | ||
|
|
1411f02761 | ||
|
|
24ad2e3c99 | ||
|
|
46efe062b8 | ||
|
|
8c3f9a4706 | ||
|
|
1aef4c710b | ||
|
|
b8821dbd81 | ||
|
|
7beed2807b | ||
|
|
6473d20b3e | ||
|
|
dcefed950b | ||
|
|
0c83a8bc69 | ||
|
|
c6d1db4b36 | ||
|
|
663a6d9d2e | ||
|
|
73ea9f2702 | ||
|
|
c71b68ac45 | ||
|
|
c4568b47fd | ||
|
|
6cb13b0532 | ||
|
|
83a3e69a20 | ||
|
|
7295fde2e6 | ||
|
|
8e42ba4c80 | ||
|
|
331ab34bcd | ||
|
|
b161f670f8 | ||
|
|
dec5e4d330 | ||
|
|
6878d42720 | ||
|
|
461ae5551b | ||
|
|
62486a2206 | ||
|
|
92982609bc | ||
|
|
0265cede89 | ||
|
|
88c73d8a7a | ||
|
|
4ea49f6b82 | ||
|
|
1b526638b8 | ||
|
|
87f57a4b62 | ||
|
|
b34a9db1a1 | ||
|
|
471c5755fc | ||
|
|
c793417a3c | ||
|
|
dcbc1c881a | ||
|
|
66ad84f0f9 | ||
|
|
50ec3ab790 | ||
|
|
7d67a1646d | ||
|
|
e50650c77f | ||
|
|
671d2567d4 | ||
|
|
d67555809f | ||
|
|
28914528e1 | ||
|
|
8acb4942f7 | ||
|
|
3b62347b0f | ||
|
|
7ca0df1363 | ||
|
|
7b250459d6 | ||
|
|
e132072f0b | ||
|
|
5d7a50efee | ||
|
|
7b012987a2 | ||
|
|
f0569adb93 | ||
|
|
f1d5a397db | ||
|
|
f8c2ac15af | ||
|
|
a88c6522f6 | ||
|
|
8f6df1d0b9 | ||
|
|
355c3d1bc7 | ||
|
|
a1779a017b | ||
|
|
67de68b5d9 | ||
|
|
f209a5481e | ||
|
|
b903b80c30 | ||
|
|
498cad34be | ||
|
|
e4eb458741 | ||
|
|
af6deaffa0 | ||
|
|
7caef29b86 | ||
|
|
39e19f927c | ||
|
|
9bbc0891c6 | ||
|
|
e1118d624d | ||
|
|
186bc9b735 | ||
|
|
b588729740 | ||
|
|
f1784aee04 | ||
|
|
0d20abb36f | ||
|
|
972104b34b | ||
|
|
dd7e83cca7 | ||
|
|
d988eb7b39 | ||
|
|
dabda70733 | ||
|
|
4c1176432a | ||
|
|
defc98d72c | ||
|
|
d78ff78095 | ||
|
|
c8f14093ac | ||
|
|
497dc6a70d | ||
|
|
d78e5867ff | ||
|
|
481e91eb86 | ||
|
|
93b1275373 | ||
|
|
645f0c53de | ||
|
|
e91546054d | ||
|
|
818d795b09 | ||
|
|
d63e6f4b23 | ||
|
|
4d7084350e | ||
|
|
faf42213f4 | ||
|
|
b4d576fa9c | ||
|
|
cbc1b92117 | ||
|
|
e644c556c5 | ||
|
|
b62cdad287 | ||
|
|
da3e4dfb6f | ||
|
|
a9c701e04f | ||
|
|
adab8ce020 | ||
|
|
1b92b237ac | ||
|
|
1923ff0222 | ||
|
|
97cce5ba83 | ||
|
|
0dcd85b6c4 | ||
|
|
f768218966 | ||
|
|
52245424b0 | ||
|
|
690efd82f8 | ||
|
|
4bb1f607d7 | ||
|
|
285748be78 | ||
|
|
78fd199c3b | ||
|
|
ae836410bb | ||
|
|
d0b7404e00 | ||
|
|
134e314fd8 | ||
|
|
c08adb6fbc | ||
|
|
28c37ebd5a | ||
|
|
2cb58ab2d7 | ||
|
|
bb175a935e | ||
|
|
39eda6584f | ||
|
|
36b8274deb | ||
|
|
274daf5415 | ||
|
|
ec5036e475 | ||
|
|
18f0dfac82 | ||
|
|
4e2b0b50ea | ||
|
|
e2eeabff12 | ||
|
|
836607e68a | ||
|
|
9273e441da | ||
|
|
17e3c11f99 | ||
|
|
5f62487189 | ||
|
|
976adac1ce | ||
|
|
f8fad4fac1 | ||
|
|
27415d4102 | ||
|
|
4956618276 | ||
|
|
6f75a51b58 | ||
|
|
a5e4e3aff1 | ||
|
|
75a9c3c452 | ||
|
|
39cf6f4f36 | ||
|
|
699b04161a | ||
|
|
7d985bd1d0 | ||
|
|
6e7caf06ee | ||
|
|
833c92198c | ||
|
|
5183326ba8 | ||
|
|
99f6f462f5 | ||
|
|
80a2218668 | ||
|
|
a128dfff51 | ||
|
|
693bf74ec0 | ||
|
|
10d791ca70 | ||
|
|
fa63a96603 | ||
|
|
16be192f47 | ||
|
|
027151ca6c | ||
|
|
4105d565d3 | ||
|
|
9ee32a7506 | ||
|
|
ca9f7b7dd6 | ||
|
|
868aa6901f | ||
|
|
5b393f2d2a | ||
|
|
e0012bea23 | ||
|
|
84c2a7b01c | ||
|
|
1b0e4abf08 | ||
|
|
3226325016 | ||
|
|
b494fdec45 | ||
|
|
f153603900 | ||
|
|
e69ed29105 | ||
|
|
57d8de8a79 | ||
|
|
5cfd4ebc5e | ||
|
|
1e7ad88b85 | ||
|
|
17c7890cba | ||
|
|
be73378684 | ||
|
|
03cda0e494 | ||
|
|
aa893914fc | ||
|
|
31a92e972e | ||
|
|
dcf9d82a95 | ||
|
|
6524fcd614 | ||
|
|
6cf24a247d | ||
|
|
43d472aa18 | ||
|
|
50d1a848bc | ||
|
|
20a7fea064 | ||
|
|
415f3ffe3d | ||
|
|
3c6d1224b4 | ||
|
|
ee4a4141f5 | ||
|
|
32ed856f60 | ||
|
|
1c3190b6ed | ||
|
|
f4dc56fd77 | ||
|
|
4f3e3bbd44 | ||
|
|
2dc0bdcaee | ||
|
|
0d8e05880c | ||
|
|
b045013970 | ||
|
|
0ad3b4efa8 | ||
|
|
6451709e72 | ||
|
|
92504d214c | ||
|
|
c3e4b3a946 | ||
|
|
3363eb6d68 | ||
|
|
4d1312f2d5 | ||
|
|
36c42ea415 | ||
|
|
bb498a51e2 | ||
|
|
84cef16f47 | ||
|
|
919f9e2fd6 | ||
|
|
f1ae8af42f | ||
|
|
4689ce1635 | ||
|
|
79bf46f120 | ||
|
|
eb1dc89a5f | ||
|
|
c85b0dde6e | ||
|
|
43d3f01a2f | ||
|
|
668e1dd44f | ||
|
|
0e6b7f33ab | ||
|
|
29ed6f9a0b | ||
|
|
71c53f1aeb | ||
|
|
73f567ea8b | ||
|
|
9e14276f4c | ||
|
|
99965bac02 | ||
|
|
d4912238f7 | ||
|
|
ea4824097e | ||
|
|
2ede5a198a | ||
|
|
a345068aba | ||
|
|
1dc82a6bba | ||
|
|
8074b89eb3 | ||
|
|
749a45a520 | ||
|
|
74c053b57d | ||
|
|
0a3aeff75b | ||
|
|
1de931c669 | ||
|
|
9b3aca404d | ||
|
|
1c07a3c639 | ||
|
|
9ed5e3e5dd | ||
|
|
db013a8d5c | ||
|
|
fcd4784dcd | ||
|
|
fbb5c473b4 | ||
|
|
8fda56126e | ||
|
|
86bbd24552 | ||
|
|
7c2779e95a | ||
|
|
250c358662 | ||
|
|
c0648ac2ae | ||
|
|
0d55f60c91 | ||
|
|
49d0280df1 | ||
|
|
48b1e85fbe | ||
|
|
e3b8abbc9b | ||
|
|
28fe054e73 | ||
|
|
f44acd253b | ||
|
|
527844fee0 | ||
|
|
be0ef6395f | ||
|
|
8874b16275 | ||
|
|
d712e20de0 | ||
|
|
ecff04f625 | ||
|
|
259e98286a | ||
|
|
00b08c88c0 | ||
|
|
0e7f444702 | ||
|
|
b016cb91c5 | ||
|
|
1cb638010c | ||
|
|
875fafc191 | ||
|
|
3674d49e63 | ||
|
|
f04eb37603 | ||
|
|
341d711c43 | ||
|
|
abb5482731 | ||
|
|
ece9684f52 | ||
|
|
aa7744ca38 | ||
|
|
d9120271e7 | ||
|
|
24eb39401b | ||
|
|
a4a8e5f32c | ||
|
|
67c25ad5b4 | ||
|
|
a4bbe4b38b | ||
|
|
31ca2a8098 | ||
|
|
b2f77b57a9 | ||
|
|
5ab6d9de1f | ||
|
|
f29bf582df | ||
|
|
3ebe1c0003 | ||
|
|
df780e0eac | ||
|
|
58fc507842 | ||
|
|
9cc421675b | ||
|
|
0aa1f35c0f | ||
|
|
cb9ec84b54 | ||
|
|
dc0c01fbd3 | ||
|
|
827d3c5038 | ||
|
|
1e2e25b0d4 | ||
|
|
218460cdd7 | ||
|
|
de7d654d0d | ||
|
|
273367c130 | ||
|
|
76bbcf2ed6 | ||
|
|
8ac1abfe13 | ||
|
|
cb215aed5c | ||
|
|
2423017a28 | ||
|
|
74a12b10d9 | ||
|
|
a9cc762196 | ||
|
|
fbba5bc2c1 | ||
|
|
9ae0b3f65a | ||
|
|
c1f97bd758 | ||
|
|
ea664b8995 | ||
|
|
be7dcc088c | ||
|
|
408858308a | ||
|
|
1d5046d1f9 | ||
|
|
cec7201447 | ||
|
|
8f38c72e11 | ||
|
|
33ca93f909 | ||
|
|
76e190735b | ||
|
|
f91ba96306 | ||
|
|
25d74e652e | ||
|
|
03f1c00877 | ||
|
|
58410cd6dc | ||
|
|
e168af8c6c | ||
|
|
ed9dec41a5 | ||
|
|
3c49178f7d | ||
|
|
9595f29010 | ||
|
|
7ec9552c22 | ||
|
|
b3fb8bb602 | ||
|
|
9871335fc8 | ||
|
|
0ae32226ce | ||
|
|
ab4c8056e0 | ||
|
|
eec5fa3a95 | ||
|
|
004d569086 | ||
|
|
4fe5d588bf | ||
|
|
bd63a31aab | ||
|
|
363a568131 | ||
|
|
a0d2753fcb | ||
|
|
31fe11a57a | ||
|
|
532215dd29 | ||
|
|
9c75dbd39c | ||
|
|
af2e05cbdf | ||
|
|
26ffa2962b | ||
|
|
7416280d75 | ||
|
|
13cf1d2e41 | ||
|
|
eb9a4b97c5 | ||
|
|
42ebe3b783 | ||
|
|
76ebbfff28 | ||
|
|
95b12a08ae | ||
|
|
54ab2e758f | ||
|
|
fe12330c81 | ||
|
|
fbfb3bef7b | ||
|
|
d4b7d801db | ||
|
|
a5e3b22574 | ||
|
|
58a1f124c2 | ||
|
|
906c3b6392 | ||
|
|
d23abe4e9f | ||
|
|
2e6cb6f34e | ||
|
|
28e0bb7088 | ||
|
|
647045305a | ||
|
|
bded7848ea | ||
|
|
0e61a5134a | ||
|
|
1cc79e92ac | ||
|
|
03f40955a3 | ||
|
|
ea72cd60cb | ||
|
|
67879e6d48 | ||
|
|
34aee99026 | ||
|
|
a41296aef5 | ||
|
|
c85adb33d2 | ||
|
|
4239a1489c | ||
|
|
bc18ebad2e | ||
|
|
71e2f5cadf | ||
|
|
7474d46e45 | ||
|
|
67748b41db | ||
|
|
16951b1905 | ||
|
|
6540cd0eeb | ||
|
|
de568abfdb | ||
|
|
3c2a61b099 | ||
|
|
9ac063c37f | ||
|
|
22efabddb4 | ||
|
|
1d6e7bf39f | ||
|
|
0a3838ca77 | ||
|
|
c0699515af | ||
|
|
83cbfa09a1 | ||
|
|
a1ade40ed8 | ||
|
|
fd4d090fd1 | ||
|
|
9daad4598b | ||
|
|
f90c60d129 | ||
|
|
3f182d36f4 | ||
|
|
342e15f0ce | ||
|
|
1147ab4ee7 | ||
|
|
e4cd4daf74 | ||
|
|
e715285611 | ||
|
|
de9fa5074e | ||
|
|
deb1b83199 | ||
|
|
c284780f0a | ||
|
|
e375080d8f | ||
|
|
c222a053af | ||
|
|
bb2336170b | ||
|
|
883d41fb40 | ||
|
|
cac9a36a23 | ||
|
|
4595e01fd0 | ||
|
|
fb52d4432a | ||
|
|
f048d38d38 | ||
|
|
31b1e34342 | ||
|
|
2f51b614b0 | ||
|
|
0104d730bf | ||
|
|
265abbe9b2 | ||
|
|
f7601aa686 | ||
|
|
ce8733209d | ||
|
|
2a2773ea29 | ||
|
|
9f5c8eca79 | ||
|
|
4eb5df28d1 | ||
|
|
11bc423ae5 | ||
|
|
273d035a44 | ||
|
|
4db82a178f | ||
|
|
e2affacc35 | ||
|
|
dc789ada44 | ||
|
|
539f5a688f | ||
|
|
aaf2a6a698 | ||
|
|
20ef99159e | ||
|
|
bc86b7a8a1 | ||
|
|
806f6279ae | ||
|
|
68ae5b671f | ||
|
|
28ce304344 | ||
|
|
b34abcb8b1 | ||
|
|
ba843a92e7 | ||
|
|
51b71fd295 | ||
|
|
fb01743a53 | ||
|
|
bfab894739 | ||
|
|
9310d19258 | ||
|
|
f79450ca02 | ||
|
|
cfdda7c6bf | ||
|
|
e36396ba75 | ||
|
|
18a9a0ab57 | ||
|
|
30d43706d3 | ||
|
|
36aa087b6d | ||
|
|
86a84b3598 | ||
|
|
b8384b53d6 | ||
|
|
1c36440094 | ||
|
|
eee0cce158 | ||
|
|
5f1caf2987 | ||
|
|
1effde7bcd | ||
|
|
a2fe9bf404 | ||
|
|
573cce270e | ||
|
|
21e7537abe | ||
|
|
053a1565c8 | ||
|
|
1377ac2ec1 | ||
|
|
7c1fb7d0ff | ||
|
|
bfff0bf329 | ||
|
|
64577de8ae | ||
|
|
a7be73280b | ||
|
|
50c3d7da9a | ||
|
|
d6228aed6a | ||
|
|
dd538b192d | ||
|
|
6cc48b1728 | ||
|
|
78363e9e51 | ||
|
|
ffd01929f1 | ||
|
|
c4f6d9c939 | ||
|
|
c27d821096 | ||
|
|
0779529616 | ||
|
|
c9b45863e2 | ||
|
|
490ae5b13d | ||
|
|
894232be56 | ||
|
|
8de08483b6 | ||
|
|
41cab7fe0f | ||
|
|
82c91c708e | ||
|
|
af1ad3e2dd | ||
|
|
dd7309e30c | ||
|
|
6105777e8c | ||
|
|
13ae011e4c | ||
|
|
4bda0cfba4 | ||
|
|
6029c7fe68 | ||
|
|
545c147fd8 | ||
|
|
5b46f7fc80 | ||
|
|
9e478f808e | ||
|
|
43bd895879 | ||
|
|
0887fc2d85 | ||
|
|
0de48e187d | ||
|
|
0a57ad0dc5 | ||
|
|
0a4699bcc9 | ||
|
|
29fedbf58b | ||
|
|
32dead4ee3 | ||
|
|
85cd5d061c | ||
|
|
6585075f8a | ||
|
|
c0a27fd2af | ||
|
|
57a5e3b6a5 | ||
|
|
7f1b897bee | ||
|
|
48c810b85c | ||
|
|
3884972e3f | ||
|
|
485cac1a88 | ||
|
|
005e15b10a | ||
|
|
6ab496ed22 | ||
|
|
8a4ebc6ab0 | ||
|
|
9d4f209f80 | ||
|
|
e44f5248ff | ||
|
|
27b5d991e2 | ||
|
|
74f6f9e793 | ||
|
|
aaf2530cc3 | ||
|
|
1269dc7cfb | ||
|
|
40872fb2e6 | ||
|
|
7b54e26bac | ||
|
|
d2223d8d6c | ||
|
|
bf16a4b4f8 | ||
|
|
ee1057e3b1 | ||
|
|
b551e587b3 | ||
|
|
d2e4484ef3 | ||
|
|
c7f66c82b3 | ||
|
|
98d8f295b1 | ||
|
|
39f4ffbcdc | ||
|
|
a86ce2b1e2 | ||
|
|
6fa9fe2482 | ||
|
|
0b2c58a91c | ||
|
|
d7ce4a2e3e | ||
|
|
386e4ba2f0 | ||
|
|
7b87e8485b | ||
|
|
d3ddacb625 | ||
|
|
eb98d8d87c | ||
|
|
ebee57f4d1 | ||
|
|
99542bbf3e | ||
|
|
da573cf490 | ||
|
|
bdda5bd4bf | ||
|
|
15ed462b2d | ||
|
|
7be5748963 | ||
|
|
57020525ed | ||
|
|
e8ab6a825a | ||
|
|
fee7b3d6ca | ||
|
|
1e7d4401dc | ||
|
|
4cecab63bd | ||
|
|
259f0434a5 | ||
|
|
ed34c39bfc | ||
|
|
33d8d0d4d3 | ||
|
|
c960b82e5c | ||
|
|
fe3cd28a53 | ||
|
|
45fbeba5cd | ||
|
|
4f33c82098 | ||
|
|
c379b55a93 | ||
|
|
5108d9aa00 | ||
|
|
ad497fbce3 | ||
|
|
0c0fb83211 | ||
|
|
9ac74f922e | ||
|
|
cb19dbc1a4 | ||
|
|
3f4042b52a | ||
|
|
5e2eb89e1f | ||
|
|
5b60db5c9d | ||
|
|
567e697776 | ||
|
|
c54ab8dd1a | ||
|
|
ec6f68c51e | ||
|
|
2a5c417c68 | ||
|
|
91b59e886b | ||
|
|
fe57273736 | ||
|
|
6b53ca876e | ||
|
|
b15d00d996 | ||
|
|
afe3cec813 | ||
|
|
fc8cad9f29 | ||
|
|
7b4b05e0dc | ||
|
|
c18787a0e9 | ||
|
|
479d19085d | ||
|
|
a80e8cfdf2 | ||
|
|
6c62841076 | ||
|
|
bbb6ecd9b0 | ||
|
|
7915396f40 | ||
|
|
652e944f69 | ||
|
|
c0991a141f | ||
|
|
48bf5ed134 | ||
|
|
bfef6c9f82 | ||
|
|
3d97bb7514 | ||
|
|
deb54d915a | ||
|
|
435308e029 | ||
|
|
dce64bfa1b | ||
|
|
429120d0af | ||
|
|
c7e2d245d1 | ||
|
|
55b2fede7f | ||
|
|
701c772eed | ||
|
|
c7eb06f737 | ||
|
|
f918cb1013 | ||
|
|
ab7937a5c7 | ||
|
|
3cdec847a5 | ||
|
|
bdf6241e70 | ||
|
|
06a38c7b1c | ||
|
|
319e37be13 | ||
|
|
6a19793777 | ||
|
|
447adbce1e | ||
|
|
97b9e64459 | ||
|
|
293d786f31 | ||
|
|
0afa0ce2ff | ||
|
|
a6621bacf3 | ||
|
|
bb50bf42b0 | ||
|
|
38063af131 | ||
|
|
1ebf193c2c | ||
|
|
9ad2352d0d | ||
|
|
607510967f | ||
|
|
9e8e1b7b2a | ||
|
|
7d58d1b7b9 | ||
|
|
8ec7032bc2 | ||
|
|
23e29cb1e3 | ||
|
|
472a049b4e | ||
|
|
0bb23b2cf7 | ||
|
|
a977b4b513 | ||
|
|
3591ba6684 | ||
|
|
e6ac450cbd | ||
|
|
e7b917726f | ||
|
|
2abfa54f95 | ||
|
|
5a48fcd8a1 | ||
|
|
0174d18d8b | ||
|
|
6a9c262aa8 | ||
|
|
cfbcc5ece0 | ||
|
|
5e60c42a76 | ||
|
|
3dc28d7643 | ||
|
|
f2a0946a7a | ||
|
|
9a583c66f9 | ||
|
|
f66512db94 | ||
|
|
6fda58f137 | ||
|
|
a48cc9d201 | ||
|
|
cc2720c1d5 | ||
|
|
059aab4fa1 | ||
|
|
b0c7e49e58 | ||
|
|
a3611513d2 | ||
|
|
8190374c2b | ||
|
|
7551db445e | ||
|
|
0fb2269c4d | ||
|
|
f45376101c | ||
|
|
3259571e7d | ||
|
|
1df5e26001 | ||
|
|
7685123a7f | ||
|
|
a246b921a0 | ||
|
|
76d73f1835 | ||
|
|
eab39d8147 | ||
|
|
4c59aac0f9 | ||
|
|
043c33f1ce | ||
|
|
71be9b8c11 | ||
|
|
0ba7fd70c6 | ||
|
|
0481d42ad8 | ||
|
|
41b7e6b56e | ||
|
|
96c3d62496 | ||
|
|
fe9e31ef5e | ||
|
|
ce3c824712 | ||
|
|
e11da081f9 | ||
|
|
5f8f998d0e | ||
|
|
cadec0b126 | ||
|
|
d963775859 | ||
|
|
50a486656d | ||
|
|
eee788e26a | ||
|
|
d77b877cc9 | ||
|
|
ca8d951980 | ||
|
|
ae2a7222ce | ||
|
|
0b8ae8520f | ||
|
|
77cad88589 | ||
|
|
ab8d669887 | ||
|
|
f8b7ce9ef1 | ||
|
|
5df6f214e3 | ||
|
|
77f21c9c39 | ||
|
|
c9e6d865aa | ||
|
|
c65f41e816 | ||
|
|
bf731ede7e | ||
|
|
08333b8551 | ||
|
|
0209d7e6d6 | ||
|
|
fdd29a3d3f | ||
|
|
cf4a651bb8 | ||
|
|
0a27aca3f8 | ||
|
|
f25c4406e6 | ||
|
|
169004b1d5 | ||
|
|
576362abd7 | ||
|
|
ac49e4e4dc | ||
|
|
d39ceb58ac | ||
|
|
2ec2de1450 | ||
|
|
3e023c17cd | ||
|
|
f2e1efbeb7 | ||
|
|
e15afbce5d | ||
|
|
e53c9ccb24 | ||
|
|
af81fdb772 | ||
|
|
ea0be354a0 | ||
|
|
cd276aecd0 | ||
|
|
c892713104 | ||
|
|
ea24e026aa | ||
|
|
369e264e2e | ||
|
|
0d020a7892 | ||
|
|
5ee2136a71 | ||
|
|
47435a6162 | ||
|
|
8fa6ac68f0 | ||
|
|
74fb56fb5d | ||
|
|
4154a8395d | ||
|
|
c80b9fc8fc | ||
|
|
6235147ed5 | ||
|
|
d41b8c432d | ||
|
|
5f95589fae | ||
|
|
2309fd5c1d | ||
|
|
9629f4bcda | ||
|
|
de47492e91 | ||
|
|
2102ccd091 | ||
|
|
e3912d560b | ||
|
|
6e12e1e3d2 | ||
|
|
602f344a36 | ||
|
|
95ecccf6dc | ||
|
|
47dd07080f | ||
|
|
aa809cfeb3 | ||
|
|
31f2b8d8e1 | ||
|
|
774dfbdc34 | ||
|
|
a4cae68de0 | ||
|
|
238cdcdbe1 | ||
|
|
cf6c713a0b | ||
|
|
b95ac0a221 | ||
|
|
8923139414 | ||
|
|
5828e1995e | ||
|
|
8dca0247d2 | ||
|
|
9a950c5375 | ||
|
|
eb423903a4 | ||
|
|
ff0a94beda | ||
|
|
f80400843f | ||
|
|
6d8c07d375 | ||
|
|
d96fe5e079 | ||
|
|
ec1b2407a4 | ||
|
|
c07687699b | ||
|
|
41f14bcbc5 | ||
|
|
64eed38779 | ||
|
|
97934e2447 | ||
|
|
e88c4ca013 | ||
|
|
4562e83dc2 | ||
|
|
abdb109f3b | ||
|
|
875aec7044 | ||
|
|
71e856cf84 | ||
|
|
a90edffb7e | ||
|
|
423ecaf484 | ||
|
|
f08e66245a | ||
|
|
0d40cc5ea3 | ||
|
|
e8feb20e39 | ||
|
|
8200643017 | ||
|
|
a6f23c49b2 | ||
|
|
a5193774b0 | ||
|
|
da98d31ced | ||
|
|
3335713169 | ||
|
|
0beed01aa5 | ||
|
|
6753f35cac | ||
|
|
6583bb1a42 | ||
|
|
7561d0c338 | ||
|
|
7ccdb734c2 | ||
|
|
6ec0d2a946 | ||
|
|
8aa352b256 | ||
|
|
db86088426 | ||
|
|
9960c31685 | ||
|
|
6e36b51188 | ||
|
|
9dbd4aad77 | ||
|
|
e60853eabc | ||
|
|
696eb2b03a | ||
|
|
2b4fe33e00 | ||
|
|
2f5e8986cf | ||
|
|
bf2b4f114f | ||
|
|
4ed650a13d | ||
|
|
3ef1ce98b9 | ||
|
|
a7a03e9f96 | ||
|
|
5e122bd6d6 | ||
|
|
ab3c2583aa | ||
|
|
8f0dee773a | ||
|
|
4a7b85a967 | ||
|
|
b74657fb2e | ||
|
|
3661b98069 | ||
|
|
75f4af4d54 | ||
|
|
6c1d763119 | ||
|
|
8ce975ac82 | ||
|
|
7db53831a9 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1,5 +1,6 @@
|
|||||||
.gitattributes export-ignore
|
.gitattributes export-ignore
|
||||||
.gitignore export-ignore
|
.gitignore export-ignore
|
||||||
.mailmap export-ignore
|
.mailmap export-ignore
|
||||||
|
*.bat text eol=crlf
|
||||||
*.pdf -text -diff
|
*.pdf -text -diff
|
||||||
*.ppm -text -diff
|
*.ppm -text -diff
|
||||||
|
|||||||
23
.gitignore
vendored
23
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
*.l[ao]
|
*.l[ao]
|
||||||
*.[ao]
|
*.[ao]
|
||||||
*.pc
|
*.pc
|
||||||
|
.DS_Store
|
||||||
.deps
|
.deps
|
||||||
.libs
|
.libs
|
||||||
/aclocal.m4
|
/aclocal.m4
|
||||||
@@ -20,8 +21,11 @@
|
|||||||
Makefile
|
Makefile
|
||||||
Makefile.in
|
Makefile.in
|
||||||
examples/anim_diff
|
examples/anim_diff
|
||||||
|
examples/anim_dump
|
||||||
examples/[cdv]webp
|
examples/[cdv]webp
|
||||||
examples/gif2webp
|
examples/gif2webp
|
||||||
|
examples/img2webp
|
||||||
|
examples/webpinfo
|
||||||
examples/webpmux
|
examples/webpmux
|
||||||
src/webp/config.h*
|
src/webp/config.h*
|
||||||
src/webp/stamp-h1
|
src/webp/stamp-h1
|
||||||
@@ -30,4 +34,21 @@ src/webp/stamp-h1
|
|||||||
*.idb
|
*.idb
|
||||||
*.pdb
|
*.pdb
|
||||||
/iosbuild
|
/iosbuild
|
||||||
/WebP.framework
|
/xcframeworkbuild
|
||||||
|
/WebP*.*framework
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
|
.gradle
|
||||||
|
/build
|
||||||
|
extras/get_disto
|
||||||
|
extras/vwebp_sdl
|
||||||
|
extras/webp_quality
|
||||||
|
tests/fuzzer/advanced_api_fuzzer
|
||||||
|
tests/fuzzer/animation_api_fuzzer
|
||||||
|
tests/fuzzer/animdecoder_fuzzer
|
||||||
|
tests/fuzzer/animencoder_fuzzer
|
||||||
|
tests/fuzzer/demux_api_fuzzer
|
||||||
|
tests/fuzzer/enc_dec_fuzzer
|
||||||
|
tests/fuzzer/mux_demux_api_fuzzer
|
||||||
|
tests/fuzzer/simple_api_fuzzer
|
||||||
|
|||||||
8
.mailmap
8
.mailmap
@@ -1,10 +1,14 @@
|
|||||||
<johann.koenig@duck.com> <johannkoenig@google.com>
|
Johann Koenig <johann.koenig@duck.com>
|
||||||
|
Johann Koenig <johann.koenig@duck.com> <johannkoenig@google.com>
|
||||||
Mikołaj Zalewski <mikolajz@google.com>
|
Mikołaj Zalewski <mikolajz@google.com>
|
||||||
Pascal Massimino <pascal.massimino@gmail.com>
|
Pascal Massimino <pascal.massimino@gmail.com>
|
||||||
<pascal.massimino@gmail.com> <skal@google.com>
|
Pascal Massimino <pascal.massimino@gmail.com> <skal@google.com>
|
||||||
Vikas Arora <vikasa@google.com>
|
Vikas Arora <vikasa@google.com>
|
||||||
<vikasa@google.com> <vikasa@gmail.com>
|
<vikasa@google.com> <vikasa@gmail.com>
|
||||||
<vikasa@google.com> <vikaas.arora@gmail.com>
|
<vikasa@google.com> <vikaas.arora@gmail.com>
|
||||||
<slobodan.prijic@imgtec.com> <Slobodan.Prijic@imgtec.com>
|
<slobodan.prijic@imgtec.com> <Slobodan.Prijic@imgtec.com>
|
||||||
<vrabaud@google.com> <vincent.rabaud@gmail.com>
|
<vrabaud@google.com> <vincent.rabaud@gmail.com>
|
||||||
Tamar Levy <tamar.levy@intel.com>
|
Tamar Levy <tamar.levy@intel.com>
|
||||||
|
<qrczak@google.com> <qrczak>
|
||||||
|
Hui Su <huisu@google.com>
|
||||||
|
James Zern <jzern@google.com>
|
||||||
|
|||||||
441
.pylintrc
Normal file
441
.pylintrc
Normal file
@@ -0,0 +1,441 @@
|
|||||||
|
# This Pylint rcfile contains a best-effort configuration to uphold the
|
||||||
|
# best-practices and style described in the Google Python style guide:
|
||||||
|
# https://google.github.io/styleguide/pyguide.html
|
||||||
|
#
|
||||||
|
# Its canonical open-source location is:
|
||||||
|
# https://google.github.io/styleguide/pylintrc
|
||||||
|
|
||||||
|
[MASTER]
|
||||||
|
|
||||||
|
# Files or directories to be skipped. They should be base names, not paths.
|
||||||
|
ignore=third_party
|
||||||
|
|
||||||
|
# Files or directories matching the regex patterns are skipped. The regex
|
||||||
|
# matches against base names, not paths.
|
||||||
|
ignore-patterns=
|
||||||
|
|
||||||
|
# Pickle collected data for later comparisons.
|
||||||
|
persistent=no
|
||||||
|
|
||||||
|
# List of plugins (as comma separated values of python modules names) to load,
|
||||||
|
# usually to register additional checkers.
|
||||||
|
load-plugins=
|
||||||
|
|
||||||
|
# Use multiple processes to speed up Pylint.
|
||||||
|
jobs=4
|
||||||
|
|
||||||
|
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||||
|
# active Python interpreter and may run arbitrary code.
|
||||||
|
unsafe-load-any-extension=no
|
||||||
|
|
||||||
|
|
||||||
|
[MESSAGES CONTROL]
|
||||||
|
|
||||||
|
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||||
|
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
|
||||||
|
confidence=
|
||||||
|
|
||||||
|
# Enable the message, report, category or checker with the given id(s). You can
|
||||||
|
# either give multiple identifier separated by comma (,) or put this option
|
||||||
|
# multiple time (only on the command line, not in the configuration file where
|
||||||
|
# it should appear only once). See also the "--disable" option for examples.
|
||||||
|
#enable=
|
||||||
|
|
||||||
|
# Disable the message, report, category or checker with the given id(s). You
|
||||||
|
# can either give multiple identifiers separated by comma (,) or put this
|
||||||
|
# option multiple times (only on the command line, not in the configuration
|
||||||
|
# file where it should appear only once).You can also use "--disable=all" to
|
||||||
|
# disable everything first and then reenable specific checks. For example, if
|
||||||
|
# you want to run only the similarities checker, you can use "--disable=all
|
||||||
|
# --enable=similarities". If you want to run only the classes checker, but have
|
||||||
|
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||||
|
# --disable=W"
|
||||||
|
disable=abstract-method,
|
||||||
|
apply-builtin,
|
||||||
|
arguments-differ,
|
||||||
|
attribute-defined-outside-init,
|
||||||
|
backtick,
|
||||||
|
bad-option-value,
|
||||||
|
basestring-builtin,
|
||||||
|
buffer-builtin,
|
||||||
|
c-extension-no-member,
|
||||||
|
consider-using-enumerate,
|
||||||
|
cmp-builtin,
|
||||||
|
cmp-method,
|
||||||
|
coerce-builtin,
|
||||||
|
coerce-method,
|
||||||
|
delslice-method,
|
||||||
|
div-method,
|
||||||
|
duplicate-code,
|
||||||
|
eq-without-hash,
|
||||||
|
execfile-builtin,
|
||||||
|
file-builtin,
|
||||||
|
filter-builtin-not-iterating,
|
||||||
|
fixme,
|
||||||
|
getslice-method,
|
||||||
|
global-statement,
|
||||||
|
hex-method,
|
||||||
|
idiv-method,
|
||||||
|
implicit-str-concat-in-sequence,
|
||||||
|
import-error,
|
||||||
|
import-self,
|
||||||
|
import-star-module-level,
|
||||||
|
inconsistent-return-statements,
|
||||||
|
input-builtin,
|
||||||
|
intern-builtin,
|
||||||
|
invalid-str-codec,
|
||||||
|
locally-disabled,
|
||||||
|
long-builtin,
|
||||||
|
long-suffix,
|
||||||
|
map-builtin-not-iterating,
|
||||||
|
misplaced-comparison-constant,
|
||||||
|
missing-function-docstring,
|
||||||
|
metaclass-assignment,
|
||||||
|
next-method-called,
|
||||||
|
next-method-defined,
|
||||||
|
no-absolute-import,
|
||||||
|
no-else-break,
|
||||||
|
no-else-continue,
|
||||||
|
no-else-raise,
|
||||||
|
no-else-return,
|
||||||
|
no-init, # added
|
||||||
|
no-member,
|
||||||
|
no-name-in-module,
|
||||||
|
no-self-use,
|
||||||
|
nonzero-method,
|
||||||
|
oct-method,
|
||||||
|
old-division,
|
||||||
|
old-ne-operator,
|
||||||
|
old-octal-literal,
|
||||||
|
old-raise-syntax,
|
||||||
|
parameter-unpacking,
|
||||||
|
print-statement,
|
||||||
|
raising-string,
|
||||||
|
range-builtin-not-iterating,
|
||||||
|
raw_input-builtin,
|
||||||
|
rdiv-method,
|
||||||
|
reduce-builtin,
|
||||||
|
relative-import,
|
||||||
|
reload-builtin,
|
||||||
|
round-builtin,
|
||||||
|
setslice-method,
|
||||||
|
signature-differs,
|
||||||
|
standarderror-builtin,
|
||||||
|
suppressed-message,
|
||||||
|
sys-max-int,
|
||||||
|
too-few-public-methods,
|
||||||
|
too-many-ancestors,
|
||||||
|
too-many-arguments,
|
||||||
|
too-many-boolean-expressions,
|
||||||
|
too-many-branches,
|
||||||
|
too-many-instance-attributes,
|
||||||
|
too-many-locals,
|
||||||
|
too-many-nested-blocks,
|
||||||
|
too-many-public-methods,
|
||||||
|
too-many-return-statements,
|
||||||
|
too-many-statements,
|
||||||
|
trailing-newlines,
|
||||||
|
unichr-builtin,
|
||||||
|
unicode-builtin,
|
||||||
|
unnecessary-pass,
|
||||||
|
unpacking-in-except,
|
||||||
|
useless-else-on-loop,
|
||||||
|
useless-object-inheritance,
|
||||||
|
useless-suppression,
|
||||||
|
using-cmp-argument,
|
||||||
|
wrong-import-order,
|
||||||
|
xrange-builtin,
|
||||||
|
zip-builtin-not-iterating,
|
||||||
|
|
||||||
|
|
||||||
|
[REPORTS]
|
||||||
|
|
||||||
|
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||||
|
# (visual studio) and html. You can also give a reporter class, eg
|
||||||
|
# mypackage.mymodule.MyReporterClass.
|
||||||
|
output-format=text
|
||||||
|
|
||||||
|
# Put messages in a separate file for each module / package specified on the
|
||||||
|
# command line instead of printing them on stdout. Reports (if any) will be
|
||||||
|
# written in a file name "pylint_global.[txt|html]". This option is deprecated
|
||||||
|
# and it will be removed in Pylint 2.0.
|
||||||
|
files-output=no
|
||||||
|
|
||||||
|
# Tells whether to display a full report or only the messages
|
||||||
|
reports=no
|
||||||
|
|
||||||
|
# Python expression which should return a note less than 10 (10 is the highest
|
||||||
|
# note). You have access to the variables errors warning, statement which
|
||||||
|
# respectively contain the number of errors / warnings messages and the total
|
||||||
|
# number of statements analyzed. This is used by the global evaluation report
|
||||||
|
# (RP0004).
|
||||||
|
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||||
|
|
||||||
|
# Template used to display messages. This is a python new-style format string
|
||||||
|
# used to format the message information. See doc for all details
|
||||||
|
#msg-template=
|
||||||
|
|
||||||
|
|
||||||
|
[BASIC]
|
||||||
|
|
||||||
|
# Good variable names which should always be accepted, separated by a comma
|
||||||
|
good-names=main,_,PRESUBMIT
|
||||||
|
|
||||||
|
# Bad variable names which should always be refused, separated by a comma
|
||||||
|
bad-names=
|
||||||
|
|
||||||
|
# Colon-delimited sets of names that determine each other's naming style when
|
||||||
|
# the name regexes allow several styles.
|
||||||
|
name-group=
|
||||||
|
|
||||||
|
# Include a hint for the correct naming format with invalid-name
|
||||||
|
include-naming-hint=no
|
||||||
|
|
||||||
|
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||||
|
# to this list to register other decorators that produce valid properties.
|
||||||
|
property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl
|
||||||
|
|
||||||
|
# Regular expression matching correct function names
|
||||||
|
function-rgx=^(?:(?P<exempt>setUp|tearDown|setUpModule|tearDownModule)|(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$
|
||||||
|
|
||||||
|
# Regular expression matching correct variable names
|
||||||
|
variable-rgx=^[a-z][a-z0-9_]*$
|
||||||
|
|
||||||
|
# Regular expression matching correct constant names
|
||||||
|
const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
|
||||||
|
|
||||||
|
# Regular expression matching correct attribute names
|
||||||
|
attr-rgx=^_{0,2}[a-z][a-z0-9_]*$
|
||||||
|
|
||||||
|
# Regular expression matching correct argument names
|
||||||
|
argument-rgx=^[a-z][a-z0-9_]*$
|
||||||
|
|
||||||
|
# Regular expression matching correct class attribute names
|
||||||
|
class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
|
||||||
|
|
||||||
|
# Regular expression matching correct inline iteration names
|
||||||
|
inlinevar-rgx=^[a-z][a-z0-9_]*$
|
||||||
|
|
||||||
|
# Regular expression matching correct class names
|
||||||
|
class-rgx=^_?[A-Z][a-zA-Z0-9]*$
|
||||||
|
|
||||||
|
# Regular expression matching correct module names
|
||||||
|
module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$
|
||||||
|
|
||||||
|
# Regular expression matching correct method names
|
||||||
|
method-rgx=(?x)^(?:(?P<exempt>_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$
|
||||||
|
|
||||||
|
# Regular expression which should only match function or class names that do
|
||||||
|
# not require a docstring.
|
||||||
|
no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$
|
||||||
|
|
||||||
|
# Minimum line length for functions/classes that require docstrings, shorter
|
||||||
|
# ones are exempt.
|
||||||
|
docstring-min-length=10
|
||||||
|
|
||||||
|
|
||||||
|
[TYPECHECK]
|
||||||
|
|
||||||
|
# List of decorators that produce context managers, such as
|
||||||
|
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||||
|
# produce valid context managers.
|
||||||
|
contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
|
||||||
|
|
||||||
|
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||||
|
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||||
|
ignore-mixin-members=yes
|
||||||
|
|
||||||
|
# List of module names for which member attributes should not be checked
|
||||||
|
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||||
|
# and thus existing member attributes cannot be deduced by static analysis. It
|
||||||
|
# supports qualified module names, as well as Unix pattern matching.
|
||||||
|
ignored-modules=
|
||||||
|
|
||||||
|
# List of class names for which member attributes should not be checked (useful
|
||||||
|
# for classes with dynamically set attributes). This supports the use of
|
||||||
|
# qualified names.
|
||||||
|
ignored-classes=optparse.Values,thread._local,_thread._local
|
||||||
|
|
||||||
|
# List of members which are set dynamically and missed by pylint inference
|
||||||
|
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||||
|
# expressions are accepted.
|
||||||
|
generated-members=
|
||||||
|
|
||||||
|
|
||||||
|
[FORMAT]
|
||||||
|
|
||||||
|
# Maximum number of characters on a single line.
|
||||||
|
max-line-length=80
|
||||||
|
|
||||||
|
# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt
|
||||||
|
# lines made too long by directives to pytype.
|
||||||
|
|
||||||
|
# Regexp for a line that is allowed to be longer than the limit.
|
||||||
|
ignore-long-lines=(?x)(
|
||||||
|
^\s*(\#\ )?<?https?://\S+>?$|
|
||||||
|
^\s*(from\s+\S+\s+)?import\s+.+$)
|
||||||
|
|
||||||
|
# Allow the body of an if to be on the same line as the test if there is no
|
||||||
|
# else.
|
||||||
|
single-line-if-stmt=yes
|
||||||
|
|
||||||
|
# List of optional constructs for which whitespace checking is disabled. `dict-
|
||||||
|
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
|
||||||
|
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
|
||||||
|
# `empty-line` allows space-only lines.
|
||||||
|
no-space-check=
|
||||||
|
|
||||||
|
# Maximum number of lines in a module
|
||||||
|
max-module-lines=99999
|
||||||
|
|
||||||
|
# String used as indentation unit. The internal Google style guide mandates 2
|
||||||
|
# spaces. Google's externaly-published style guide says 4, consistent with
|
||||||
|
# PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google
|
||||||
|
# projects (like TensorFlow).
|
||||||
|
indent-string=' '
|
||||||
|
|
||||||
|
# Number of spaces of indent required inside a hanging or continued line.
|
||||||
|
indent-after-paren=4
|
||||||
|
|
||||||
|
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||||
|
expected-line-ending-format=
|
||||||
|
|
||||||
|
|
||||||
|
[MISCELLANEOUS]
|
||||||
|
|
||||||
|
# List of note tags to take in consideration, separated by a comma.
|
||||||
|
notes=TODO
|
||||||
|
|
||||||
|
|
||||||
|
[STRING]
|
||||||
|
|
||||||
|
# This flag controls whether inconsistent-quotes generates a warning when the
|
||||||
|
# character used as a quote delimiter is used inconsistently within a module.
|
||||||
|
check-quote-consistency=yes
|
||||||
|
|
||||||
|
|
||||||
|
[VARIABLES]
|
||||||
|
|
||||||
|
# Tells whether we should check for unused import in __init__ files.
|
||||||
|
init-import=no
|
||||||
|
|
||||||
|
# A regular expression matching the name of dummy variables (i.e. expectedly
|
||||||
|
# not used).
|
||||||
|
dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)
|
||||||
|
|
||||||
|
# List of additional names supposed to be defined in builtins. Remember that
|
||||||
|
# you should avoid to define new builtins when possible.
|
||||||
|
additional-builtins=
|
||||||
|
|
||||||
|
# List of strings which can identify a callback function by name. A callback
|
||||||
|
# name must start or end with one of those strings.
|
||||||
|
callbacks=cb_,_cb
|
||||||
|
|
||||||
|
# List of qualified module names which can have objects that can redefine
|
||||||
|
# builtins.
|
||||||
|
redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools
|
||||||
|
|
||||||
|
|
||||||
|
[LOGGING]
|
||||||
|
|
||||||
|
# Logging modules to check that the string format arguments are in logging
|
||||||
|
# function parameter format
|
||||||
|
logging-modules=logging,absl.logging,tensorflow.io.logging
|
||||||
|
|
||||||
|
|
||||||
|
[SIMILARITIES]
|
||||||
|
|
||||||
|
# Minimum lines number of a similarity.
|
||||||
|
min-similarity-lines=4
|
||||||
|
|
||||||
|
# Ignore comments when computing similarities.
|
||||||
|
ignore-comments=yes
|
||||||
|
|
||||||
|
# Ignore docstrings when computing similarities.
|
||||||
|
ignore-docstrings=yes
|
||||||
|
|
||||||
|
# Ignore imports when computing similarities.
|
||||||
|
ignore-imports=no
|
||||||
|
|
||||||
|
|
||||||
|
[SPELLING]
|
||||||
|
|
||||||
|
# Spelling dictionary name. Available dictionaries: none. To make it working
|
||||||
|
# install python-enchant package.
|
||||||
|
spelling-dict=
|
||||||
|
|
||||||
|
# List of comma separated words that should not be checked.
|
||||||
|
spelling-ignore-words=
|
||||||
|
|
||||||
|
# A path to a file that contains private dictionary; one word per line.
|
||||||
|
spelling-private-dict-file=
|
||||||
|
|
||||||
|
# Tells whether to store unknown words to indicated private dictionary in
|
||||||
|
# --spelling-private-dict-file option instead of raising a message.
|
||||||
|
spelling-store-unknown-words=no
|
||||||
|
|
||||||
|
|
||||||
|
[IMPORTS]
|
||||||
|
|
||||||
|
# Deprecated modules which should not be used, separated by a comma
|
||||||
|
deprecated-modules=regsub,
|
||||||
|
TERMIOS,
|
||||||
|
Bastion,
|
||||||
|
rexec,
|
||||||
|
sets
|
||||||
|
|
||||||
|
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||||
|
# given file (report RP0402 must not be disabled)
|
||||||
|
import-graph=
|
||||||
|
|
||||||
|
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||||
|
# not be disabled)
|
||||||
|
ext-import-graph=
|
||||||
|
|
||||||
|
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||||
|
# not be disabled)
|
||||||
|
int-import-graph=
|
||||||
|
|
||||||
|
# Force import order to recognize a module as part of the standard
|
||||||
|
# compatibility libraries.
|
||||||
|
known-standard-library=
|
||||||
|
|
||||||
|
# Force import order to recognize a module as part of a third party library.
|
||||||
|
known-third-party=enchant, absl
|
||||||
|
|
||||||
|
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||||
|
# 3 compatible code, which means that the block might have code that exists
|
||||||
|
# only in one or another interpreter, leading to false positives when analysed.
|
||||||
|
analyse-fallback-blocks=no
|
||||||
|
|
||||||
|
|
||||||
|
[CLASSES]
|
||||||
|
|
||||||
|
# List of method names used to declare (i.e. assign) instance attributes.
|
||||||
|
defining-attr-methods=__init__,
|
||||||
|
__new__,
|
||||||
|
setUp
|
||||||
|
|
||||||
|
# List of member names, which should be excluded from the protected access
|
||||||
|
# warning.
|
||||||
|
exclude-protected=_asdict,
|
||||||
|
_fields,
|
||||||
|
_replace,
|
||||||
|
_source,
|
||||||
|
_make
|
||||||
|
|
||||||
|
# List of valid names for the first argument in a class method.
|
||||||
|
valid-classmethod-first-arg=cls,
|
||||||
|
class_
|
||||||
|
|
||||||
|
# List of valid names for the first argument in a metaclass class method.
|
||||||
|
valid-metaclass-classmethod-first-arg=mcs
|
||||||
|
|
||||||
|
|
||||||
|
[EXCEPTIONS]
|
||||||
|
|
||||||
|
# Exceptions that will emit a warning when being caught. Defaults to
|
||||||
|
# "Exception"
|
||||||
|
overgeneral-exceptions=StandardError,
|
||||||
|
Exception,
|
||||||
|
BaseException
|
||||||
2
.style.yapf
Normal file
2
.style.yapf
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[style]
|
||||||
|
based_on_style = chromium
|
||||||
21
AUTHORS
21
AUTHORS
@@ -1,19 +1,34 @@
|
|||||||
Contributors:
|
Contributors:
|
||||||
|
- Aidan O'Loan (aidanol at gmail dot com)
|
||||||
|
- Alan Browning (browning at google dot com)
|
||||||
- Charles Munger (clm 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)
|
- 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)
|
- Djordje Pesut (djordje dot pesut at imgtec dot com)
|
||||||
|
- Hui Su (huisu at google dot com)
|
||||||
|
- Ilya Kurdyukov (jpegqs at gmail dot com)
|
||||||
|
- Ingvar Stepanyan (rreverser at google dot com)
|
||||||
- James Zern (jzern at google dot com)
|
- James Zern (jzern at google dot com)
|
||||||
- Jan Engelhardt (jengelh at medozas dot de)
|
- Jan Engelhardt (jengelh at medozas dot de)
|
||||||
- Johann (johann dot koenig at duck dot com)
|
- Jehan (jehan at girinstud dot io)
|
||||||
|
- Johann Koenig (johann dot koenig at duck dot com)
|
||||||
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
|
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
|
||||||
- Jyrki Alakuijala (jyrki at google dot com)
|
- Jyrki Alakuijala (jyrki at google dot com)
|
||||||
|
- Konstantin Ivlev (tomskside at gmail dot com)
|
||||||
- Lode Vandevenne (lode at google dot com)
|
- Lode Vandevenne (lode at google dot com)
|
||||||
- Lou Quillio (louquillio at google dot com)
|
- Lou Quillio (louquillio at google dot com)
|
||||||
- Mans Rullgard (mans at mansr dot com)
|
- Mans Rullgard (mans at mansr dot com)
|
||||||
|
- Marcin Kowalczyk (qrczak at google dot com)
|
||||||
- Martin Olsson (mnemo at minimum dot se)
|
- Martin Olsson (mnemo at minimum dot se)
|
||||||
- Mikołaj Zalewski (mikolajz at google dot com)
|
- Mikołaj Zalewski (mikolajz at google dot com)
|
||||||
- Mislav Bradac (mislavm at google dot com)
|
- Mislav Bradac (mislavm at google dot com)
|
||||||
|
- Nico Weber (thakis at chromium dot org)
|
||||||
- Noel Chromium (noel at chromium dot org)
|
- Noel Chromium (noel at chromium dot org)
|
||||||
|
- Oliver Wolff (oliver dot wolff at qt dot io)
|
||||||
|
- Owen Rodley (orodley at google dot com)
|
||||||
|
- Parag Salasakar (img dot mips1 at gmail dot com)
|
||||||
- Pascal Massimino (pascal dot massimino at gmail dot com)
|
- Pascal Massimino (pascal dot massimino at gmail dot com)
|
||||||
- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org)
|
- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org)
|
||||||
- Pierre Joye (pierre dot php at gmail dot com)
|
- Pierre Joye (pierre dot php at gmail dot com)
|
||||||
@@ -29,4 +44,8 @@ Contributors:
|
|||||||
- Urvang Joshi (urvang at google dot com)
|
- Urvang Joshi (urvang at google dot com)
|
||||||
- Vikas Arora (vikasa at google dot com)
|
- Vikas Arora (vikasa at google dot com)
|
||||||
- Vincent Rabaud (vrabaud at google dot com)
|
- Vincent Rabaud (vrabaud at google dot com)
|
||||||
|
- Vlad Tsyrklevich (vtsyrklevich at chromium dot org)
|
||||||
|
- Wan-Teh Chang (wtc at google dot com)
|
||||||
- Yang Zhang (yang dot zhang at arm dot com)
|
- Yang Zhang (yang dot zhang at arm dot com)
|
||||||
|
- Yannis Guyon (yguyon at google dot com)
|
||||||
|
- Zhi An Ng (zhin at chromium dot org)
|
||||||
|
|||||||
132
Android.mk
132
Android.mk
@@ -1,6 +1,7 @@
|
|||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
WEBP_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD
|
WEBP_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD
|
||||||
|
WEBP_CFLAGS += -fvisibility=hidden
|
||||||
|
|
||||||
ifeq ($(APP_OPTIM),release)
|
ifeq ($(APP_OPTIM),release)
|
||||||
WEBP_CFLAGS += -finline-functions -ffast-math \
|
WEBP_CFLAGS += -finline-functions -ffast-math \
|
||||||
@@ -10,27 +11,39 @@ ifeq ($(APP_OPTIM),release)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# mips32 fails to build with clang from r14b
|
||||||
|
# https://bugs.chromium.org/p/webp/issues/detail?id=343
|
||||||
|
ifeq ($(findstring clang,$(NDK_TOOLCHAIN_VERSION)),clang)
|
||||||
|
ifeq ($(TARGET_ARCH),mips)
|
||||||
|
clang_version := $(shell $(TARGET_CC) --version)
|
||||||
|
ifneq ($(findstring clang version 3,$(clang_version)),)
|
||||||
|
WEBP_CFLAGS += -no-integrated-as
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),)
|
ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),)
|
||||||
# Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal
|
# Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal
|
||||||
# instructions to be generated for armv7a code. Instead target the neon code
|
# instructions to be generated for armv7a code. Instead target the neon code
|
||||||
# specifically.
|
# specifically.
|
||||||
NEON := c.neon
|
NEON := c.neon
|
||||||
USE_CPUFEATURES := yes
|
USE_CPUFEATURES := yes
|
||||||
|
WEBP_CFLAGS += -DHAVE_CPU_FEATURES_H
|
||||||
else
|
else
|
||||||
NEON := c
|
NEON := c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dec_srcs := \
|
dec_srcs := \
|
||||||
src/dec/alpha.c \
|
src/dec/alpha_dec.c \
|
||||||
src/dec/buffer.c \
|
src/dec/buffer_dec.c \
|
||||||
src/dec/frame.c \
|
src/dec/frame_dec.c \
|
||||||
src/dec/idec.c \
|
src/dec/idec_dec.c \
|
||||||
src/dec/io.c \
|
src/dec/io_dec.c \
|
||||||
src/dec/quant.c \
|
src/dec/quant_dec.c \
|
||||||
src/dec/tree.c \
|
src/dec/tree_dec.c \
|
||||||
src/dec/vp8.c \
|
src/dec/vp8_dec.c \
|
||||||
src/dec/vp8l.c \
|
src/dec/vp8l_dec.c \
|
||||||
src/dec/webp.c \
|
src/dec/webp_dec.c \
|
||||||
|
|
||||||
demux_srcs := \
|
demux_srcs := \
|
||||||
src/demux/anim_decode.c \
|
src/demux/anim_decode.c \
|
||||||
@@ -39,82 +52,95 @@ demux_srcs := \
|
|||||||
dsp_dec_srcs := \
|
dsp_dec_srcs := \
|
||||||
src/dsp/alpha_processing.c \
|
src/dsp/alpha_processing.c \
|
||||||
src/dsp/alpha_processing_mips_dsp_r2.c \
|
src/dsp/alpha_processing_mips_dsp_r2.c \
|
||||||
|
src/dsp/alpha_processing_neon.$(NEON) \
|
||||||
src/dsp/alpha_processing_sse2.c \
|
src/dsp/alpha_processing_sse2.c \
|
||||||
src/dsp/alpha_processing_sse41.c \
|
src/dsp/alpha_processing_sse41.c \
|
||||||
src/dsp/argb.c \
|
|
||||||
src/dsp/argb_mips_dsp_r2.c \
|
|
||||||
src/dsp/argb_sse2.c \
|
|
||||||
src/dsp/cpu.c \
|
src/dsp/cpu.c \
|
||||||
src/dsp/dec.c \
|
src/dsp/dec.c \
|
||||||
src/dsp/dec_clip_tables.c \
|
src/dsp/dec_clip_tables.c \
|
||||||
src/dsp/dec_mips32.c \
|
src/dsp/dec_mips32.c \
|
||||||
src/dsp/dec_mips_dsp_r2.c \
|
src/dsp/dec_mips_dsp_r2.c \
|
||||||
|
src/dsp/dec_msa.c \
|
||||||
src/dsp/dec_neon.$(NEON) \
|
src/dsp/dec_neon.$(NEON) \
|
||||||
src/dsp/dec_sse2.c \
|
src/dsp/dec_sse2.c \
|
||||||
src/dsp/dec_sse41.c \
|
src/dsp/dec_sse41.c \
|
||||||
src/dsp/filters.c \
|
src/dsp/filters.c \
|
||||||
src/dsp/filters_mips_dsp_r2.c \
|
src/dsp/filters_mips_dsp_r2.c \
|
||||||
|
src/dsp/filters_msa.c \
|
||||||
|
src/dsp/filters_neon.$(NEON) \
|
||||||
src/dsp/filters_sse2.c \
|
src/dsp/filters_sse2.c \
|
||||||
src/dsp/lossless.c \
|
src/dsp/lossless.c \
|
||||||
src/dsp/lossless_mips_dsp_r2.c \
|
src/dsp/lossless_mips_dsp_r2.c \
|
||||||
|
src/dsp/lossless_msa.c \
|
||||||
src/dsp/lossless_neon.$(NEON) \
|
src/dsp/lossless_neon.$(NEON) \
|
||||||
src/dsp/lossless_sse2.c \
|
src/dsp/lossless_sse2.c \
|
||||||
|
src/dsp/lossless_sse41.c \
|
||||||
src/dsp/rescaler.c \
|
src/dsp/rescaler.c \
|
||||||
src/dsp/rescaler_mips32.c \
|
src/dsp/rescaler_mips32.c \
|
||||||
src/dsp/rescaler_mips_dsp_r2.c \
|
src/dsp/rescaler_mips_dsp_r2.c \
|
||||||
|
src/dsp/rescaler_msa.c \
|
||||||
src/dsp/rescaler_neon.$(NEON) \
|
src/dsp/rescaler_neon.$(NEON) \
|
||||||
src/dsp/rescaler_sse2.c \
|
src/dsp/rescaler_sse2.c \
|
||||||
src/dsp/upsampling.c \
|
src/dsp/upsampling.c \
|
||||||
src/dsp/upsampling_mips_dsp_r2.c \
|
src/dsp/upsampling_mips_dsp_r2.c \
|
||||||
|
src/dsp/upsampling_msa.c \
|
||||||
src/dsp/upsampling_neon.$(NEON) \
|
src/dsp/upsampling_neon.$(NEON) \
|
||||||
src/dsp/upsampling_sse2.c \
|
src/dsp/upsampling_sse2.c \
|
||||||
|
src/dsp/upsampling_sse41.c \
|
||||||
src/dsp/yuv.c \
|
src/dsp/yuv.c \
|
||||||
src/dsp/yuv_mips32.c \
|
src/dsp/yuv_mips32.c \
|
||||||
src/dsp/yuv_mips_dsp_r2.c \
|
src/dsp/yuv_mips_dsp_r2.c \
|
||||||
|
src/dsp/yuv_neon.$(NEON) \
|
||||||
src/dsp/yuv_sse2.c \
|
src/dsp/yuv_sse2.c \
|
||||||
|
src/dsp/yuv_sse41.c \
|
||||||
|
|
||||||
dsp_enc_srcs := \
|
dsp_enc_srcs := \
|
||||||
src/dsp/cost.c \
|
src/dsp/cost.c \
|
||||||
src/dsp/cost_mips32.c \
|
src/dsp/cost_mips32.c \
|
||||||
src/dsp/cost_mips_dsp_r2.c \
|
src/dsp/cost_mips_dsp_r2.c \
|
||||||
|
src/dsp/cost_neon.$(NEON) \
|
||||||
src/dsp/cost_sse2.c \
|
src/dsp/cost_sse2.c \
|
||||||
src/dsp/enc.c \
|
src/dsp/enc.c \
|
||||||
src/dsp/enc_avx2.c \
|
|
||||||
src/dsp/enc_mips32.c \
|
src/dsp/enc_mips32.c \
|
||||||
src/dsp/enc_mips_dsp_r2.c \
|
src/dsp/enc_mips_dsp_r2.c \
|
||||||
|
src/dsp/enc_msa.c \
|
||||||
src/dsp/enc_neon.$(NEON) \
|
src/dsp/enc_neon.$(NEON) \
|
||||||
src/dsp/enc_sse2.c \
|
src/dsp/enc_sse2.c \
|
||||||
src/dsp/enc_sse41.c \
|
src/dsp/enc_sse41.c \
|
||||||
src/dsp/lossless_enc.c \
|
src/dsp/lossless_enc.c \
|
||||||
src/dsp/lossless_enc_mips32.c \
|
src/dsp/lossless_enc_mips32.c \
|
||||||
src/dsp/lossless_enc_mips_dsp_r2.c \
|
src/dsp/lossless_enc_mips_dsp_r2.c \
|
||||||
|
src/dsp/lossless_enc_msa.c \
|
||||||
src/dsp/lossless_enc_neon.$(NEON) \
|
src/dsp/lossless_enc_neon.$(NEON) \
|
||||||
src/dsp/lossless_enc_sse2.c \
|
src/dsp/lossless_enc_sse2.c \
|
||||||
src/dsp/lossless_enc_sse41.c \
|
src/dsp/lossless_enc_sse41.c \
|
||||||
|
src/dsp/ssim.c \
|
||||||
|
src/dsp/ssim_sse2.c \
|
||||||
|
|
||||||
enc_srcs := \
|
enc_srcs := \
|
||||||
src/enc/alpha.c \
|
src/enc/alpha_enc.c \
|
||||||
src/enc/analysis.c \
|
src/enc/analysis_enc.c \
|
||||||
src/enc/backward_references.c \
|
src/enc/backward_references_cost_enc.c \
|
||||||
src/enc/config.c \
|
src/enc/backward_references_enc.c \
|
||||||
src/enc/cost.c \
|
src/enc/config_enc.c \
|
||||||
src/enc/delta_palettization.c \
|
src/enc/cost_enc.c \
|
||||||
src/enc/filter.c \
|
src/enc/filter_enc.c \
|
||||||
src/enc/frame.c \
|
src/enc/frame_enc.c \
|
||||||
src/enc/histogram.c \
|
src/enc/histogram_enc.c \
|
||||||
src/enc/iterator.c \
|
src/enc/iterator_enc.c \
|
||||||
src/enc/near_lossless.c \
|
src/enc/near_lossless_enc.c \
|
||||||
src/enc/picture.c \
|
src/enc/picture_enc.c \
|
||||||
src/enc/picture_csp.c \
|
src/enc/picture_csp_enc.c \
|
||||||
src/enc/picture_psnr.c \
|
src/enc/picture_psnr_enc.c \
|
||||||
src/enc/picture_rescale.c \
|
src/enc/picture_rescale_enc.c \
|
||||||
src/enc/picture_tools.c \
|
src/enc/picture_tools_enc.c \
|
||||||
src/enc/quant.c \
|
src/enc/predictor_enc.c \
|
||||||
src/enc/syntax.c \
|
src/enc/quant_enc.c \
|
||||||
src/enc/token.c \
|
src/enc/syntax_enc.c \
|
||||||
src/enc/tree.c \
|
src/enc/token_enc.c \
|
||||||
src/enc/vp8l.c \
|
src/enc/tree_enc.c \
|
||||||
src/enc/webpenc.c \
|
src/enc/vp8l_enc.c \
|
||||||
|
src/enc/webp_enc.c \
|
||||||
|
|
||||||
mux_srcs := \
|
mux_srcs := \
|
||||||
src/mux/anim_encode.c \
|
src/mux/anim_encode.c \
|
||||||
@@ -123,20 +149,20 @@ mux_srcs := \
|
|||||||
src/mux/muxread.c \
|
src/mux/muxread.c \
|
||||||
|
|
||||||
utils_dec_srcs := \
|
utils_dec_srcs := \
|
||||||
src/utils/bit_reader.c \
|
src/utils/bit_reader_utils.c \
|
||||||
src/utils/color_cache.c \
|
src/utils/color_cache_utils.c \
|
||||||
src/utils/filters.c \
|
src/utils/filters_utils.c \
|
||||||
src/utils/huffman.c \
|
src/utils/huffman_utils.c \
|
||||||
src/utils/quant_levels_dec.c \
|
src/utils/quant_levels_dec_utils.c \
|
||||||
src/utils/random.c \
|
src/utils/random_utils.c \
|
||||||
src/utils/rescaler.c \
|
src/utils/rescaler_utils.c \
|
||||||
src/utils/thread.c \
|
src/utils/thread_utils.c \
|
||||||
src/utils/utils.c \
|
src/utils/utils.c \
|
||||||
|
|
||||||
utils_enc_srcs := \
|
utils_enc_srcs := \
|
||||||
src/utils/bit_writer.c \
|
src/utils/bit_writer_utils.c \
|
||||||
src/utils/huffman_encode.c \
|
src/utils/huffman_encode_utils.c \
|
||||||
src/utils/quant_levels.c \
|
src/utils/quant_levels_utils.c \
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# libwebpdecoder
|
# libwebpdecoder
|
||||||
@@ -149,7 +175,7 @@ LOCAL_SRC_FILES := \
|
|||||||
$(utils_dec_srcs) \
|
$(utils_dec_srcs) \
|
||||||
|
|
||||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
|
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
|
||||||
|
|
||||||
# prefer arm over thumb mode for performance gains
|
# prefer arm over thumb mode for performance gains
|
||||||
LOCAL_ARM_MODE := arm
|
LOCAL_ARM_MODE := arm
|
||||||
@@ -183,7 +209,7 @@ LOCAL_SRC_FILES := \
|
|||||||
$(utils_enc_srcs) \
|
$(utils_enc_srcs) \
|
||||||
|
|
||||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
|
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
|
||||||
|
|
||||||
# prefer arm over thumb mode for performance gains
|
# prefer arm over thumb mode for performance gains
|
||||||
LOCAL_ARM_MODE := arm
|
LOCAL_ARM_MODE := arm
|
||||||
@@ -206,7 +232,7 @@ include $(CLEAR_VARS)
|
|||||||
LOCAL_SRC_FILES := $(demux_srcs)
|
LOCAL_SRC_FILES := $(demux_srcs)
|
||||||
|
|
||||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
|
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
|
||||||
|
|
||||||
# prefer arm over thumb mode for performance gains
|
# prefer arm over thumb mode for performance gains
|
||||||
LOCAL_ARM_MODE := arm
|
LOCAL_ARM_MODE := arm
|
||||||
@@ -229,7 +255,7 @@ include $(CLEAR_VARS)
|
|||||||
LOCAL_SRC_FILES := $(mux_srcs)
|
LOCAL_SRC_FILES := $(mux_srcs)
|
||||||
|
|
||||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
|
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/src
|
||||||
|
|
||||||
# prefer arm over thumb mode for performance gains
|
# prefer arm over thumb mode for performance gains
|
||||||
LOCAL_ARM_MODE := arm
|
LOCAL_ARM_MODE := arm
|
||||||
@@ -246,7 +272,9 @@ endif
|
|||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
include $(LOCAL_PATH)/examples/Android.mk
|
WEBP_SRC_PATH := $(LOCAL_PATH)
|
||||||
|
include $(WEBP_SRC_PATH)/imageio/Android.mk
|
||||||
|
include $(WEBP_SRC_PATH)/examples/Android.mk
|
||||||
|
|
||||||
ifeq ($(USE_CPUFEATURES),yes)
|
ifeq ($(USE_CPUFEATURES),yes)
|
||||||
$(call import-module,android/cpufeatures)
|
$(call import-module,android/cpufeatures)
|
||||||
|
|||||||
737
CMakeLists.txt
Normal file
737
CMakeLists.txt
Normal file
@@ -0,0 +1,737 @@
|
|||||||
|
# Copyright (c) 2020 Google LLC.
|
||||||
|
#
|
||||||
|
# Use of this source code is governed by a BSD-style license
|
||||||
|
# that can be found in the LICENSE file in the root of the source
|
||||||
|
# tree. An additional intellectual property rights grant can be found
|
||||||
|
# in the file PATENTS. All contributing project authors may
|
||||||
|
# be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.7)
|
||||||
|
|
||||||
|
if(POLICY CMP0072)
|
||||||
|
cmake_policy(SET CMP0072 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
project(WebP C)
|
||||||
|
|
||||||
|
# Options for coder / decoder executables.
|
||||||
|
if(NOT EMSCRIPTEN)
|
||||||
|
# Disable SIMD on Emscripten by default, as it's a new unstable Wasm feature.
|
||||||
|
# Users can still explicitly opt-in to make a SIMD-enabled build.
|
||||||
|
set(WEBP_ENABLE_SIMD_DEFAULT ON)
|
||||||
|
endif()
|
||||||
|
option(WEBP_ENABLE_SIMD "Enable any SIMD optimization."
|
||||||
|
${WEBP_ENABLE_SIMD_DEFAULT})
|
||||||
|
# Emscripten supports SSE builds using its compatibility headers, by default it
|
||||||
|
# will use SSE4 if WEBP_ENABLE_WASM_SIMD is OFF and WEBP_ENABLE_SIMD is ON.
|
||||||
|
option(WEBP_ENABLE_WASM_SIMD "Enable WebAssembly SIMD optimizations" OFF)
|
||||||
|
option(WEBP_BUILD_ANIM_UTILS "Build animation utilities." ON)
|
||||||
|
option(WEBP_BUILD_CWEBP "Build the cwebp command line tool." ON)
|
||||||
|
option(WEBP_BUILD_DWEBP "Build the dwebp command line tool." ON)
|
||||||
|
option(WEBP_BUILD_GIF2WEBP "Build the gif2webp conversion tool." ON)
|
||||||
|
option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." ON)
|
||||||
|
option(WEBP_BUILD_VWEBP "Build the vwebp viewer tool." ON)
|
||||||
|
option(WEBP_BUILD_WEBPINFO "Build the webpinfo command line tool." ON)
|
||||||
|
option(WEBP_BUILD_LIBWEBPMUX "Build the libwebpmux library." ON)
|
||||||
|
option(WEBP_BUILD_WEBPMUX "Build the webpmux command line tool." ON)
|
||||||
|
option(WEBP_BUILD_EXTRAS "Build extras." ON)
|
||||||
|
option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF)
|
||||||
|
option(WEBP_USE_THREAD "Enable threading support" ON)
|
||||||
|
option(WEBP_NEAR_LOSSLESS "Enable near-lossless encoding" ON)
|
||||||
|
option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces."
|
||||||
|
OFF)
|
||||||
|
set(WEBP_BITTRACE "0" CACHE STRING "Bit trace mode (0=none, 1=bit, 2=bytes)")
|
||||||
|
set_property(CACHE WEBP_BITTRACE PROPERTY STRINGS 0 1 2)
|
||||||
|
|
||||||
|
# Option needed for handling Unicode file names on Windows.
|
||||||
|
if(WIN32)
|
||||||
|
option(WEBP_UNICODE "Build Unicode executables." ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_WEBP_JS)
|
||||||
|
set(WEBP_BUILD_ANIM_UTILS OFF)
|
||||||
|
set(WEBP_BUILD_CWEBP OFF)
|
||||||
|
set(WEBP_BUILD_GIF2WEBP OFF)
|
||||||
|
set(WEBP_BUILD_IMG2WEBP OFF)
|
||||||
|
set(WEBP_BUILD_VWEBP OFF)
|
||||||
|
set(WEBP_BUILD_WEBPINFO OFF)
|
||||||
|
set(WEBP_BUILD_WEBPMUX OFF)
|
||||||
|
set(WEBP_BUILD_EXTRAS OFF)
|
||||||
|
set(WEBP_USE_THREAD OFF)
|
||||||
|
|
||||||
|
if(WEBP_ENABLE_SIMD)
|
||||||
|
message("wasm2js does not support SIMD, disabling webp.js generation.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(WEBP_DEP_LIBRARIES)
|
||||||
|
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)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Include dependencies.
|
||||||
|
include(cmake/deps.cmake)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
# ##############################################################################
|
||||||
|
# Options.
|
||||||
|
if(WEBP_ENABLE_SWAP_16BIT_CSP)
|
||||||
|
add_definitions(-DWEBP_SWAP_16BIT_CSP=1)
|
||||||
|
endif()
|
||||||
|
if(WEBP_ENABLE_WASM_SIMD)
|
||||||
|
add_definitions(-DWEBP_ENABLE_WASM_SIMD_INTRINSICS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT WEBP_BITTRACE STREQUAL "0")
|
||||||
|
add_definitions(-DBITTRACE=${WEBP_BITTRACE})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_UNICODE)
|
||||||
|
# Windows recommends setting both UNICODE and _UNICODE.
|
||||||
|
add_definitions(-DUNICODE -D_UNICODE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||||
|
set(exec_prefix "\$\{prefix\}")
|
||||||
|
set(libdir "\$\{prefix\}/lib")
|
||||||
|
set(includedir "\$\{prefix\}/include")
|
||||||
|
set(PTHREAD_LIBS ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
set(INSTALLED_LIBRARIES)
|
||||||
|
|
||||||
|
# ##############################################################################
|
||||||
|
# Android only.
|
||||||
|
if(ANDROID)
|
||||||
|
include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
|
||||||
|
add_library(cpufeatures STATIC
|
||||||
|
${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
|
||||||
|
list(APPEND INSTALLED_LIBRARIES cpufeatures)
|
||||||
|
target_link_libraries(cpufeatures dl)
|
||||||
|
set(WEBP_DEP_LIBRARIES ${WEBP_DEP_LIBRARIES} cpufeatures)
|
||||||
|
set(WEBP_DEP_INCLUDE_DIRS ${WEBP_DEP_INCLUDE_DIRS}
|
||||||
|
${ANDROID_NDK}/sources/android/cpufeatures)
|
||||||
|
add_definitions(-DHAVE_CPU_FEATURES_H=1)
|
||||||
|
set(HAVE_CPU_FEATURES_H 1)
|
||||||
|
else()
|
||||||
|
set(HAVE_CPU_FEATURES_H 0)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
function(configure_pkg_config FILE)
|
||||||
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${FILE}")
|
||||||
|
|
||||||
|
if(HAVE_MATH_LIBRARY)
|
||||||
|
# MSVC doesn't have libm
|
||||||
|
file(READ ${CMAKE_CURRENT_BINARY_DIR}/${FILE} data)
|
||||||
|
string(REPLACE "-lm" "" data ${data})
|
||||||
|
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${FILE} ${data})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES "${CMAKE_CURRENT_BINARY_DIR}/${FILE}"
|
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# ##############################################################################
|
||||||
|
# WebP source files. Read the Makefile.am to get the source files.
|
||||||
|
|
||||||
|
# We expect the Makefiles to define the sources as defined in the first regex.
|
||||||
|
# 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})
|
||||||
|
set(SRCS ${${VAR}})
|
||||||
|
foreach(FILES ${FILES_PER_LINE})
|
||||||
|
string(FIND ${FILES} "=" OFFSET)
|
||||||
|
math(EXPR OFFSET "${OFFSET} + 2")
|
||||||
|
string(SUBSTRING ${FILES}
|
||||||
|
${OFFSET}
|
||||||
|
-1
|
||||||
|
FILES)
|
||||||
|
if(FILES)
|
||||||
|
string(REGEX MATCHALL
|
||||||
|
"[0-9a-z\\._]+"
|
||||||
|
FILES
|
||||||
|
${FILES})
|
||||||
|
foreach(FILE ${FILES})
|
||||||
|
list(APPEND SRCS ${FOLDER}/${FILE})
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
set(${VAR} ${SRCS} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
set(WEBP_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/dec "WEBP_DEC_SRCS" "")
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/demux "WEBP_DEMUX_SRCS" "")
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_COMMON_SRCS" "COMMON")
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "ENC")
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_ENC_SRCS" "dsp_[^ ]*")
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/dsp "WEBP_DSP_DEC_SRCS" "decode_[^ ]*")
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/enc "WEBP_ENC_SRCS" "")
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_COMMON_SRCS" "COMMON")
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_ENC_SRCS" "ENC")
|
||||||
|
parse_makefile_am(${WEBP_SRC_DIR}/utils "WEBP_UTILS_DEC_SRCS" "decode_[^ ]*")
|
||||||
|
|
||||||
|
# Remove the files specific to SIMD we don't use.
|
||||||
|
foreach(FILE ${WEBP_SIMD_FILES_NOT_TO_INCLUDE})
|
||||||
|
list(REMOVE_ITEM WEBP_DSP_ENC_SRCS ${FILE})
|
||||||
|
list(REMOVE_ITEM WEBP_DSP_DEC_SRCS ${FILE})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Generate the config.h file.
|
||||||
|
configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/config.h.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/src/webp/config.h)
|
||||||
|
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)
|
||||||
|
string(REGEX MATCH
|
||||||
|
"${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})
|
||||||
|
|
||||||
|
# See the libtool docs for more information:
|
||||||
|
# https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
|
||||||
|
#
|
||||||
|
# c=<current>, a=<age>, r=<revision>
|
||||||
|
#
|
||||||
|
# libtool generates a .so file as .so.[c-a].a.r, while -version-info c:r:a is
|
||||||
|
# passed to libtool.
|
||||||
|
#
|
||||||
|
# We set FULL = [c-a].a.r and MAJOR = [c-a].
|
||||||
|
separate_arguments(LT_VERSION)
|
||||||
|
list(GET LT_VERSION 0 LT_CURRENT)
|
||||||
|
list(GET LT_VERSION 1 LT_REVISION)
|
||||||
|
list(GET LT_VERSION 2 LT_AGE)
|
||||||
|
math(EXPR LT_CURRENT_MINUS_AGE "${LT_CURRENT} - ${LT_AGE}")
|
||||||
|
|
||||||
|
set_target_properties(
|
||||||
|
${TARGET_NAME}
|
||||||
|
PROPERTIES VERSION
|
||||||
|
${LT_CURRENT_MINUS_AGE}.${LT_AGE}.${LT_REVISION}
|
||||||
|
SOVERSION
|
||||||
|
${LT_CURRENT_MINUS_AGE})
|
||||||
|
endmacro()
|
||||||
|
set_version(Makefile.am webp webp)
|
||||||
|
set_version(Makefile.am webpdecoder webpdecoder)
|
||||||
|
set_version(demux/Makefile.am webpdemux webpdemux)
|
||||||
|
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})
|
||||||
|
|
||||||
|
# Define the libraries to install.
|
||||||
|
list(APPEND INSTALLED_LIBRARIES webpdecoder webp webpdemux)
|
||||||
|
|
||||||
|
# Deal with SIMD. Change the compile flags for SIMD files we use.
|
||||||
|
list(LENGTH WEBP_SIMD_FILES_TO_INCLUDE WEBP_SIMD_FILES_TO_INCLUDE_LENGTH)
|
||||||
|
math(EXPR WEBP_SIMD_FILES_TO_INCLUDE_RANGE
|
||||||
|
"${WEBP_SIMD_FILES_TO_INCLUDE_LENGTH}-1")
|
||||||
|
|
||||||
|
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})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(NOT WEBP_BUILD_LIBWEBPMUX)
|
||||||
|
set(WEBP_BUILD_GIF2WEBP OFF)
|
||||||
|
set(WEBP_BUILD_IMG2WEBP OFF)
|
||||||
|
set(WEBP_BUILD_WEBPMUX OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_GIF2WEBP AND NOT GIF_FOUND)
|
||||||
|
set(WEBP_BUILD_GIF2WEBP OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_ANIM_UTILS AND NOT GIF_FOUND)
|
||||||
|
set(WEBP_BUILD_ANIM_UTILS OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Build the executables if asked for.
|
||||||
|
if(WEBP_BUILD_ANIM_UTILS
|
||||||
|
OR WEBP_BUILD_CWEBP
|
||||||
|
OR WEBP_BUILD_DWEBP
|
||||||
|
OR WEBP_BUILD_GIF2WEBP
|
||||||
|
OR WEBP_BUILD_IMG2WEBP
|
||||||
|
OR WEBP_BUILD_VWEBP)
|
||||||
|
# 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>)
|
||||||
|
|
||||||
|
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEIOUTILS_SRCS"
|
||||||
|
"imageio_util_[^ ]*")
|
||||||
|
add_library(imageioutil STATIC ${IMAGEIOUTILS_SRCS})
|
||||||
|
target_link_libraries(imageioutil webp)
|
||||||
|
|
||||||
|
# Image-decoding utility library.
|
||||||
|
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEDEC_SRCS"
|
||||||
|
"imagedec_[^ ]*")
|
||||||
|
add_library(imagedec STATIC ${IMAGEDEC_SRCS})
|
||||||
|
target_link_libraries(imagedec
|
||||||
|
imageioutil
|
||||||
|
webpdemux
|
||||||
|
webp
|
||||||
|
${WEBP_DEP_IMG_LIBRARIES})
|
||||||
|
|
||||||
|
# Image-encoding utility library.
|
||||||
|
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/imageio "IMAGEENC_SRCS"
|
||||||
|
"imageenc_[^ ]*")
|
||||||
|
add_library(imageenc STATIC ${IMAGEENC_SRCS})
|
||||||
|
target_link_libraries(imageenc imageioutil webp)
|
||||||
|
|
||||||
|
set_property(TARGET exampleutil
|
||||||
|
imageioutil
|
||||||
|
imagedec
|
||||||
|
imageenc
|
||||||
|
PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_DWEBP)
|
||||||
|
# dwebp
|
||||||
|
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "DWEBP_SRCS" "dwebp")
|
||||||
|
add_executable(dwebp ${DWEBP_SRCS})
|
||||||
|
target_link_libraries(dwebp exampleutil imagedec imageenc)
|
||||||
|
target_include_directories(dwebp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
install(TARGETS dwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_CWEBP)
|
||||||
|
# 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)
|
||||||
|
install(TARGETS cwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
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;\
|
||||||
|
${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)
|
||||||
|
list(APPEND INSTALLED_LIBRARIES libwebpmux)
|
||||||
|
configure_pkg_config("src/mux/libwebpmux.pc")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_GIF2WEBP)
|
||||||
|
# gif2webp
|
||||||
|
include_directories(${WEBP_DEP_GIF_INCLUDE_DIRS})
|
||||||
|
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "GIF2WEBP_SRCS"
|
||||||
|
"gif2webp")
|
||||||
|
add_executable(gif2webp ${GIF2WEBP_SRCS})
|
||||||
|
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})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_IMG2WEBP)
|
||||||
|
# img2webp
|
||||||
|
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
|
||||||
|
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "IMG2WEBP_SRCS"
|
||||||
|
"img2webp")
|
||||||
|
add_executable(img2webp ${IMG2WEBP_SRCS})
|
||||||
|
target_link_libraries(img2webp
|
||||||
|
exampleutil
|
||||||
|
imagedec
|
||||||
|
imageioutil
|
||||||
|
webp
|
||||||
|
libwebpmux)
|
||||||
|
target_include_directories(img2webp PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
install(TARGETS img2webp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_VWEBP)
|
||||||
|
# vwebp
|
||||||
|
find_package(GLUT)
|
||||||
|
if(GLUT_FOUND)
|
||||||
|
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})
|
||||||
|
install(TARGETS vwebp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||||
|
check_c_compiler_flag("-Wno-deprecated-declarations" HAS_NO_DEPRECATED)
|
||||||
|
if(HAS_NO_DEPRECATED)
|
||||||
|
target_compile_options(vwebp PRIVATE "-Wno-deprecated-declarations")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_WEBPINFO)
|
||||||
|
# webpinfo
|
||||||
|
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS})
|
||||||
|
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "WEBPINFO_SRCS"
|
||||||
|
"webpinfo")
|
||||||
|
add_executable(webpinfo ${WEBPINFO_SRCS})
|
||||||
|
target_link_libraries(webpinfo exampleutil imageioutil)
|
||||||
|
target_include_directories(webpinfo PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
install(TARGETS webpinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_WEBPMUX)
|
||||||
|
# webpmux
|
||||||
|
parse_makefile_am(${CMAKE_CURRENT_SOURCE_DIR}/examples "WEBPMUX_SRCS"
|
||||||
|
"webpmux")
|
||||||
|
add_executable(webpmux ${WEBPMUX_SRCS})
|
||||||
|
target_link_libraries(webpmux exampleutil imageioutil libwebpmux webp)
|
||||||
|
target_include_directories(webpmux PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
install(TARGETS webpmux RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_EXTRAS)
|
||||||
|
set(EXTRAS_MAKEFILE "${CMAKE_CURRENT_SOURCE_DIR}/extras")
|
||||||
|
parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_EXTRAS_SRCS" "libwebpextras_la")
|
||||||
|
parse_makefile_am(${EXTRAS_MAKEFILE} "GET_DISTO_SRCS" "get_disto")
|
||||||
|
parse_makefile_am(${EXTRAS_MAKEFILE} "WEBP_QUALITY_SRCS" "webp_quality")
|
||||||
|
parse_makefile_am(${EXTRAS_MAKEFILE} "VWEBP_SDL_SRCS" "vwebp_sdl")
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# 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})
|
||||||
|
|
||||||
|
# vwebp_sdl
|
||||||
|
find_package(SDL)
|
||||||
|
if(SDL_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})
|
||||||
|
set(WEBP_HAVE_SDL 1)
|
||||||
|
target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_WEBP_JS)
|
||||||
|
# wasm2js does not support SIMD.
|
||||||
|
if(NOT WEBP_ENABLE_SIMD)
|
||||||
|
# JavaScript version
|
||||||
|
add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
|
||||||
|
target_link_libraries(webp_js webpdecoder SDL)
|
||||||
|
target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
set(WEBP_HAVE_SDL 1)
|
||||||
|
set_target_properties(
|
||||||
|
webp_js
|
||||||
|
PROPERTIES LINK_FLAGS "-s WASM=0 \
|
||||||
|
-s EXPORTED_FUNCTIONS='[\"_WebpToSDL\"]' -s INVOKE_RUN=0 \
|
||||||
|
-s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'")
|
||||||
|
set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp)
|
||||||
|
target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# WASM version
|
||||||
|
add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c)
|
||||||
|
target_link_libraries(webp_wasm webpdecoder SDL)
|
||||||
|
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\"]'")
|
||||||
|
target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL)
|
||||||
|
|
||||||
|
target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WEBP_BUILD_ANIM_UTILS)
|
||||||
|
# anim_diff
|
||||||
|
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS} ${WEBP_DEP_GIF_INCLUDE_DIRS})
|
||||||
|
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_include_directories(anim_diff PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
|
||||||
|
# anim_dump
|
||||||
|
include_directories(${WEBP_DEP_IMG_INCLUDE_DIRS} ${WEBP_DEP_GIF_INCLUDE_DIRS})
|
||||||
|
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_include_directories(anim_dump PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
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})
|
||||||
|
set(ConfigPackageLocation ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake/)
|
||||||
|
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)
|
||||||
|
|
||||||
|
# Create the Config file.
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
configure_package_config_file(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/cmake/WebPConfig.cmake.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake
|
||||||
|
INSTALL_DESTINATION
|
||||||
|
${ConfigPackageLocation})
|
||||||
|
|
||||||
|
# Install the generated CMake files.
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/WebPConfigVersion.cmake"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/WebPConfig.cmake"
|
||||||
|
DESTINATION ${ConfigPackageLocation})
|
||||||
|
|
||||||
|
# Install the man pages.
|
||||||
|
set(MAN_PAGES
|
||||||
|
cwebp.1
|
||||||
|
dwebp.1
|
||||||
|
gif2webp.1
|
||||||
|
img2webp.1
|
||||||
|
vwebp.1
|
||||||
|
webpmux.1
|
||||||
|
webpinfo.1)
|
||||||
|
set(EXEC_BUILDS
|
||||||
|
"CWEBP"
|
||||||
|
"DWEBP"
|
||||||
|
"GIF2WEBP"
|
||||||
|
"IMG2WEBP"
|
||||||
|
"VWEBP"
|
||||||
|
"WEBPMUX"
|
||||||
|
"WEBPINFO")
|
||||||
|
list(LENGTH MAN_PAGES MAN_PAGES_LENGTH)
|
||||||
|
math(EXPR MAN_PAGES_RANGE "${MAN_PAGES_LENGTH} - 1")
|
||||||
|
|
||||||
|
foreach(I_MAN RANGE ${MAN_PAGES_RANGE})
|
||||||
|
list(GET EXEC_BUILDS ${I_MAN} EXEC_BUILD)
|
||||||
|
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)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
29
CONTRIBUTING.md
Normal file
29
CONTRIBUTING.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# How to Contribute
|
||||||
|
|
||||||
|
We'd love to accept your patches and contributions to this project. There are
|
||||||
|
just a few small guidelines you need to follow.
|
||||||
|
|
||||||
|
## Contributor License Agreement
|
||||||
|
|
||||||
|
Contributions to this project must be accompanied by a Contributor License
|
||||||
|
Agreement. You (or your employer) retain the copyright to your contribution;
|
||||||
|
this simply gives us permission to use and redistribute your contributions as
|
||||||
|
part of the project. Head over to <https://cla.developers.google.com/> to see
|
||||||
|
your current agreements on file or to sign a new one.
|
||||||
|
|
||||||
|
You generally only need to submit a CLA once, so if you've already submitted one
|
||||||
|
(even if it was for a different project), you probably don't need to do it
|
||||||
|
again.
|
||||||
|
|
||||||
|
## Code reviews
|
||||||
|
|
||||||
|
All submissions, including submissions by project members, require review. We
|
||||||
|
use a [Gerrit](https://www.gerritcodereview.com) instance hosted at
|
||||||
|
https://chromium-review.googlesource.com for this purpose. See the
|
||||||
|
[WebM Project page](https://www.webmproject.org/code/contribute/submitting-patches/)
|
||||||
|
for additional details.
|
||||||
|
|
||||||
|
## Community Guidelines
|
||||||
|
|
||||||
|
This project follows
|
||||||
|
[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
SUBDIRS = src examples man
|
SUBDIRS = src imageio man
|
||||||
EXTRA_DIST = COPYING autogen.sh
|
EXTRA_DIST = COPYING autogen.sh
|
||||||
|
|
||||||
|
if BUILD_EXTRAS
|
||||||
|
SUBDIRS += extras
|
||||||
|
endif
|
||||||
|
|
||||||
|
SUBDIRS += examples
|
||||||
|
|||||||
257
Makefile.vc
257
Makefile.vc
@@ -28,8 +28,8 @@ PLATFORM_LDFLAGS = /SAFESEH
|
|||||||
|
|
||||||
NOLOGO = /nologo
|
NOLOGO = /nologo
|
||||||
CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
|
CCNODBG = cl.exe $(NOLOGO) /O2 /DNDEBUG
|
||||||
CCDEBUG = cl.exe $(NOLOGO) /Od /Gm /Zi /D_DEBUG /RTC1
|
CCDEBUG = cl.exe $(NOLOGO) /Od /Zi /D_DEBUG /RTC1
|
||||||
CFLAGS = /Isrc $(NOLOGO) /W3 /EHsc /c
|
CFLAGS = /I. /Isrc $(NOLOGO) /W3 /EHsc /c
|
||||||
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
|
CFLAGS = $(CFLAGS) /DWIN32 /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN
|
||||||
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
|
LDFLAGS = /LARGEADDRESSAWARE /MANIFEST /NXCOMPAT /DYNAMICBASE
|
||||||
LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS)
|
LDFLAGS = $(LDFLAGS) $(PLATFORM_LDFLAGS)
|
||||||
@@ -37,6 +37,8 @@ LNKDLL = link.exe /DLL $(NOLOGO)
|
|||||||
LNKEXE = link.exe $(NOLOGO)
|
LNKEXE = link.exe $(NOLOGO)
|
||||||
LNKLIB = lib.exe $(NOLOGO)
|
LNKLIB = lib.exe $(NOLOGO)
|
||||||
MT = mt.exe $(NOLOGO)
|
MT = mt.exe $(NOLOGO)
|
||||||
|
RCNODBG = rc.exe $(NOLOGO) /l"0x0409" # 0x409 = U.S. English
|
||||||
|
RCDEBUG = $(RCNODBG) /D_DEBUG
|
||||||
|
|
||||||
!IF "$(ARCH)" == "ARM"
|
!IF "$(ARCH)" == "ARM"
|
||||||
CFLAGS = $(CFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP /DWEBP_USE_THREAD
|
CFLAGS = $(CFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP /DWEBP_USE_THREAD
|
||||||
@@ -51,11 +53,6 @@ OUTDIR = ..\obj\
|
|||||||
OUTDIR = $(OBJDIR)
|
OUTDIR = $(OBJDIR)
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
!IF "$(HAVE_AVX2)" == "1"
|
|
||||||
CFLAGS = $(CFLAGS) /DWEBP_HAVE_AVX2
|
|
||||||
AVX2_FLAGS = /arch:AVX2
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
# Runtime library configuration
|
# Runtime library configuration
|
||||||
!IF "$(RTLIBCFG)" == "static"
|
!IF "$(RTLIBCFG)" == "static"
|
||||||
@@ -82,6 +79,8 @@ OUTPUT_DIRS = $(DIRBIN) $(DIRINC) $(DIRLIB) \
|
|||||||
$(DIROBJ)\dsp \
|
$(DIROBJ)\dsp \
|
||||||
$(DIROBJ)\enc \
|
$(DIROBJ)\enc \
|
||||||
$(DIROBJ)\examples \
|
$(DIROBJ)\examples \
|
||||||
|
$(DIROBJ)\extras \
|
||||||
|
$(DIROBJ)\imageio \
|
||||||
$(DIROBJ)\mux \
|
$(DIROBJ)\mux \
|
||||||
$(DIROBJ)\utils \
|
$(DIROBJ)\utils \
|
||||||
|
|
||||||
@@ -99,9 +98,11 @@ LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug
|
|||||||
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug
|
||||||
!ELSE IF "$(CFG)" == "release-dynamic"
|
!ELSE IF "$(CFG)" == "release-dynamic"
|
||||||
CC = $(CCNODBG)
|
CC = $(CCNODBG)
|
||||||
|
RC = $(RCNODBG)
|
||||||
DLLBUILD = TRUE
|
DLLBUILD = TRUE
|
||||||
!ELSE IF "$(CFG)" == "debug-dynamic"
|
!ELSE IF "$(CFG)" == "debug-dynamic"
|
||||||
CC = $(CCDEBUG)
|
CC = $(CCDEBUG)
|
||||||
|
RC = $(RCDEBUG)
|
||||||
RTLIB = $(RTLIBD)
|
RTLIB = $(RTLIBD)
|
||||||
DLLBUILD = TRUE
|
DLLBUILD = TRUE
|
||||||
LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
|
LIBWEBPDECODER_BASENAME = $(LIBWEBPDECODER_BASENAME)_debug
|
||||||
@@ -128,12 +129,16 @@ LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb
|
|||||||
CFGSET = TRUE
|
CFGSET = TRUE
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
|
!IF "$(UNICODE)" == "1"
|
||||||
|
CFLAGS = $(CFLAGS) /D_UNICODE /DUNICODE
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# Usage
|
# Usage
|
||||||
#
|
#
|
||||||
!IF "$(CFGSET)" == "FALSE"
|
!IF "$(CFGSET)" == "FALSE"
|
||||||
!MESSAGE Usage: nmake /f Makefile.vc [CFG=<config>]
|
!MESSAGE Usage: nmake /f Makefile.vc [CFG=<config>]
|
||||||
!MESSAGE . [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [<target>]
|
!MESSAGE . [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [UNICODE=1] [<target>]
|
||||||
!MESSAGE
|
!MESSAGE
|
||||||
!MESSAGE where <config> is one of:
|
!MESSAGE where <config> is one of:
|
||||||
!MESSAGE - release-static - release static library
|
!MESSAGE - release-static - release static library
|
||||||
@@ -149,6 +154,7 @@ CFGSET = TRUE
|
|||||||
!MESSAGE - all - build (de)mux-based targets for CFG
|
!MESSAGE - all - build (de)mux-based targets for CFG
|
||||||
!MESSAGE - gif2webp - requires libgif & >= VS2013
|
!MESSAGE - gif2webp - requires libgif & >= VS2013
|
||||||
!MESSAGE - anim_diff - requires libgif & >= VS2013
|
!MESSAGE - anim_diff - requires libgif & >= VS2013
|
||||||
|
!MESSAGE - anim_dump
|
||||||
!MESSAGE
|
!MESSAGE
|
||||||
!MESSAGE RTLIBCFG controls the runtime library linkage - 'static' or 'dynamic'.
|
!MESSAGE RTLIBCFG controls the runtime library linkage - 'static' or 'dynamic'.
|
||||||
!MESSAGE 'legacy' will produce a Windows 2000 compatible library.
|
!MESSAGE 'legacy' will produce a Windows 2000 compatible library.
|
||||||
@@ -169,16 +175,16 @@ CFGSET = TRUE
|
|||||||
#
|
#
|
||||||
|
|
||||||
DEC_OBJS = \
|
DEC_OBJS = \
|
||||||
$(DIROBJ)\dec\alpha.obj \
|
$(DIROBJ)\dec\alpha_dec.obj \
|
||||||
$(DIROBJ)\dec\buffer.obj \
|
$(DIROBJ)\dec\buffer_dec.obj \
|
||||||
$(DIROBJ)\dec\frame.obj \
|
$(DIROBJ)\dec\frame_dec.obj \
|
||||||
$(DIROBJ)\dec\idec.obj \
|
$(DIROBJ)\dec\idec_dec.obj \
|
||||||
$(DIROBJ)\dec\io.obj \
|
$(DIROBJ)\dec\io_dec.obj \
|
||||||
$(DIROBJ)\dec\quant.obj \
|
$(DIROBJ)\dec\quant_dec.obj \
|
||||||
$(DIROBJ)\dec\tree.obj \
|
$(DIROBJ)\dec\tree_dec.obj \
|
||||||
$(DIROBJ)\dec\vp8.obj \
|
$(DIROBJ)\dec\vp8_dec.obj \
|
||||||
$(DIROBJ)\dec\vp8l.obj \
|
$(DIROBJ)\dec\vp8l_dec.obj \
|
||||||
$(DIROBJ)\dec\webp.obj \
|
$(DIROBJ)\dec\webp_dec.obj \
|
||||||
|
|
||||||
DEMUX_OBJS = \
|
DEMUX_OBJS = \
|
||||||
$(DIROBJ)\demux\anim_decode.obj \
|
$(DIROBJ)\demux\anim_decode.obj \
|
||||||
@@ -187,6 +193,7 @@ DEMUX_OBJS = \
|
|||||||
DSP_DEC_OBJS = \
|
DSP_DEC_OBJS = \
|
||||||
$(DIROBJ)\dsp\alpha_processing.obj \
|
$(DIROBJ)\dsp\alpha_processing.obj \
|
||||||
$(DIROBJ)\dsp\alpha_processing_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\alpha_processing_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\alpha_processing_neon.obj \
|
||||||
$(DIROBJ)\dsp\alpha_processing_sse2.obj \
|
$(DIROBJ)\dsp\alpha_processing_sse2.obj \
|
||||||
$(DIROBJ)\dsp\alpha_processing_sse41.obj \
|
$(DIROBJ)\dsp\alpha_processing_sse41.obj \
|
||||||
$(DIROBJ)\dsp\cpu.obj \
|
$(DIROBJ)\dsp\cpu.obj \
|
||||||
@@ -194,62 +201,78 @@ DSP_DEC_OBJS = \
|
|||||||
$(DIROBJ)\dsp\dec_clip_tables.obj \
|
$(DIROBJ)\dsp\dec_clip_tables.obj \
|
||||||
$(DIROBJ)\dsp\dec_mips32.obj \
|
$(DIROBJ)\dsp\dec_mips32.obj \
|
||||||
$(DIROBJ)\dsp\dec_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\dec_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\dec_msa.obj \
|
||||||
$(DIROBJ)\dsp\dec_neon.obj \
|
$(DIROBJ)\dsp\dec_neon.obj \
|
||||||
$(DIROBJ)\dsp\dec_sse2.obj \
|
$(DIROBJ)\dsp\dec_sse2.obj \
|
||||||
$(DIROBJ)\dsp\dec_sse41.obj \
|
$(DIROBJ)\dsp\dec_sse41.obj \
|
||||||
$(DIROBJ)\dsp\filters.obj \
|
$(DIROBJ)\dsp\filters.obj \
|
||||||
$(DIROBJ)\dsp\filters_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\filters_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\filters_msa.obj \
|
||||||
|
$(DIROBJ)\dsp\filters_neon.obj \
|
||||||
$(DIROBJ)\dsp\filters_sse2.obj \
|
$(DIROBJ)\dsp\filters_sse2.obj \
|
||||||
$(DIROBJ)\dsp\lossless.obj \
|
$(DIROBJ)\dsp\lossless.obj \
|
||||||
$(DIROBJ)\dsp\lossless_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\lossless_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\lossless_msa.obj \
|
||||||
$(DIROBJ)\dsp\lossless_neon.obj \
|
$(DIROBJ)\dsp\lossless_neon.obj \
|
||||||
$(DIROBJ)\dsp\lossless_sse2.obj \
|
$(DIROBJ)\dsp\lossless_sse2.obj \
|
||||||
|
$(DIROBJ)\dsp\lossless_sse41.obj \
|
||||||
$(DIROBJ)\dsp\rescaler.obj \
|
$(DIROBJ)\dsp\rescaler.obj \
|
||||||
$(DIROBJ)\dsp\rescaler_mips32.obj \
|
$(DIROBJ)\dsp\rescaler_mips32.obj \
|
||||||
$(DIROBJ)\dsp\rescaler_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\rescaler_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\rescaler_msa.obj \
|
||||||
$(DIROBJ)\dsp\rescaler_neon.obj \
|
$(DIROBJ)\dsp\rescaler_neon.obj \
|
||||||
$(DIROBJ)\dsp\rescaler_sse2.obj \
|
$(DIROBJ)\dsp\rescaler_sse2.obj \
|
||||||
$(DIROBJ)\dsp\upsampling.obj \
|
$(DIROBJ)\dsp\upsampling.obj \
|
||||||
$(DIROBJ)\dsp\upsampling_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\upsampling_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\upsampling_msa.obj \
|
||||||
$(DIROBJ)\dsp\upsampling_neon.obj \
|
$(DIROBJ)\dsp\upsampling_neon.obj \
|
||||||
$(DIROBJ)\dsp\upsampling_sse2.obj \
|
$(DIROBJ)\dsp\upsampling_sse2.obj \
|
||||||
|
$(DIROBJ)\dsp\upsampling_sse41.obj \
|
||||||
$(DIROBJ)\dsp\yuv.obj \
|
$(DIROBJ)\dsp\yuv.obj \
|
||||||
$(DIROBJ)\dsp\yuv_mips32.obj \
|
$(DIROBJ)\dsp\yuv_mips32.obj \
|
||||||
$(DIROBJ)\dsp\yuv_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\yuv_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\yuv_neon.obj \
|
||||||
$(DIROBJ)\dsp\yuv_sse2.obj \
|
$(DIROBJ)\dsp\yuv_sse2.obj \
|
||||||
|
$(DIROBJ)\dsp\yuv_sse41.obj \
|
||||||
|
|
||||||
DSP_ENC_OBJS = \
|
DSP_ENC_OBJS = \
|
||||||
$(DIROBJ)\dsp\argb.obj \
|
|
||||||
$(DIROBJ)\dsp\argb_mips_dsp_r2.obj \
|
|
||||||
$(DIROBJ)\dsp\argb_sse2.obj \
|
|
||||||
$(DIROBJ)\dsp\cost.obj \
|
$(DIROBJ)\dsp\cost.obj \
|
||||||
$(DIROBJ)\dsp\cost_mips32.obj \
|
$(DIROBJ)\dsp\cost_mips32.obj \
|
||||||
$(DIROBJ)\dsp\cost_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\cost_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\cost_neon.obj \
|
||||||
$(DIROBJ)\dsp\cost_sse2.obj \
|
$(DIROBJ)\dsp\cost_sse2.obj \
|
||||||
$(DIROBJ)\dsp\enc.obj \
|
$(DIROBJ)\dsp\enc.obj \
|
||||||
$(DIROBJ)\dsp\enc_avx2.obj \
|
|
||||||
$(DIROBJ)\dsp\enc_mips32.obj \
|
$(DIROBJ)\dsp\enc_mips32.obj \
|
||||||
$(DIROBJ)\dsp\enc_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\enc_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\enc_msa.obj \
|
||||||
$(DIROBJ)\dsp\enc_neon.obj \
|
$(DIROBJ)\dsp\enc_neon.obj \
|
||||||
$(DIROBJ)\dsp\enc_sse2.obj \
|
$(DIROBJ)\dsp\enc_sse2.obj \
|
||||||
$(DIROBJ)\dsp\enc_sse41.obj \
|
$(DIROBJ)\dsp\enc_sse41.obj \
|
||||||
$(DIROBJ)\dsp\lossless_enc.obj \
|
$(DIROBJ)\dsp\lossless_enc.obj \
|
||||||
$(DIROBJ)\dsp\lossless_enc_mips32.obj \
|
$(DIROBJ)\dsp\lossless_enc_mips32.obj \
|
||||||
$(DIROBJ)\dsp\lossless_enc_mips_dsp_r2.obj \
|
$(DIROBJ)\dsp\lossless_enc_mips_dsp_r2.obj \
|
||||||
|
$(DIROBJ)\dsp\lossless_enc_msa.obj \
|
||||||
$(DIROBJ)\dsp\lossless_enc_neon.obj \
|
$(DIROBJ)\dsp\lossless_enc_neon.obj \
|
||||||
$(DIROBJ)\dsp\lossless_enc_sse2.obj \
|
$(DIROBJ)\dsp\lossless_enc_sse2.obj \
|
||||||
$(DIROBJ)\dsp\lossless_enc_sse41.obj \
|
$(DIROBJ)\dsp\lossless_enc_sse41.obj \
|
||||||
|
$(DIROBJ)\dsp\ssim.obj \
|
||||||
|
$(DIROBJ)\dsp\ssim_sse2.obj \
|
||||||
|
|
||||||
EX_ANIM_UTIL_OBJS = \
|
EX_ANIM_UTIL_OBJS = \
|
||||||
$(DIROBJ)\examples\anim_util.obj \
|
$(DIROBJ)\examples\anim_util.obj \
|
||||||
|
|
||||||
EX_FORMAT_DEC_OBJS = \
|
IMAGEIO_DEC_OBJS = \
|
||||||
$(DIROBJ)\examples\jpegdec.obj \
|
$(DIROBJ)\imageio\image_dec.obj \
|
||||||
$(DIROBJ)\examples\metadata.obj \
|
$(DIROBJ)\imageio\jpegdec.obj \
|
||||||
$(DIROBJ)\examples\pngdec.obj \
|
$(DIROBJ)\imageio\metadata.obj \
|
||||||
$(DIROBJ)\examples\tiffdec.obj \
|
$(DIROBJ)\imageio\pngdec.obj \
|
||||||
$(DIROBJ)\examples\webpdec.obj \
|
$(DIROBJ)\imageio\pnmdec.obj \
|
||||||
$(DIROBJ)\examples\wicdec.obj \
|
$(DIROBJ)\imageio\tiffdec.obj \
|
||||||
|
$(DIROBJ)\imageio\webpdec.obj \
|
||||||
|
$(DIROBJ)\imageio\wicdec.obj \
|
||||||
|
|
||||||
|
IMAGEIO_ENC_OBJS = \
|
||||||
|
$(DIROBJ)\imageio\image_enc.obj \
|
||||||
|
|
||||||
EX_GIF_DEC_OBJS = \
|
EX_GIF_DEC_OBJS = \
|
||||||
$(DIROBJ)\examples\gifdec.obj \
|
$(DIROBJ)\examples\gifdec.obj \
|
||||||
@@ -258,28 +281,36 @@ EX_UTIL_OBJS = \
|
|||||||
$(DIROBJ)\examples\example_util.obj \
|
$(DIROBJ)\examples\example_util.obj \
|
||||||
|
|
||||||
ENC_OBJS = \
|
ENC_OBJS = \
|
||||||
$(DIROBJ)\enc\alpha.obj \
|
$(DIROBJ)\enc\alpha_enc.obj \
|
||||||
$(DIROBJ)\enc\analysis.obj \
|
$(DIROBJ)\enc\analysis_enc.obj \
|
||||||
$(DIROBJ)\enc\backward_references.obj \
|
$(DIROBJ)\enc\backward_references_cost_enc.obj \
|
||||||
$(DIROBJ)\enc\config.obj \
|
$(DIROBJ)\enc\backward_references_enc.obj \
|
||||||
$(DIROBJ)\enc\cost.obj \
|
$(DIROBJ)\enc\config_enc.obj \
|
||||||
$(DIROBJ)\enc\delta_palettization.obj \
|
$(DIROBJ)\enc\cost_enc.obj \
|
||||||
$(DIROBJ)\enc\filter.obj \
|
$(DIROBJ)\enc\filter_enc.obj \
|
||||||
$(DIROBJ)\enc\frame.obj \
|
$(DIROBJ)\enc\frame_enc.obj \
|
||||||
$(DIROBJ)\enc\histogram.obj \
|
$(DIROBJ)\enc\histogram_enc.obj \
|
||||||
$(DIROBJ)\enc\iterator.obj \
|
$(DIROBJ)\enc\iterator_enc.obj \
|
||||||
$(DIROBJ)\enc\near_lossless.obj \
|
$(DIROBJ)\enc\near_lossless_enc.obj \
|
||||||
$(DIROBJ)\enc\picture.obj \
|
$(DIROBJ)\enc\picture_enc.obj \
|
||||||
$(DIROBJ)\enc\picture_csp.obj \
|
$(DIROBJ)\enc\picture_csp_enc.obj \
|
||||||
$(DIROBJ)\enc\picture_psnr.obj \
|
$(DIROBJ)\enc\picture_psnr_enc.obj \
|
||||||
$(DIROBJ)\enc\picture_rescale.obj \
|
$(DIROBJ)\enc\picture_rescale_enc.obj \
|
||||||
$(DIROBJ)\enc\picture_tools.obj \
|
$(DIROBJ)\enc\picture_tools_enc.obj \
|
||||||
$(DIROBJ)\enc\quant.obj \
|
$(DIROBJ)\enc\predictor_enc.obj \
|
||||||
$(DIROBJ)\enc\syntax.obj \
|
$(DIROBJ)\enc\quant_enc.obj \
|
||||||
$(DIROBJ)\enc\token.obj \
|
$(DIROBJ)\enc\syntax_enc.obj \
|
||||||
$(DIROBJ)\enc\tree.obj \
|
$(DIROBJ)\enc\token_enc.obj \
|
||||||
$(DIROBJ)\enc\vp8l.obj \
|
$(DIROBJ)\enc\tree_enc.obj \
|
||||||
$(DIROBJ)\enc\webpenc.obj \
|
$(DIROBJ)\enc\vp8l_enc.obj \
|
||||||
|
$(DIROBJ)\enc\webp_enc.obj \
|
||||||
|
|
||||||
|
EXTRAS_OBJS = \
|
||||||
|
$(DIROBJ)\extras\extras.obj \
|
||||||
|
$(DIROBJ)\extras\quality_estimate.obj \
|
||||||
|
|
||||||
|
IMAGEIO_UTIL_OBJS = \
|
||||||
|
$(DIROBJ)\imageio\imageio_util.obj \
|
||||||
|
|
||||||
MUX_OBJS = \
|
MUX_OBJS = \
|
||||||
$(DIROBJ)\mux\anim_encode.obj \
|
$(DIROBJ)\mux\anim_encode.obj \
|
||||||
@@ -288,20 +319,20 @@ MUX_OBJS = \
|
|||||||
$(DIROBJ)\mux\muxread.obj \
|
$(DIROBJ)\mux\muxread.obj \
|
||||||
|
|
||||||
UTILS_DEC_OBJS = \
|
UTILS_DEC_OBJS = \
|
||||||
$(DIROBJ)\utils\bit_reader.obj \
|
$(DIROBJ)\utils\bit_reader_utils.obj \
|
||||||
$(DIROBJ)\utils\color_cache.obj \
|
$(DIROBJ)\utils\color_cache_utils.obj \
|
||||||
$(DIROBJ)\utils\filters.obj \
|
$(DIROBJ)\utils\filters_utils.obj \
|
||||||
$(DIROBJ)\utils\huffman.obj \
|
$(DIROBJ)\utils\huffman_utils.obj \
|
||||||
$(DIROBJ)\utils\quant_levels_dec.obj \
|
$(DIROBJ)\utils\quant_levels_dec_utils.obj \
|
||||||
$(DIROBJ)\utils\rescaler.obj \
|
$(DIROBJ)\utils\rescaler_utils.obj \
|
||||||
$(DIROBJ)\utils\random.obj \
|
$(DIROBJ)\utils\random_utils.obj \
|
||||||
$(DIROBJ)\utils\thread.obj \
|
$(DIROBJ)\utils\thread_utils.obj \
|
||||||
$(DIROBJ)\utils\utils.obj \
|
$(DIROBJ)\utils\utils.obj \
|
||||||
|
|
||||||
UTILS_ENC_OBJS = \
|
UTILS_ENC_OBJS = \
|
||||||
$(DIROBJ)\utils\bit_writer.obj \
|
$(DIROBJ)\utils\bit_writer_utils.obj \
|
||||||
$(DIROBJ)\utils\huffman_encode.obj \
|
$(DIROBJ)\utils\huffman_encode_utils.obj \
|
||||||
$(DIROBJ)\utils\quant_levels.obj \
|
$(DIROBJ)\utils\quant_levels_utils.obj \
|
||||||
|
|
||||||
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
|
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
|
||||||
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
|
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
|
||||||
@@ -315,7 +346,10 @@ ex: $(OUT_LIBS)
|
|||||||
all: ex
|
all: ex
|
||||||
!ELSE
|
!ELSE
|
||||||
OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe
|
OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe
|
||||||
EXTRA_EXAMPLES = $(DIRBIN)\vwebp.exe $(DIRBIN)\webpmux.exe
|
EXTRA_EXAMPLES = $(DIRBIN)\vwebp.exe $(DIRBIN)\webpmux.exe \
|
||||||
|
$(DIRBIN)\img2webp.exe $(DIRBIN)\get_disto.exe \
|
||||||
|
$(DIRBIN)\webp_quality.exe $(DIRBIN)\vwebp_sdl.exe \
|
||||||
|
$(DIRBIN)\webpinfo.exe
|
||||||
|
|
||||||
ex: $(OUT_LIBS) $(OUT_EXAMPLES)
|
ex: $(OUT_LIBS) $(OUT_EXAMPLES)
|
||||||
all: ex $(EXTRA_EXAMPLES)
|
all: ex $(EXTRA_EXAMPLES)
|
||||||
@@ -323,26 +357,57 @@ all: ex $(EXTRA_EXAMPLES)
|
|||||||
# C99 support which is only available from VS2013 onward.
|
# C99 support which is only available from VS2013 onward.
|
||||||
gif2webp: $(DIRBIN)\gif2webp.exe
|
gif2webp: $(DIRBIN)\gif2webp.exe
|
||||||
anim_diff: $(DIRBIN)\anim_diff.exe
|
anim_diff: $(DIRBIN)\anim_diff.exe
|
||||||
|
anim_dump: $(DIRBIN)\anim_dump.exe
|
||||||
|
|
||||||
$(DIRBIN)\anim_diff.exe: $(DIROBJ)\examples\anim_diff.obj $(EX_ANIM_UTIL_OBJS)
|
$(DIRBIN)\anim_diff.exe: $(DIROBJ)\examples\anim_diff.obj $(EX_ANIM_UTIL_OBJS)
|
||||||
$(DIRBIN)\anim_diff.exe: $(EX_UTIL_OBJS)
|
$(DIRBIN)\anim_diff.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
|
||||||
$(DIRBIN)\anim_diff.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
|
$(DIRBIN)\anim_diff.exe: $(EX_GIF_DEC_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
|
||||||
$(DIRBIN)\cwebp.exe: $(DIROBJ)\examples\cwebp.obj $(EX_FORMAT_DEC_OBJS)
|
$(DIRBIN)\anim_dump.exe: $(DIROBJ)\examples\anim_dump.obj $(EX_ANIM_UTIL_OBJS)
|
||||||
$(DIRBIN)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj
|
$(DIRBIN)\anim_dump.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
|
||||||
|
$(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)\dwebp.exe: $(DIROBJ)\examples\dwebp.obj $(IMAGEIO_DEC_OBJS)
|
||||||
|
$(DIRBIN)\dwebp.exe: $(IMAGEIO_ENC_OBJS)
|
||||||
|
$(DIRBIN)\dwebp.exe: $(IMAGEIO_UTIL_OBJS)
|
||||||
|
$(DIRBIN)\dwebp.exe: $(LIBWEBPDEMUX)
|
||||||
$(DIRBIN)\gif2webp.exe: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS)
|
$(DIRBIN)\gif2webp.exe: $(DIROBJ)\examples\gif2webp.obj $(EX_GIF_DEC_OBJS)
|
||||||
$(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(LIBWEBPMUX) $(LIBWEBP)
|
$(DIRBIN)\gif2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBPMUX)
|
||||||
$(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj
|
$(DIRBIN)\gif2webp.exe: $(LIBWEBP)
|
||||||
$(DIRBIN)\vwebp.exe: $(EX_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
|
$(DIRBIN)\vwebp.exe: $(DIROBJ)\examples\vwebp.obj $(EX_UTIL_OBJS)
|
||||||
|
$(DIRBIN)\vwebp.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBPDEMUX) $(LIBWEBP)
|
||||||
|
$(DIRBIN)\vwebp_sdl.exe: $(DIROBJ)\extras\vwebp_sdl.obj
|
||||||
|
$(DIRBIN)\vwebp_sdl.exe: $(DIROBJ)\extras\webp_to_sdl.obj
|
||||||
|
$(DIRBIN)\vwebp_sdl.exe: $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
|
||||||
$(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX)
|
$(DIRBIN)\webpmux.exe: $(DIROBJ)\examples\webpmux.obj $(LIBWEBPMUX)
|
||||||
$(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(LIBWEBP)
|
$(DIRBIN)\webpmux.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS) $(LIBWEBP)
|
||||||
$(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP)
|
$(DIRBIN)\img2webp.exe: $(DIROBJ)\examples\img2webp.obj $(LIBWEBPMUX)
|
||||||
$(EX_UTIL_OBJS) $(EX_FORMAT_DEC_OBJS): $(OUTPUT_DIRS)
|
$(DIRBIN)\img2webp.exe: $(IMAGEIO_DEC_OBJS)
|
||||||
!ENDIF # ARCH == ARM
|
$(DIRBIN)\img2webp.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
|
||||||
|
$(DIRBIN)\img2webp.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
|
||||||
|
$(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)
|
||||||
|
$(DIRBIN)\webp_quality.exe: $(DIROBJ)\extras\webp_quality.obj
|
||||||
|
$(DIRBIN)\webp_quality.exe: $(IMAGEIO_UTIL_OBJS)
|
||||||
|
$(DIRBIN)\webp_quality.exe: $(EXTRAS_OBJS)
|
||||||
|
# EXTRA_OBJS requires private symbols from dsp. Explicitly add those when
|
||||||
|
# building libwebp as a dll.
|
||||||
|
!IF "$(DLLBUILD)" == "TRUE"
|
||||||
|
$(DIRBIN)\webp_quality.exe: $(DSP_DEC_OBJS)
|
||||||
|
!ENDIF
|
||||||
|
$(DIRBIN)\webp_quality.exe: $(LIBWEBP)
|
||||||
|
$(DIRBIN)\webpinfo.exe: $(DIROBJ)\examples\webpinfo.obj
|
||||||
|
$(DIRBIN)\webpinfo.exe: $(IMAGEIO_DEC_OBJS)
|
||||||
|
$(DIRBIN)\webpinfo.exe: $(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS)
|
||||||
|
$(DIRBIN)\webpinfo.exe: $(LIBWEBPDEMUX) $(LIBWEBP)
|
||||||
|
|
||||||
experimental:
|
$(OUT_EXAMPLES): $(EX_UTIL_OBJS) $(LIBWEBP)
|
||||||
$(MAKE) /f Makefile.vc \
|
$(EX_UTIL_OBJS) $(IMAGEIO_UTIL_OBJS): $(OUTPUT_DIRS)
|
||||||
CFG=$(CFG) \
|
$(IMAGEIO_DEC_OBJS) $(IMAGEIO_ENC_OBJS) $(EXTRAS_OBJS): $(OUTPUT_DIRS)
|
||||||
CFLAGS="$(CFLAGS) /DWEBP_EXPERIMENTAL_FEATURES" /$(MAKEFLAGS)
|
!ENDIF # ARCH == ARM
|
||||||
|
|
||||||
$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS)
|
$(LIBWEBPDECODER): $(LIBWEBPDECODER_OBJS)
|
||||||
$(LIBWEBP): $(LIBWEBP_OBJS)
|
$(LIBWEBP): $(LIBWEBP_OBJS)
|
||||||
@@ -358,8 +423,17 @@ $(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): \
|
|||||||
{$(DIROBJ)}.c{$(DIROBJ)}.obj:
|
{$(DIROBJ)}.c{$(DIROBJ)}.obj:
|
||||||
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
|
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $<
|
||||||
|
|
||||||
$(LIBWEBPMUX): $(LIBWEBP)
|
{src}.rc{$(DIROBJ)}.res:
|
||||||
$(LIBWEBPDEMUX): $(LIBWEBP)
|
$(RC) /fo$@ $<
|
||||||
|
{src\demux}.rc{$(DIROBJ)\demux}.res:
|
||||||
|
$(RC) /fo$@ $<
|
||||||
|
{src\mux}.rc{$(DIROBJ)\mux}.res:
|
||||||
|
$(RC) /fo$@ $<
|
||||||
|
|
||||||
|
$(LIBWEBP): $(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):
|
||||||
$(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $**
|
$(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $**
|
||||||
@@ -380,18 +454,18 @@ $(OUTPUT_DIRS):
|
|||||||
$(DIROBJ)\$(DLLINC):
|
$(DIROBJ)\$(DLLINC):
|
||||||
@echo #ifndef WEBP_DLL_H_ > $@
|
@echo #ifndef WEBP_DLL_H_ > $@
|
||||||
@echo #define WEBP_DLL_H_ >> $@
|
@echo #define WEBP_DLL_H_ >> $@
|
||||||
@echo #define WEBP_EXTERN(type) __declspec(dllexport) type >> $@
|
@echo #define WEBP_EXTERN __declspec(dllexport) >> $@
|
||||||
@echo #endif /* WEBP_DLL_H_ */ >> $@
|
@echo #endif /* WEBP_DLL_H_ */ >> $@
|
||||||
|
|
||||||
.SUFFIXES: .c .obj .res .exe
|
.SUFFIXES: .c .obj .res .exe
|
||||||
# File-specific flag builds. Note batch rules take precedence over wildcards,
|
# File-specific flag builds. Note batch rules take precedence over wildcards,
|
||||||
# so for now name each file individually.
|
# so for now name each file individually.
|
||||||
$(DIROBJ)\dsp\enc_avx2.obj: src\dsp\enc_avx2.c
|
|
||||||
$(CC) $(CFLAGS) $(AVX2_FLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dsp\ \
|
|
||||||
src\dsp\$(@B).c
|
|
||||||
$(DIROBJ)\examples\anim_diff.obj: examples\anim_diff.c
|
$(DIROBJ)\examples\anim_diff.obj: examples\anim_diff.c
|
||||||
$(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
|
$(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
|
||||||
/Fo$(DIROBJ)\examples\ examples\$(@B).c
|
/Fo$(DIROBJ)\examples\ examples\$(@B).c
|
||||||
|
$(DIROBJ)\examples\anim_dump.obj: examples\anim_dump.c
|
||||||
|
$(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
|
||||||
|
/Fo$(DIROBJ)\examples\ examples\$(@B).c
|
||||||
$(DIROBJ)\examples\anim_util.obj: examples\anim_util.c
|
$(DIROBJ)\examples\anim_util.obj: examples\anim_util.c
|
||||||
$(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
|
$(CC) $(CFLAGS) /DWEBP_HAVE_GIF /Fd$(LIBWEBP_PDBNAME) \
|
||||||
/Fo$(DIROBJ)\examples\ examples\$(@B).c
|
/Fo$(DIROBJ)\examples\ examples\$(@B).c
|
||||||
@@ -404,6 +478,10 @@ $(DIROBJ)\examples\gifdec.obj: examples\gifdec.c
|
|||||||
# Batch rules
|
# Batch rules
|
||||||
{examples}.c{$(DIROBJ)\examples}.obj::
|
{examples}.c{$(DIROBJ)\examples}.obj::
|
||||||
$(CC) $(CFLAGS) /Fd$(DIROBJ)\examples\ /Fo$(DIROBJ)\examples\ $<
|
$(CC) $(CFLAGS) /Fd$(DIROBJ)\examples\ /Fo$(DIROBJ)\examples\ $<
|
||||||
|
{extras}.c{$(DIROBJ)\extras}.obj::
|
||||||
|
$(CC) $(CFLAGS) /Fd$(DIROBJ)\extras\ /Fo$(DIROBJ)\extras\ $<
|
||||||
|
{imageio}.c{$(DIROBJ)\imageio}.obj::
|
||||||
|
$(CC) $(CFLAGS) /Fd$(DIROBJ)\imageio\ /Fo$(DIROBJ)\imageio\ $<
|
||||||
{src\dec}.c{$(DIROBJ)\dec}.obj::
|
{src\dec}.c{$(DIROBJ)\dec}.obj::
|
||||||
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $<
|
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $<
|
||||||
{src\demux}.c{$(DIROBJ)\demux}.obj::
|
{src\demux}.c{$(DIROBJ)\demux}.obj::
|
||||||
@@ -417,9 +495,18 @@ $(DIROBJ)\examples\gifdec.obj: examples\gifdec.c
|
|||||||
{src\utils}.c{$(DIROBJ)\utils}.obj::
|
{src\utils}.c{$(DIROBJ)\utils}.obj::
|
||||||
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\utils\ $<
|
$(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\utils\ $<
|
||||||
|
|
||||||
|
LNKLIBS = ole32.lib windowscodecs.lib shlwapi.lib
|
||||||
|
!IF "$(UNICODE)" == "1"
|
||||||
|
LNKLIBS = $(LNKLIBS) Shell32.lib
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
{$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe:
|
{$(DIROBJ)\examples}.obj{$(DIRBIN)}.exe:
|
||||||
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** \
|
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
|
||||||
ole32.lib windowscodecs.lib shlwapi.lib
|
$(MT) -manifest $@.manifest -outputresource:$@;1
|
||||||
|
del $@.manifest
|
||||||
|
|
||||||
|
{$(DIROBJ)\extras}.obj{$(DIRBIN)}.exe:
|
||||||
|
$(LNKEXE) $(LDFLAGS) /OUT:$@ $** $(LNKLIBS)
|
||||||
$(MT) -manifest $@.manifest -outputresource:$@;1
|
$(MT) -manifest $@.manifest -outputresource:$@;1
|
||||||
del $@.manifest
|
del $@.manifest
|
||||||
|
|
||||||
|
|||||||
132
NEWS
132
NEWS
@@ -1,3 +1,135 @@
|
|||||||
|
- 7/20/2021: version 1.2.1
|
||||||
|
This is a binary compatible release.
|
||||||
|
* minor lossless encoder improvements and x86 color conversion speed up
|
||||||
|
* add ARM64 simulator support to xcframeworkbuild.sh (#510)
|
||||||
|
* further security related hardening in libwebp & examples
|
||||||
|
(issues: #497, #508, #518)
|
||||||
|
(chromium: #1196480, #1196773, #1196775, #1196777, #1196778, #1196850)
|
||||||
|
(oss-fuzz: #28658, #28978)
|
||||||
|
* toolchain updates and bug fixes (#498, #501, #502, #504, #505, #506, #509,
|
||||||
|
#533)
|
||||||
|
* use more inclusive language within the source (#507)
|
||||||
|
|
||||||
|
- 12/23/2020: version 1.2.0
|
||||||
|
* API changes:
|
||||||
|
- libwebp:
|
||||||
|
encode.h: add a qmin / qmax range for quality factor (cwebp adds -qrange)
|
||||||
|
* lossless encoder improvements
|
||||||
|
* SIMD support for Wasm builds
|
||||||
|
* add xcframeworkbuild.sh, supports Mac Catalyst builds
|
||||||
|
* import fuzzers from oss-fuzz & chromium (#409)
|
||||||
|
* webpmux: add an '-set loop <value>' option (#494)
|
||||||
|
* toolchain updates and bug fixes (#449, #463, #470, #475, #477, #478, #479,
|
||||||
|
#488, #491)
|
||||||
|
|
||||||
|
- 12/18/2019: version 1.1.0
|
||||||
|
* API changes:
|
||||||
|
- libwebp:
|
||||||
|
WebPMalloc (issue #442)
|
||||||
|
- extras:
|
||||||
|
WebPUnmultiplyARGB
|
||||||
|
* alpha decode fix (issue #439)
|
||||||
|
* toolchain updates and bug fixes
|
||||||
|
(chromium: #1026858, #1027136, #1027409, #1028620, #1028716, #995200)
|
||||||
|
(oss-fuzz: #19430, #19447)
|
||||||
|
|
||||||
|
- 7/4/2019: version 1.0.3
|
||||||
|
This is a binary compatible release.
|
||||||
|
* resize fixes for Nx1 sizes and the addition of non-opaque alpha values for
|
||||||
|
odd sizes (issues #418, #434)
|
||||||
|
* lossless encode/decode performance improvements
|
||||||
|
* lossy compression performance improvement at low quality levels with flat
|
||||||
|
content (issue #432)
|
||||||
|
* python swig files updated to support python 3
|
||||||
|
Tool updates:
|
||||||
|
vwebp will now preserve the aspect ratio of images that exceed monitor
|
||||||
|
resolution by scaling the image to fit (issue #433)
|
||||||
|
|
||||||
|
- 1/14/2019: version 1.0.2
|
||||||
|
This is a binary compatible release.
|
||||||
|
* (Windows) unicode file support in the tools (linux and mac already had
|
||||||
|
support, issue #398)
|
||||||
|
* lossless encoder speedups
|
||||||
|
* lossy encoder speedup on ARM
|
||||||
|
* lossless multi-threaded security fix (chromium:917029)
|
||||||
|
|
||||||
|
- 11/2/2018: version 1.0.1
|
||||||
|
This is a binary compatible release.
|
||||||
|
* lossless encoder speedups
|
||||||
|
* big-endian fix for alpha decoding (issue #393)
|
||||||
|
* gif2webp fix for loop count=65535 transcode (issue #382)
|
||||||
|
* further security related hardening in libwebp & libwebpmux
|
||||||
|
(issues #383, #385, #386, #387, #388, #391)
|
||||||
|
(oss-fuzz #9099, #9100, #9105, #9106, #9111, #9112, #9119, #9123, #9170,
|
||||||
|
#9178, #9179, #9183, #9186, #9191, #9364, #9417, #9496, #10349,
|
||||||
|
#10423, #10634, #10700, #10838, #10922, #11021, #11088, #11152)
|
||||||
|
* miscellaneous bug & build fixes (issues #381, #394, #396, #397, #400)
|
||||||
|
|
||||||
|
- 4/2/2018: version 1.0.0
|
||||||
|
This is a binary compatible release.
|
||||||
|
* lossy encoder improvements to avoid chroma shifts in various circumstances
|
||||||
|
(issues #308, #340)
|
||||||
|
* big-endian fixes for decode, RGBA import and WebPPictureDistortion
|
||||||
|
Tool updates:
|
||||||
|
gifwebp, anim_diff - default duration behavior (<= 10ms) changed to match
|
||||||
|
web browsers, transcoding tools (issue #379)
|
||||||
|
img2webp, webpmux - allow options to be passed in via a file (issue #355)
|
||||||
|
|
||||||
|
- 11/24/2017: version 0.6.1
|
||||||
|
This is a binary compatible release.
|
||||||
|
* lossless performance and compression improvements + a new 'cruncher' mode
|
||||||
|
(-m 6 -q 100)
|
||||||
|
* ARM performance improvements with clang (15-20% w/ndk r15c, issue #339)
|
||||||
|
* webp-js: emscripten/webassembly based javascript decoder
|
||||||
|
* miscellaneous bug & build fixes (issue #329, #332, #343, #353, #360, #361,
|
||||||
|
#363)
|
||||||
|
Tool updates / additions:
|
||||||
|
added webpinfo - prints file format information (issue #330)
|
||||||
|
gif2webp - loop behavior modified to match Chrome M63+ (crbug.com/649264);
|
||||||
|
'-loop_compatibility' can be used for the old behavior
|
||||||
|
|
||||||
|
- 1/26/2017: version 0.6.0
|
||||||
|
* lossless performance and compression improvements
|
||||||
|
* miscellaneous performance improvements (SSE2, NEON, MSA)
|
||||||
|
* webpmux gained a -duration option allowing for frame timing modification
|
||||||
|
* new img2webp utility allowing a sequence of images to be converted to
|
||||||
|
animated webp
|
||||||
|
* API changes:
|
||||||
|
- libwebp:
|
||||||
|
WebPPictureSharpARGBToYUVA
|
||||||
|
WebPPlaneDistortion
|
||||||
|
- libwebpmux / gif2webp:
|
||||||
|
WebPAnimEncoderOptions: kmax <= 0 now disables keyframes, kmax == 1
|
||||||
|
forces all keyframes. See mux.h and the gif2webp
|
||||||
|
manpage for details.
|
||||||
|
|
||||||
|
- 12/13/2016: version 0.5.2
|
||||||
|
This is a binary compatible release.
|
||||||
|
This release covers CVE-2016-8888 and CVE-2016-9085.
|
||||||
|
* further security related hardening in the tools; fixes to
|
||||||
|
gif2webp/AnimEncoder (issues #310, #314, #316, #322), cwebp/libwebp (issue
|
||||||
|
#312)
|
||||||
|
* full libwebp (encoder & decoder) iOS framework; libwebpdecoder
|
||||||
|
WebP.framework renamed to WebPDecoder.framework (issue #307)
|
||||||
|
* CMake support for Android Studio (2.2)
|
||||||
|
* miscellaneous build related fixes (issue #306, #313)
|
||||||
|
* miscellaneous documentation improvements (issue #225)
|
||||||
|
* minor lossy encoder fixes and improvements
|
||||||
|
|
||||||
|
- 6/14/2016: version 0.5.1
|
||||||
|
This is a binary compatible release.
|
||||||
|
* miscellaneous bug fixes (issues #280, #289)
|
||||||
|
* reverted alpha plane encoding with color cache for compatibility with
|
||||||
|
libwebp 0.4.0->0.4.3 (issues #291, #298)
|
||||||
|
* lossless encoding performance improvements
|
||||||
|
* memory reduction in both lossless encoding and decoding
|
||||||
|
* force mux output to be in the extended format (VP8X) when undefined chunks
|
||||||
|
are present (issue #294)
|
||||||
|
* gradle, cmake build support
|
||||||
|
* workaround for compiler bug causing 64-bit decode failures on android
|
||||||
|
devices using clang-3.8 in the r11c NDK
|
||||||
|
* various WebPAnimEncoder improvements
|
||||||
|
|
||||||
- 12/17/2015: version 0.5.0
|
- 12/17/2015: version 0.5.0
|
||||||
* miscellaneous bug & build fixes (issues #234, #258, #274, #275, #278)
|
* miscellaneous bug & build fixes (issues #234, #258, #274, #275, #278)
|
||||||
* encoder & decoder speed-ups on x86/ARM/MIPS for lossy & lossless
|
* encoder & decoder speed-ups on x86/ARM/MIPS for lossy & lossless
|
||||||
|
|||||||
183
PRESUBMIT.py
Normal file
183
PRESUBMIT.py
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
# Copyright (c) 2021, Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of Google nor the names of its contributors may
|
||||||
|
# be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
"""Top-level presubmit script for libwebp.
|
||||||
|
|
||||||
|
See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
|
||||||
|
details on the presubmit API built into depot_tools.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import subprocess2
|
||||||
|
|
||||||
|
USE_PYTHON3 = True
|
||||||
|
_BASH_INDENTATION = "2"
|
||||||
|
_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"]
|
||||||
|
_INCLUDE_MAN_FILES_ONLY = [r"man/.+\.1$"]
|
||||||
|
_LIBWEBP_MAX_LINE_LENGTH = 80
|
||||||
|
|
||||||
|
|
||||||
|
def _GetFilesToSkip(input_api):
|
||||||
|
return list(input_api.DEFAULT_FILES_TO_SKIP) + [
|
||||||
|
r"swig/.*\.py$",
|
||||||
|
r"\.pylintrc$",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _RunManCmd(input_api, output_api, man_file):
|
||||||
|
"""man command wrapper."""
|
||||||
|
cmd = ["man", "--warnings", "-EUTF-8", "-l", "-Tutf8", "-Z", man_file]
|
||||||
|
name = "Check %s file." % man_file
|
||||||
|
start = input_api.time.time()
|
||||||
|
output, _ = subprocess2.communicate(
|
||||||
|
cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
|
||||||
|
duration = input_api.time.time() - start
|
||||||
|
if output[1]:
|
||||||
|
return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
|
||||||
|
(name, " ".join(cmd), duration, output[1]))
|
||||||
|
return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
|
||||||
|
(name, " ".join(cmd), duration))
|
||||||
|
|
||||||
|
|
||||||
|
def _RunShellCheckCmd(input_api, output_api, bash_file):
|
||||||
|
"""shellcheck command wrapper."""
|
||||||
|
cmd = ["shellcheck", "-x", "-oall", "-sbash", bash_file]
|
||||||
|
name = "Check %s file." % bash_file
|
||||||
|
start = input_api.time.time()
|
||||||
|
output, rc = subprocess2.communicate(
|
||||||
|
cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
|
||||||
|
duration = input_api.time.time() - start
|
||||||
|
if rc == 0:
|
||||||
|
return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
|
||||||
|
(name, " ".join(cmd), duration))
|
||||||
|
return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
|
||||||
|
(name, " ".join(cmd), duration, output[1]))
|
||||||
|
|
||||||
|
|
||||||
|
def _RunShfmtCheckCmd(input_api, output_api, bash_file):
|
||||||
|
"""shfmt command wrapper."""
|
||||||
|
cmd = [
|
||||||
|
"shfmt", "-i", _BASH_INDENTATION, "-bn", "-ci", "-sr", "-kp", "-d",
|
||||||
|
bash_file
|
||||||
|
]
|
||||||
|
name = "Check %s file." % bash_file
|
||||||
|
start = input_api.time.time()
|
||||||
|
output, rc = subprocess2.communicate(
|
||||||
|
cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
|
||||||
|
duration = input_api.time.time() - start
|
||||||
|
if rc == 0:
|
||||||
|
return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
|
||||||
|
(name, " ".join(cmd), duration))
|
||||||
|
return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
|
||||||
|
(name, " ".join(cmd), duration, output[1]))
|
||||||
|
|
||||||
|
|
||||||
|
def _RunCmdOnCheckedFiles(input_api, output_api, run_cmd, files_to_check):
|
||||||
|
"""Ensure that libwebp/ files are clean."""
|
||||||
|
file_filter = lambda x: input_api.FilterSourceFile(
|
||||||
|
x, files_to_check=files_to_check, files_to_skip=None)
|
||||||
|
|
||||||
|
affected_files = input_api.change.AffectedFiles(file_filter=file_filter)
|
||||||
|
results = [
|
||||||
|
run_cmd(input_api, output_api, f.AbsoluteLocalPath())
|
||||||
|
for f in affected_files
|
||||||
|
]
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def _CommonChecks(input_api, output_api):
|
||||||
|
"""Ensures this patch does not have trailing spaces, extra EOLs,
|
||||||
|
or long lines.
|
||||||
|
"""
|
||||||
|
results = []
|
||||||
|
results.extend(
|
||||||
|
input_api.canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol(
|
||||||
|
input_api, output_api))
|
||||||
|
results.extend(
|
||||||
|
input_api.canned_checks.CheckChangeHasNoTabs(input_api, output_api))
|
||||||
|
results.extend(
|
||||||
|
input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
|
||||||
|
input_api, output_api))
|
||||||
|
|
||||||
|
source_file_filter = lambda x: input_api.FilterSourceFile(
|
||||||
|
x, files_to_skip=_GetFilesToSkip(input_api))
|
||||||
|
results.extend(
|
||||||
|
input_api.canned_checks.CheckLongLines(
|
||||||
|
input_api,
|
||||||
|
output_api,
|
||||||
|
maxlen=_LIBWEBP_MAX_LINE_LENGTH,
|
||||||
|
source_file_filter=source_file_filter))
|
||||||
|
|
||||||
|
results.extend(
|
||||||
|
input_api.canned_checks.CheckPatchFormatted(
|
||||||
|
input_api,
|
||||||
|
output_api,
|
||||||
|
check_clang_format=False,
|
||||||
|
check_python=True,
|
||||||
|
result_factory=output_api.PresubmitError))
|
||||||
|
results.extend(
|
||||||
|
_RunCmdOnCheckedFiles(input_api, output_api, _RunManCmd,
|
||||||
|
_INCLUDE_MAN_FILES_ONLY))
|
||||||
|
# Run pylint.
|
||||||
|
results.extend(
|
||||||
|
input_api.canned_checks.RunPylint(
|
||||||
|
input_api,
|
||||||
|
output_api,
|
||||||
|
files_to_skip=_GetFilesToSkip(input_api),
|
||||||
|
pylintrc=".pylintrc",
|
||||||
|
version="2.7"))
|
||||||
|
|
||||||
|
# Binaries shellcheck and shfmt are not installed in depot_tools.
|
||||||
|
# Installation is needed
|
||||||
|
try:
|
||||||
|
subprocess2.communicate(["shellcheck", "--version"])
|
||||||
|
results.extend(
|
||||||
|
_RunCmdOnCheckedFiles(input_api, output_api, _RunShellCheckCmd,
|
||||||
|
_INCLUDE_BASH_FILES_ONLY))
|
||||||
|
print("shfmt")
|
||||||
|
subprocess2.communicate(["shfmt", "-version"])
|
||||||
|
results.extend(
|
||||||
|
_RunCmdOnCheckedFiles(input_api, output_api, _RunShfmtCheckCmd,
|
||||||
|
_INCLUDE_BASH_FILES_ONLY))
|
||||||
|
except OSError as os_error:
|
||||||
|
results.append(
|
||||||
|
output_api.PresubmitPromptWarning(
|
||||||
|
"%s\nPlease install missing binaries locally." % os_error.args[0]))
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def CheckChangeOnUpload(input_api, output_api):
|
||||||
|
results = []
|
||||||
|
results.extend(_CommonChecks(input_api, output_api))
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def CheckChangeOnCommit(input_api, output_api):
|
||||||
|
results = []
|
||||||
|
results.extend(_CommonChecks(input_api, output_api))
|
||||||
|
return results
|
||||||
198
README
198
README
@@ -4,7 +4,7 @@
|
|||||||
\__\__/\____/\_____/__/ ____ ___
|
\__\__/\____/\_____/__/ ____ ___
|
||||||
/ _/ / \ \ / _ \/ _/
|
/ _/ / \ \ / _ \/ _/
|
||||||
/ \_/ / / \ \ __/ \__
|
/ \_/ / / \ \ __/ \__
|
||||||
\____/____/\_____/_____/____/v0.5.0
|
\____/____/\_____/_____/____/v1.2.1
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
============
|
============
|
||||||
@@ -20,7 +20,7 @@ https://chromium.googlesource.com/webm/libwebp
|
|||||||
|
|
||||||
It is released under the same license as the WebM project.
|
It is released under the same license as the WebM project.
|
||||||
See http://www.webmproject.org/license/software/ or the
|
See http://www.webmproject.org/license/software/ or the
|
||||||
file "COPYING" file for details. An additional intellectual
|
"COPYING" file for details. An additional intellectual
|
||||||
property rights grant can be found in the file PATENTS.
|
property rights grant can be found in the file PATENTS.
|
||||||
|
|
||||||
Building:
|
Building:
|
||||||
@@ -84,6 +84,82 @@ be installed independently using a minor modification in the corresponding
|
|||||||
Makefile.am configure files (see comments there). See './configure --help' for
|
Makefile.am configure files (see comments there). See './configure --help' for
|
||||||
more options.
|
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:
|
SWIG bindings:
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@@ -149,12 +225,14 @@ Usage:
|
|||||||
|
|
||||||
If input size (-s) for an image is not specified, it is
|
If input size (-s) for an image is not specified, it is
|
||||||
assumed to be a PNG, JPEG, TIFF or WebP file.
|
assumed to be a PNG, JPEG, TIFF or WebP file.
|
||||||
|
Note: Animated PNG and WebP files are not supported.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-h / -help ............ short help
|
-h / -help ............. short help
|
||||||
-H / -longhelp ........ long help
|
-H / -longhelp ......... long help
|
||||||
-q <float> ............. quality factor (0:small..100:big)
|
-q <float> ............. quality factor (0:small..100:big), default=75
|
||||||
-alpha_q <int> ......... transparency-compression quality (0..100)
|
-alpha_q <int> ......... transparency-compression quality (0..100),
|
||||||
|
default=100
|
||||||
-preset <string> ....... preset setting, one of:
|
-preset <string> ....... preset setting, one of:
|
||||||
default, photo, picture,
|
default, photo, picture,
|
||||||
drawing, icon, text
|
drawing, icon, text
|
||||||
@@ -162,20 +240,23 @@ Options:
|
|||||||
-z <int> ............... activates lossless preset with given
|
-z <int> ............... activates lossless preset with given
|
||||||
level in [0:fast, ..., 9:slowest]
|
level in [0:fast, ..., 9:slowest]
|
||||||
|
|
||||||
-m <int> ............... compression method (0=fast, 6=slowest)
|
-m <int> ............... compression method (0=fast, 6=slowest), default=4
|
||||||
-segments <int> ........ number of segments to use (1..4)
|
-segments <int> ........ number of segments to use (1..4), default=4
|
||||||
-size <int> ............ target size (in bytes)
|
-size <int> ............ target size (in bytes)
|
||||||
-psnr <float> .......... target PSNR (in dB. typically: 42)
|
-psnr <float> .......... target PSNR (in dB. typically: 42)
|
||||||
|
|
||||||
-s <int> <int> ......... input size (width x height) for YUV
|
-s <int> <int> ......... input size (width x height) for YUV
|
||||||
-sns <int> ............. spatial noise shaping (0:off, 100:max)
|
-sns <int> ............. spatial noise shaping (0:off, 100:max), default=50
|
||||||
-f <int> ............... filter strength (0=off..100)
|
-f <int> ............... filter strength (0=off..100), default=60
|
||||||
-sharpness <int> ....... filter sharpness (0:most .. 7:least sharp)
|
-sharpness <int> ....... filter sharpness (0:most .. 7:least sharp), default=0
|
||||||
-strong ................ use strong filter instead of simple (default)
|
-strong ................ use strong filter instead of simple (default)
|
||||||
-nostrong .............. use simple filter instead of strong
|
-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
|
-partition_limit <int> . limit quality to fit the 512k limit on
|
||||||
the first partition (0=no degradation ... 100=full)
|
the first partition (0=no degradation ... 100=full)
|
||||||
-pass <int> ............ analysis pass number (1..10)
|
-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
|
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
|
||||||
-resize <w> <h> ........ resize picture (after any cropping)
|
-resize <w> <h> ........ resize picture (after any cropping)
|
||||||
-mt .................... use multi-threading if available
|
-mt .................... use multi-threading if available
|
||||||
@@ -185,18 +266,18 @@ Options:
|
|||||||
-print_ssim ............ prints averaged SSIM distortion
|
-print_ssim ............ prints averaged SSIM distortion
|
||||||
-print_lsim ............ prints local-similarity distortion
|
-print_lsim ............ prints local-similarity distortion
|
||||||
-d <file.pgm> .......... dump the compressed output (PGM file)
|
-d <file.pgm> .......... dump the compressed output (PGM file)
|
||||||
-alpha_method <int> .... transparency-compression method (0..1)
|
-alpha_method <int> .... transparency-compression method (0..1), default=1
|
||||||
-alpha_filter <string> . predictive filtering for alpha plane,
|
-alpha_filter <string> . predictive filtering for alpha plane,
|
||||||
one of: none, fast (default) or best
|
one of: none, fast (default) or best
|
||||||
-exact ................. preserve RGB values in transparent area
|
-exact ................. preserve RGB values in transparent area, default=off
|
||||||
-blend_alpha <hex> ..... blend colors against background color
|
-blend_alpha <hex> ..... blend colors against background color
|
||||||
expressed as RGB values written in
|
expressed as RGB values written in
|
||||||
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
|
hexadecimal, e.g. 0xc0e0d0 for red=0xc0
|
||||||
green=0xe0 and blue=0xd0
|
green=0xe0 and blue=0xd0
|
||||||
-noalpha ............... discard any transparency information
|
-noalpha ............... discard any transparency information
|
||||||
-lossless .............. encode image losslessly
|
-lossless .............. encode image losslessly, default=off
|
||||||
-near_lossless <int> ... use near-lossless image
|
-near_lossless <int> ... use near-lossless image
|
||||||
preprocessing (0..100=off)
|
preprocessing (0..100=off), default=100
|
||||||
-hint <string> ......... specify image characteristics hint,
|
-hint <string> ......... specify image characteristics hint,
|
||||||
one of: photo, picture or graph
|
one of: photo, picture or graph
|
||||||
|
|
||||||
@@ -216,6 +297,7 @@ Experimental Options:
|
|||||||
-af .................... auto-adjust filter strength
|
-af .................... auto-adjust filter strength
|
||||||
-pre <int> ............. pre-processing filter
|
-pre <int> ............. pre-processing filter
|
||||||
|
|
||||||
|
|
||||||
The main options you might want to try in order to further tune the
|
The main options you might want to try in order to further tune the
|
||||||
visual quality are:
|
visual quality are:
|
||||||
-preset
|
-preset
|
||||||
@@ -263,7 +345,9 @@ The full list of options is available using -h:
|
|||||||
> dwebp -h
|
> dwebp -h
|
||||||
Usage: dwebp in_file [options] [-o out_file]
|
Usage: dwebp in_file [options] [-o out_file]
|
||||||
|
|
||||||
Decodes the WebP image file to PNG format [Default]
|
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:
|
Use following options to convert into alternate image formats:
|
||||||
-pam ......... save the raw RGBA samples as a color PAM
|
-pam ......... save the raw RGBA samples as a color PAM
|
||||||
-ppm ......... save the raw RGB samples as a color PPM
|
-ppm ......... save the raw RGB samples as a color PPM
|
||||||
@@ -274,7 +358,7 @@ Use following options to convert into alternate image formats:
|
|||||||
-yuv ......... save the raw YUV samples in flat layout
|
-yuv ......... save the raw YUV samples in flat layout
|
||||||
|
|
||||||
Other options are:
|
Other options are:
|
||||||
-version .... print version number and exit
|
-version ..... print version number and exit
|
||||||
-nofancy ..... don't use the fancy YUV420 upscaler
|
-nofancy ..... don't use the fancy YUV420 upscaler
|
||||||
-nofilter .... disable in-loop filtering
|
-nofilter .... disable in-loop filtering
|
||||||
-nodither .... disable dithering
|
-nodither .... disable dithering
|
||||||
@@ -286,11 +370,28 @@ Use following options to convert into alternate image formats:
|
|||||||
-flip ........ flip the output vertically
|
-flip ........ flip the output vertically
|
||||||
-alpha ....... only save the alpha plane
|
-alpha ....... only save the alpha plane
|
||||||
-incremental . use incremental decoding (useful for tests)
|
-incremental . use incremental decoding (useful for tests)
|
||||||
-h ....... this help message
|
-h ........... this help message
|
||||||
-v ....... verbose (e.g. print encoding/decoding times)
|
-v ........... verbose (e.g. print encoding/decoding times)
|
||||||
-quiet ....... quiet mode, don't print anything
|
-quiet ....... quiet mode, don't print anything
|
||||||
-noasm ....... disable all assembly optimizations
|
-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:
|
Visualization tool:
|
||||||
===================
|
===================
|
||||||
|
|
||||||
@@ -303,19 +404,22 @@ Usage: vwebp in_file [options]
|
|||||||
|
|
||||||
Decodes the WebP image file and visualize it using OpenGL
|
Decodes the WebP image file and visualize it using OpenGL
|
||||||
Options are:
|
Options are:
|
||||||
-version .... print version number and exit
|
-version ..... print version number and exit
|
||||||
-noicc ....... don't use the icc profile if present
|
-noicc ....... don't use the icc profile if present
|
||||||
-nofancy ..... don't use the fancy YUV420 upscaler
|
-nofancy ..... don't use the fancy YUV420 upscaler
|
||||||
-nofilter .... disable in-loop filtering
|
-nofilter .... disable in-loop filtering
|
||||||
-dither <int> dithering strength (0..100), default=50
|
-dither <int> dithering strength (0..100), default=50
|
||||||
-noalphadither disable alpha plane dithering
|
-noalphadither disable alpha plane dithering
|
||||||
|
-usebgcolor .. display background color
|
||||||
-mt .......... use multi-threading
|
-mt .......... use multi-threading
|
||||||
-info ........ print info
|
-info ........ print info
|
||||||
-h ....... this help message
|
-h ........... this help message
|
||||||
|
|
||||||
Keyboard shortcuts:
|
Keyboard shortcuts:
|
||||||
'c' ................ toggle use of color profile
|
'c' ................ toggle use of color profile
|
||||||
|
'b' ................ toggle background color display
|
||||||
'i' ................ overlay file information
|
'i' ................ overlay file information
|
||||||
|
'd' ................ disable blending & disposal (debug)
|
||||||
'q' / 'Q' / ESC .... quit
|
'q' / 'Q' / ESC .... quit
|
||||||
|
|
||||||
Building:
|
Building:
|
||||||
@@ -325,7 +429,7 @@ Prerequisites:
|
|||||||
1) OpenGL & OpenGL Utility Toolkit (GLUT)
|
1) OpenGL & OpenGL Utility Toolkit (GLUT)
|
||||||
Linux:
|
Linux:
|
||||||
$ sudo apt-get install freeglut3-dev mesa-common-dev
|
$ sudo apt-get install freeglut3-dev mesa-common-dev
|
||||||
Mac + XCode:
|
Mac + Xcode:
|
||||||
- These libraries should be available in the OpenGL / GLUT frameworks.
|
- These libraries should be available in the OpenGL / GLUT frameworks.
|
||||||
Windows:
|
Windows:
|
||||||
http://freeglut.sourceforge.net/index.php#download
|
http://freeglut.sourceforge.net/index.php#download
|
||||||
@@ -344,6 +448,41 @@ $ make -f makefile.unix examples/vwebp
|
|||||||
> nmake /f Makefile.vc CFG=release-static \
|
> nmake /f Makefile.vc CFG=release-static \
|
||||||
../obj/x64/release-static/bin/vwebp.exe
|
../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-level options] [image files...] [per-frame options...]
|
||||||
|
|
||||||
|
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 conversion:
|
||||||
========================
|
========================
|
||||||
Animated GIF files can be converted to WebP files with animation using the
|
Animated GIF files can be converted to WebP files with animation using the
|
||||||
@@ -353,7 +492,7 @@ vwebp.
|
|||||||
Usage:
|
Usage:
|
||||||
gif2webp [options] gif_file -o webp_file
|
gif2webp [options] gif_file -o webp_file
|
||||||
Options:
|
Options:
|
||||||
-h / -help ............ this help
|
-h / -help ............. this help
|
||||||
-lossy ................. encode image using lossy compression
|
-lossy ................. encode image using lossy compression
|
||||||
-mixed ................. for each frame in the image, pick lossy
|
-mixed ................. for each frame in the image, pick lossy
|
||||||
or lossless compression heuristically
|
or lossless compression heuristically
|
||||||
@@ -369,6 +508,8 @@ Options:
|
|||||||
-metadata <string> ..... comma separated list of metadata to
|
-metadata <string> ..... comma separated list of metadata to
|
||||||
copy from the input to the output if present
|
copy from the input to the output if present
|
||||||
Valid values: all, none, icc, xmp (default)
|
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
|
-mt .................... use multi-threading if available
|
||||||
|
|
||||||
-version ............... print version number and exit
|
-version ............... print version number and exit
|
||||||
@@ -397,6 +538,11 @@ Options:
|
|||||||
-min_psnr <float> ... minimum per-frame PSNR
|
-min_psnr <float> ... minimum per-frame PSNR
|
||||||
-raw_comparison ..... if this flag is not used, RGB is
|
-raw_comparison ..... if this flag is not used, RGB is
|
||||||
premultiplied before comparison
|
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:
|
Building:
|
||||||
---------
|
---------
|
||||||
@@ -457,7 +603,7 @@ The encoding flow looks like:
|
|||||||
// Setup a config, starting form a preset and tuning some additional
|
// Setup a config, starting form a preset and tuning some additional
|
||||||
// parameters
|
// parameters
|
||||||
WebPConfig config;
|
WebPConfig config;
|
||||||
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor))
|
if (!WebPConfigPreset(&config, WEBP_PRESET_PHOTO, quality_factor)) {
|
||||||
return 0; // version error
|
return 0; // version error
|
||||||
}
|
}
|
||||||
// ... additional tuning
|
// ... additional tuning
|
||||||
@@ -473,7 +619,7 @@ The encoding flow looks like:
|
|||||||
pic.width = width;
|
pic.width = width;
|
||||||
pic.height = height;
|
pic.height = height;
|
||||||
// allocated picture of dimension width x height
|
// allocated picture of dimension width x height
|
||||||
if (!WebPPictureAllocate(&pic)) {
|
if (!WebPPictureAlloc(&pic)) {
|
||||||
return 0; // memory error
|
return 0; // memory error
|
||||||
}
|
}
|
||||||
// at this point, 'pic' has been initialized as a container,
|
// at this point, 'pic' has been initialized as a container,
|
||||||
@@ -637,7 +783,7 @@ an otherwise too-large picture. Some CPU can be saved too, incidentally.
|
|||||||
Bugs:
|
Bugs:
|
||||||
=====
|
=====
|
||||||
|
|
||||||
Please report all bugs to our issue tracker:
|
Please report all bugs to the issue tracker:
|
||||||
https://bugs.chromium.org/p/webp
|
https://bugs.chromium.org/p/webp
|
||||||
Patches welcome! See this page to get started:
|
Patches welcome! See this page to get started:
|
||||||
http://www.webmproject.org/code/contribute/submitting-patches/
|
http://www.webmproject.org/code/contribute/submitting-patches/
|
||||||
|
|||||||
60
README.mux
60
README.mux
@@ -1,7 +1,7 @@
|
|||||||
__ __ ____ ____ ____ __ __ _ __ __
|
__ __ ____ ____ ____ __ __ _ __ __
|
||||||
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
|
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
|
||||||
\ / __/ _ \ __/ / / (_/ /__
|
\ / __/ _ \ __/ / / (_/ /__
|
||||||
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v0.3.0
|
\__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.2.1
|
||||||
|
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
@@ -25,12 +25,15 @@ A list of options is available using the -help command line flag:
|
|||||||
> webpmux -help
|
> webpmux -help
|
||||||
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
|
Usage: webpmux -get GET_OPTIONS INPUT -o OUTPUT
|
||||||
webpmux -set SET_OPTIONS INPUT -o OUTPUT
|
webpmux -set SET_OPTIONS INPUT -o OUTPUT
|
||||||
|
webpmux -duration DURATION_OPTIONS [-duration ...]
|
||||||
|
INPUT -o OUTPUT
|
||||||
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
|
webpmux -strip STRIP_OPTIONS INPUT -o OUTPUT
|
||||||
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
|
webpmux -frame FRAME_OPTIONS [-frame...] [-loop LOOP_COUNT]
|
||||||
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
|
[-bgcolor BACKGROUND_COLOR] -o OUTPUT
|
||||||
webpmux -info INPUT
|
webpmux -info INPUT
|
||||||
webpmux [-h|-help]
|
webpmux [-h|-help]
|
||||||
webpmux -version
|
webpmux -version
|
||||||
|
webpmux argument_file_name
|
||||||
|
|
||||||
GET_OPTIONS:
|
GET_OPTIONS:
|
||||||
Extract relevant data:
|
Extract relevant data:
|
||||||
@@ -40,14 +43,27 @@ GET_OPTIONS:
|
|||||||
frame n get nth frame
|
frame n get nth frame
|
||||||
|
|
||||||
SET_OPTIONS:
|
SET_OPTIONS:
|
||||||
Set color profile/metadata:
|
Set color profile/metadata/parameters:
|
||||||
icc file.icc set ICC profile
|
loop LOOP_COUNT set the loop count
|
||||||
exif file.exif set EXIF metadata
|
bgcolor BACKGROUND_COLOR set the animation background color
|
||||||
xmp file.xmp set XMP metadata
|
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,
|
where: 'file.icc' contains the ICC profile to be set,
|
||||||
'file.exif' contains the EXIF metadata to be set
|
'file.exif' contains the EXIF metadata to be set
|
||||||
'file.xmp' contains the XMP metadata to be set
|
'file.xmp' contains the XMP metadata to be set
|
||||||
|
|
||||||
|
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_OPTIONS:
|
||||||
Strip color profile/metadata:
|
Strip color profile/metadata:
|
||||||
icc strip ICC profile
|
icc strip ICC profile
|
||||||
@@ -79,6 +95,9 @@ INPUT & OUTPUT are in WebP format.
|
|||||||
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
|
Note: The nature of EXIF, XMP and ICC data is not checked and is assumed to be
|
||||||
valid.
|
valid.
|
||||||
|
|
||||||
|
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:
|
Visualization tool:
|
||||||
===================
|
===================
|
||||||
|
|
||||||
@@ -194,11 +213,40 @@ Code example:
|
|||||||
For a detailed AnimEncoder API reference, please refer to the header file
|
For a detailed AnimEncoder API reference, please refer to the header file
|
||||||
(src/webp/mux.h).
|
(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:
|
Bugs:
|
||||||
=====
|
=====
|
||||||
|
|
||||||
Please report all bugs to our issue tracker:
|
Please report all bugs to the issue tracker:
|
||||||
https://bugs.chromium.org/p/webp
|
https://bugs.chromium.org/p/webp
|
||||||
Patches welcome! See this page to get started:
|
Patches welcome! See this page to get started:
|
||||||
http://www.webmproject.org/code/contribute/submitting-patches/
|
http://www.webmproject.org/code/contribute/submitting-patches/
|
||||||
|
|||||||
75
README.webp_js
Normal file
75
README.webp_js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
__ __ ____ ____ ____ __ ____
|
||||||
|
/ \\/ \ _ \ _ \ _ \ (__)/ __\
|
||||||
|
\ / __/ _ \ __/ _) \_ \
|
||||||
|
\__\__/_____/____/_/ /____/____/
|
||||||
|
|
||||||
|
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.
|
||||||
435
build.gradle
Normal file
435
build.gradle
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
// Define dependencies.
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url "https://jcenter.bintray.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "com.android.tools.build:gradle:${ANDROID_GRADLE_PLUGIN_VERSION}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define versions in the project.
|
||||||
|
project.ext {
|
||||||
|
buildToolsVersion = "${BUILD_TOOLS_VERSION}"
|
||||||
|
compileSdkVersion = COMPILE_SDK_VERSION.toInteger()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Core libraries and executables.
|
||||||
|
apply plugin: "c"
|
||||||
|
def NEON
|
||||||
|
model {
|
||||||
|
buildTypes {
|
||||||
|
debug
|
||||||
|
release
|
||||||
|
}
|
||||||
|
platforms {
|
||||||
|
arm {
|
||||||
|
architecture "arm"
|
||||||
|
}
|
||||||
|
arm64 {
|
||||||
|
architecture "arm64"
|
||||||
|
}
|
||||||
|
x86 {
|
||||||
|
architecture "x86"
|
||||||
|
}
|
||||||
|
x64 {
|
||||||
|
architecture "x86_64"
|
||||||
|
}
|
||||||
|
mips32r2
|
||||||
|
mips32r5
|
||||||
|
mips64r6
|
||||||
|
}
|
||||||
|
toolChains {
|
||||||
|
gcc(Gcc) {
|
||||||
|
target("mips32r2") {
|
||||||
|
cCompiler.args "-mips32r2"
|
||||||
|
}
|
||||||
|
target("mips32r5") {
|
||||||
|
cCompiler.args "-mips32r5"
|
||||||
|
}
|
||||||
|
target("mips64r6") {
|
||||||
|
cCompiler.args "-mips64r6"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
if (toolChain in Gcc) {
|
||||||
|
cCompiler.args "-fPIC"
|
||||||
|
cCompiler.args "-Wall"
|
||||||
|
cCompiler.define "ANDROID"
|
||||||
|
cCompiler.define "HAVE_MALLOC_H"
|
||||||
|
}
|
||||||
|
// Optimizations.
|
||||||
|
if (buildType == buildTypes.release) {
|
||||||
|
if (toolChain in Gcc) {
|
||||||
|
cCompiler.args "-finline-functions"
|
||||||
|
cCompiler.args "-ffast-math"
|
||||||
|
cCompiler.args "-ffunction-sections"
|
||||||
|
cCompiler.args "-fdata-sections"
|
||||||
|
}
|
||||||
|
if (toolChain in Clang) {
|
||||||
|
cCompiler.args "-frename-registers -s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mips32 fails to build with clang from r14b
|
||||||
|
// https://bugs.chromium.org/p/webp/issues/detail?id=343
|
||||||
|
if (toolChain in Clang) {
|
||||||
|
if (getTargetPlatform() == "mips") {
|
||||||
|
cCompiler.args "-no-integrated-as"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check for NEON usage.
|
||||||
|
if (getTargetPlatform() == "arm") {
|
||||||
|
NEON = "c.neon"
|
||||||
|
cCompiler.define "HAVE_CPU_FEATURES_H"
|
||||||
|
} else {
|
||||||
|
NEON = "c"
|
||||||
|
}
|
||||||
|
|
||||||
|
cCompiler.args "-I" + file(".").absolutePath
|
||||||
|
}
|
||||||
|
// Link to pthread for shared libraries.
|
||||||
|
withType(SharedLibraryBinarySpec) {
|
||||||
|
if (toolChain in Gcc) {
|
||||||
|
cCompiler.define "HAVE_PTHREAD"
|
||||||
|
cCompiler.define "WEBP_USE_THREAD"
|
||||||
|
linker.args "-pthread"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
components {
|
||||||
|
webp(NativeLibrarySpec) {
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "src/dec"
|
||||||
|
include "alpha_dec.c"
|
||||||
|
include "buffer_dec.c"
|
||||||
|
include "frame_dec.c"
|
||||||
|
include "idec_dec.c"
|
||||||
|
include "io_dec.c"
|
||||||
|
include "quant_dec.c"
|
||||||
|
include "tree_dec.c"
|
||||||
|
include "vp8_dec.c"
|
||||||
|
include "vp8l_dec.c"
|
||||||
|
include "webp_dec.c"
|
||||||
|
srcDir "src/dsp"
|
||||||
|
include "alpha_processing.c"
|
||||||
|
include "alpha_processing_mips_dsp_r2.c"
|
||||||
|
include "alpha_processing_neon.$NEON"
|
||||||
|
include "alpha_processing_sse2.c"
|
||||||
|
include "alpha_processing_sse41.c"
|
||||||
|
include "cpu.c"
|
||||||
|
include "dec.c"
|
||||||
|
include "dec_clip_tables.c"
|
||||||
|
include "dec_mips32.c"
|
||||||
|
include "dec_mips_dsp_r2.c"
|
||||||
|
include "dec_msa.c"
|
||||||
|
include "dec_neon.$NEON"
|
||||||
|
include "dec_sse2.c"
|
||||||
|
include "dec_sse41.c"
|
||||||
|
include "filters.c"
|
||||||
|
include "filters_mips_dsp_r2.c"
|
||||||
|
include "filters_msa.c"
|
||||||
|
include "filters_neon.$NEON"
|
||||||
|
include "filters_sse2.c"
|
||||||
|
include "lossless.c"
|
||||||
|
include "lossless_mips_dsp_r2.c"
|
||||||
|
include "lossless_msa.c"
|
||||||
|
include "lossless_neon.$NEON"
|
||||||
|
include "lossless_sse2.c"
|
||||||
|
include "lossless_sse41.c"
|
||||||
|
include "rescaler.c"
|
||||||
|
include "rescaler_mips32.c"
|
||||||
|
include "rescaler_mips_dsp_r2.c"
|
||||||
|
include "rescaler_msa.c"
|
||||||
|
include "rescaler_neon.$NEON"
|
||||||
|
include "rescaler_sse2.c"
|
||||||
|
include "upsampling.c"
|
||||||
|
include "upsampling_mips_dsp_r2.c"
|
||||||
|
include "upsampling_msa.c"
|
||||||
|
include "upsampling_neon.$NEON"
|
||||||
|
include "upsampling_sse2.c"
|
||||||
|
include "upsampling_sse41.c"
|
||||||
|
include "yuv.c"
|
||||||
|
include "yuv_mips32.c"
|
||||||
|
include "yuv_mips_dsp_r2.c"
|
||||||
|
include "yuv_neon.$NEON"
|
||||||
|
include "yuv_sse2.c"
|
||||||
|
include "yuv_sse41.c"
|
||||||
|
srcDir "src/utils"
|
||||||
|
include "bit_reader_utils.c"
|
||||||
|
include "color_cache_utils.c"
|
||||||
|
include "filters_utils.c"
|
||||||
|
include "huffman_utils.c"
|
||||||
|
include "quant_levels_dec_utils.c"
|
||||||
|
include "random_utils.c"
|
||||||
|
include "rescaler_utils.c"
|
||||||
|
include "thread_utils.c"
|
||||||
|
include "utils.c"
|
||||||
|
srcDir "src/dsp"
|
||||||
|
include "cost.c"
|
||||||
|
include "cost_mips32.c"
|
||||||
|
include "cost_mips_dsp_r2.c"
|
||||||
|
include "cost_neon.$NEON"
|
||||||
|
include "cost_sse2.c"
|
||||||
|
include "enc.c"
|
||||||
|
include "enc_mips32.c"
|
||||||
|
include "enc_mips_dsp_r2.c"
|
||||||
|
include "enc_msa.c"
|
||||||
|
include "enc_neon.$NEON"
|
||||||
|
include "enc_sse2.c"
|
||||||
|
include "enc_sse41.c"
|
||||||
|
include "lossless_enc.c"
|
||||||
|
include "lossless_enc_mips32.c"
|
||||||
|
include "lossless_enc_mips_dsp_r2.c"
|
||||||
|
include "lossless_enc_msa.c"
|
||||||
|
include "lossless_enc_neon.$NEON"
|
||||||
|
include "lossless_enc_sse2.c"
|
||||||
|
include "lossless_enc_sse41.c"
|
||||||
|
include "ssim.c"
|
||||||
|
include "ssim_sse2.c"
|
||||||
|
srcDir "src/enc"
|
||||||
|
include "alpha_enc.c"
|
||||||
|
include "analysis_enc.c"
|
||||||
|
include "backward_references_cost_enc.c"
|
||||||
|
include "backward_references_enc.c"
|
||||||
|
include "config_enc.c"
|
||||||
|
include "cost_enc.c"
|
||||||
|
include "filter_enc.c"
|
||||||
|
include "frame_enc.c"
|
||||||
|
include "histogram_enc.c"
|
||||||
|
include "iterator_enc.c"
|
||||||
|
include "near_lossless_enc.c"
|
||||||
|
include "picture_enc.c"
|
||||||
|
include "picture_csp_enc.c"
|
||||||
|
include "picture_psnr_enc.c"
|
||||||
|
include "picture_rescale_enc.c"
|
||||||
|
include "picture_tools_enc.c"
|
||||||
|
include "predictor_enc.c"
|
||||||
|
include "quant_enc.c"
|
||||||
|
include "syntax_enc.c"
|
||||||
|
include "token_enc.c"
|
||||||
|
include "tree_enc.c"
|
||||||
|
include "vp8l_enc.c"
|
||||||
|
include "webp_enc.c"
|
||||||
|
srcDir "src/utils"
|
||||||
|
include "bit_writer_utils.c"
|
||||||
|
include "huffman_encode_utils.c"
|
||||||
|
include "quant_levels_utils.c"
|
||||||
|
}
|
||||||
|
exportedHeaders {
|
||||||
|
srcDir "src"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
webpdemux(NativeLibrarySpec) {
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "src/demux"
|
||||||
|
include "anim_decode.c"
|
||||||
|
include "demux.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
webpmux(NativeLibrarySpec) {
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "src/mux/"
|
||||||
|
include "anim_encode.c"
|
||||||
|
include "muxedit.c"
|
||||||
|
include "muxinternal.c"
|
||||||
|
include "muxread.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executables from examples.
|
||||||
|
example_util(NativeLibrarySpec) {
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
lib library: "webp", linkage: "static"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "./examples"
|
||||||
|
include "example_util.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imageio_util(NativeLibrarySpec) {
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
lib library: "webp", linkage: "static"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "./imageio"
|
||||||
|
include "imageio_util.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imagedec(NativeLibrarySpec) {
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
lib library: "webpdemux", linkage: "static"
|
||||||
|
lib library: "webp", linkage: "static"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "./imageio"
|
||||||
|
include "image_dec.c"
|
||||||
|
include "jpegdec.c"
|
||||||
|
include "metadata.c"
|
||||||
|
include "pngdec.c"
|
||||||
|
include "pnmdec.c"
|
||||||
|
include "tiffdec.c"
|
||||||
|
include "webpdec.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imageenc(NativeLibrarySpec) {
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
lib library: "webp", linkage: "static"
|
||||||
|
lib library: "imageio_util", linkage: "static"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "./imageio"
|
||||||
|
include "image_enc.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cwebp(NativeExecutableSpec) {
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
lib library: "example_util", linkage: "static"
|
||||||
|
lib library: "imagedec", linkage: "static"
|
||||||
|
lib library: "imageio_util", linkage: "static"
|
||||||
|
lib library: "webpdemux", linkage: "static"
|
||||||
|
lib library: "webp", linkage: "static"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "./examples"
|
||||||
|
include "cwebp.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dwebp(NativeExecutableSpec) {
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
lib library: "example_util", linkage: "static"
|
||||||
|
lib library: "imagedec", linkage: "static"
|
||||||
|
lib library: "imageenc", linkage: "static"
|
||||||
|
lib library: "imageio_util", linkage: "static"
|
||||||
|
lib library: "webpdemux", linkage: "static"
|
||||||
|
lib library: "webp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "./examples"
|
||||||
|
include "dwebp.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
webpmux_example(NativeExecutableSpec) {
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
lib library: "example_util", linkage: "static"
|
||||||
|
lib library: "imageio_util", linkage: "static"
|
||||||
|
lib library: "webpmux", linkage: "static"
|
||||||
|
lib library: "webp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "./examples"
|
||||||
|
include "webpmux.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img2webp_example(NativeExecutableSpec) {
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
lib library: "example_util", linkage: "static"
|
||||||
|
lib library: "imagedec", linkage: "static"
|
||||||
|
lib library: "imageio_util", linkage: "static"
|
||||||
|
lib library: "webpmux", linkage: "static"
|
||||||
|
lib library: "webpdemux", linkage: "static"
|
||||||
|
lib library: "webp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "./examples"
|
||||||
|
include "img2webp.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
webpinfo_example(NativeExecutableSpec) {
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
lib library: "example_util", linkage: "static"
|
||||||
|
lib library: "imageio_util", linkage: "static"
|
||||||
|
lib library: "webp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
c {
|
||||||
|
source {
|
||||||
|
srcDir "./examples"
|
||||||
|
include "webpinfo.c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks {
|
||||||
|
// Task to test all possible configurations.
|
||||||
|
buildAllExecutables(Task) {
|
||||||
|
dependsOn $.binaries.findAll { it.buildable }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
cmake/WebPConfig.cmake.in
Normal file
11
cmake/WebPConfig.cmake.in
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
set(WebP_VERSION @PROJECT_VERSION@)
|
||||||
|
set(WEBP_VERSION ${WebP_VERSION})
|
||||||
|
|
||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||||
|
|
||||||
|
set(WebP_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
|
||||||
|
set(WEBP_INCLUDE_DIRS ${WebP_INCLUDE_DIRS})
|
||||||
|
set(WebP_LIBRARIES "@INSTALLED_LIBRARIES@")
|
||||||
|
set(WEBP_LIBRARIES "${WebP_LIBRARIES}")
|
||||||
152
cmake/config.h.in
Normal file
152
cmake/config.h.in
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/* Adapted from the autotools src/webp/config.h.in. */
|
||||||
|
|
||||||
|
/* Define if building universal (internal helper macro) */
|
||||||
|
/* TODO: handle properly in CMake */
|
||||||
|
#cmakedefine AC_APPLE_UNIVERSAL_BUILD 1
|
||||||
|
|
||||||
|
/* Set to 1 if __builtin_bswap16 is available */
|
||||||
|
#cmakedefine HAVE_BUILTIN_BSWAP16 1
|
||||||
|
|
||||||
|
/* Set to 1 if __builtin_bswap32 is available */
|
||||||
|
#cmakedefine HAVE_BUILTIN_BSWAP32 1
|
||||||
|
|
||||||
|
/* Set to 1 if __builtin_bswap64 is available */
|
||||||
|
#cmakedefine HAVE_BUILTIN_BSWAP64 1
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <wincodec.h> header file. */
|
||||||
|
#cmakedefine HAVE_WINCODEC_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <windows.h> header file. */
|
||||||
|
#cmakedefine HAVE_WINDOWS_H 1
|
||||||
|
|
||||||
|
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||||
|
*/
|
||||||
|
/* TODO: handle properly in CMake */
|
||||||
|
#cmakedefine LT_OBJDIR "@LT_OBJDIR@"
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#cmakedefine PACKAGE "@PROJECT_NAME@"
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@"
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#cmakedefine PACKAGE_URL "@PACKAGE_URL@"
|
||||||
|
|
||||||
|
/* 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@"
|
||||||
|
|
||||||
|
/* Set to 1 if GIF library is installed */
|
||||||
|
#cmakedefine WEBP_HAVE_GIF 1
|
||||||
|
|
||||||
|
/* Set to 1 if OpenGL is supported */
|
||||||
|
#cmakedefine WEBP_HAVE_GL 1
|
||||||
|
|
||||||
|
/* Set to 1 if JPEG library is installed */
|
||||||
|
#cmakedefine WEBP_HAVE_JPEG 1
|
||||||
|
|
||||||
|
/* Set to 1 if Wasm SIMD is supported */
|
||||||
|
#cmakedefine WEBP_HAVE_WASM_SIMD
|
||||||
|
|
||||||
|
/* Set to 1 if NEON is supported */
|
||||||
|
#cmakedefine WEBP_HAVE_NEON
|
||||||
|
|
||||||
|
/* Set to 1 if runtime detection of NEON is enabled */
|
||||||
|
/* TODO: handle properly in CMake */
|
||||||
|
#cmakedefine WEBP_HAVE_NEON_RTCD
|
||||||
|
|
||||||
|
/* Set to 1 if PNG library is installed */
|
||||||
|
#cmakedefine WEBP_HAVE_PNG 1
|
||||||
|
|
||||||
|
/* Set to 1 if SDL library is installed */
|
||||||
|
#cmakedefine WEBP_HAVE_SDL 1
|
||||||
|
|
||||||
|
/* Set to 1 if SSE2 is supported */
|
||||||
|
#cmakedefine WEBP_HAVE_SSE2 1
|
||||||
|
|
||||||
|
/* Set to 1 if SSE4.1 is supported */
|
||||||
|
#cmakedefine WEBP_HAVE_SSE41 1
|
||||||
|
|
||||||
|
/* Set to 1 if TIFF library is installed */
|
||||||
|
#cmakedefine WEBP_HAVE_TIFF 1
|
||||||
|
|
||||||
|
/* Enable near lossless encoding */
|
||||||
|
#cmakedefine WEBP_NEAR_LOSSLESS 1
|
||||||
|
|
||||||
|
/* Undefine this to disable thread support. */
|
||||||
|
#cmakedefine WEBP_USE_THREAD 1
|
||||||
|
|
||||||
|
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||||
|
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||||
|
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||||
|
# if defined __BIG_ENDIAN__
|
||||||
|
# define WORDS_BIGENDIAN 1
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# ifndef WORDS_BIGENDIAN
|
||||||
|
# undef WORDS_BIGENDIAN
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
168
cmake/cpu.cmake
Normal file
168
cmake/cpu.cmake
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
# Copyright (c) 2021 Google LLC.
|
||||||
|
#
|
||||||
|
# Use of this source code is governed by a BSD-style license
|
||||||
|
# that can be found in the LICENSE file in the root of the source
|
||||||
|
# tree. An additional intellectual property rights grant can be found
|
||||||
|
# in the file PATENTS. All contributing project authors may
|
||||||
|
# be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
# Check for SIMD extensions.
|
||||||
|
include(CMakePushCheckState)
|
||||||
|
|
||||||
|
function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
|
||||||
|
if(NOT ENABLE_SIMD)
|
||||||
|
message(STATUS "Disabling ${WEBP_SIMD_FLAG} optimization.")
|
||||||
|
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE)
|
||||||
|
cmake_push_check_state()
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
check_c_source_compiles("
|
||||||
|
#include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\"
|
||||||
|
int main(void) {
|
||||||
|
#if !defined(WEBP_USE_${WEBP_SIMD_FLAG})
|
||||||
|
this is not valid code
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" 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)
|
||||||
|
else()
|
||||||
|
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# those are included in the names of WEBP_USE_* in c++ code.
|
||||||
|
set(WEBP_SIMD_FLAGS "WASM_SIMD;SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA")
|
||||||
|
set(WEBP_SIMD_FILE_EXTENSIONS
|
||||||
|
"_wasm.c;_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
|
||||||
|
if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
# With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2
|
||||||
|
# or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4
|
||||||
|
# flag, but an AVX one. Using that with SSE4 code risks generating illegal
|
||||||
|
# instructions when used on machines with SSE4 only. The flags are left for
|
||||||
|
# older (untested) versions to avoid any potential compatibility issues.
|
||||||
|
if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:")
|
||||||
|
set(SIMD_ENABLE_FLAGS)
|
||||||
|
else()
|
||||||
|
set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;")
|
||||||
|
endif()
|
||||||
|
set(SIMD_DISABLE_FLAGS)
|
||||||
|
else()
|
||||||
|
set(SIMD_ENABLE_FLAGS
|
||||||
|
"-msimd128;-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
|
||||||
|
set(SIMD_DISABLE_FLAGS
|
||||||
|
"-mno-simd128;-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_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
|
||||||
|
# optimizations but should (as this configuration does not exist anymore).
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
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.
|
||||||
|
if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 5)
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
# Emscripten supports SSE via compat headers, if WEBP_ENABLED_WASM_SIMD is
|
||||||
|
# specified skip testing those (because it will succeed).
|
||||||
|
if (EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 1 AND ${WEBP_ENABLE_WASM_SIMD})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG)
|
||||||
|
|
||||||
|
# First try with no extra flag added as the compiler might have default flags
|
||||||
|
# (especially on Android).
|
||||||
|
unset(WEBP_HAVE_${WEBP_SIMD_FLAG} CACHE)
|
||||||
|
cmake_push_check_state()
|
||||||
|
set(CMAKE_REQUIRED_FLAGS)
|
||||||
|
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
|
||||||
|
if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG})
|
||||||
|
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
|
||||||
|
# This enables using Emscripten's SSE compatibility headers.
|
||||||
|
if(EMSCRIPTEN)
|
||||||
|
set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG})
|
||||||
|
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
|
||||||
|
else()
|
||||||
|
if(MSVC AND SIMD_ENABLE_FLAGS)
|
||||||
|
# The detection for SSE2/SSE4 support under MSVC is based on the compiler
|
||||||
|
# version so e.g., clang-cl will require flags to enable the assembly.
|
||||||
|
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
|
||||||
|
else()
|
||||||
|
set(SIMD_COMPILE_FLAG " ")
|
||||||
|
endif()
|
||||||
|
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}")
|
||||||
|
if(WEBP_HAVE_${WEBP_SIMD_FLAG})
|
||||||
|
# Memorize the file and flags.
|
||||||
|
foreach(FILE ${SIMD_FILES})
|
||||||
|
list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE})
|
||||||
|
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG})
|
||||||
|
endforeach()
|
||||||
|
else()
|
||||||
|
# Remove the file from the list.
|
||||||
|
foreach(FILE ${SIMD_FILES})
|
||||||
|
list(APPEND WEBP_SIMD_FILES_NOT_TO_INCLUDE ${FILE})
|
||||||
|
endforeach()
|
||||||
|
# Explicitly disable SIMD.
|
||||||
|
if(SIMD_DISABLE_FLAGS)
|
||||||
|
list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
|
||||||
|
include(CheckCCompilerFlag)
|
||||||
|
if(SIMD_COMPILE_FLAG)
|
||||||
|
# Between 3.17.0 and 3.18.2 check_cxx_compiler_flag() sets a normal
|
||||||
|
# variable at parent scope while check_cxx_source_compiles() continues
|
||||||
|
# to set an internal cache variable, so we unset both to avoid the
|
||||||
|
# failure / success state persisting between checks. See
|
||||||
|
# https://gitlab.kitware.com/cmake/cmake/-/issues/21207.
|
||||||
|
unset(HAS_COMPILE_FLAG)
|
||||||
|
unset(HAS_COMPILE_FLAG CACHE)
|
||||||
|
check_c_compiler_flag(${SIMD_COMPILE_FLAG} HAS_COMPILE_FLAG)
|
||||||
|
if(HAS_COMPILE_FLAG)
|
||||||
|
# Do one more check for Clang to circumvent CMake issue 13194.
|
||||||
|
if(COMMAND check_compiler_flag_common_patterns)
|
||||||
|
# Only in CMake 3.0 and above.
|
||||||
|
check_compiler_flag_common_patterns(COMMON_PATTERNS)
|
||||||
|
else()
|
||||||
|
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})
|
||||||
|
if(NOT FLAG_${SIMD_COMPILE_FLAG})
|
||||||
|
unset(HAS_COMPILE_FLAG)
|
||||||
|
unset(HAS_COMPILE_FLAG CACHE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(HAS_COMPILE_FLAG)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SIMD_COMPILE_FLAG}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
cmake_pop_check_state()
|
||||||
|
endforeach()
|
||||||
180
cmake/deps.cmake
Normal file
180
cmake/deps.cmake
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
# Copyright (c) 2021 Google LLC.
|
||||||
|
#
|
||||||
|
# Use of this source code is governed by a BSD-style license
|
||||||
|
# that can be found in the LICENSE file in the root of the source
|
||||||
|
# tree. An additional intellectual property rights grant can be found
|
||||||
|
# in the file PATENTS. All contributing project authors may
|
||||||
|
# be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
# Generate the config.h to compile with specific intrinsics / libs.
|
||||||
|
|
||||||
|
# Check for compiler options.
|
||||||
|
include(CheckCSourceCompiles)
|
||||||
|
check_c_source_compiles("
|
||||||
|
int main(void) {
|
||||||
|
(void)__builtin_bswap16(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_BUILTIN_BSWAP16)
|
||||||
|
check_c_source_compiles("
|
||||||
|
int main(void) {
|
||||||
|
(void)__builtin_bswap32(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_BUILTIN_BSWAP32)
|
||||||
|
check_c_source_compiles("
|
||||||
|
int main(void) {
|
||||||
|
(void)__builtin_bswap64(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_BUILTIN_BSWAP64)
|
||||||
|
|
||||||
|
# Check for libraries.
|
||||||
|
if(WEBP_USE_THREAD)
|
||||||
|
find_package(Threads)
|
||||||
|
if(Threads_FOUND)
|
||||||
|
# work around cmake bug on QNX (https://cmake.org/Bug/view.php?id=11333)
|
||||||
|
if(CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
|
||||||
|
endif()
|
||||||
|
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})
|
||||||
|
endif()
|
||||||
|
set(WEBP_USE_THREAD ${Threads_FOUND})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# TODO: this seems unused, check with autotools.
|
||||||
|
set(LT_OBJDIR ".libs/")
|
||||||
|
|
||||||
|
# Only useful for vwebp, so useless for now.
|
||||||
|
find_package(OpenGL)
|
||||||
|
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("
|
||||||
|
#include <math.h>
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
return (int)pow(argc, 2.5);
|
||||||
|
}
|
||||||
|
" HAVE_MATH_LIBRARY)
|
||||||
|
if(NOT HAVE_MATH_LIBRARY)
|
||||||
|
message(STATUS "Adding -lm flag.")
|
||||||
|
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})
|
||||||
|
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("
|
||||||
|
#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)
|
||||||
|
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)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check for SIMD extensions.
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/cpu.cmake)
|
||||||
|
|
||||||
|
# Define extra info.
|
||||||
|
set(PACKAGE ${PROJECT_NAME})
|
||||||
|
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
|
||||||
|
${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)
|
||||||
|
set(${VAR} ${TMP_SUB} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
list(GET CONFIGURE_AC_PACKAGE_INFO 1 PACKAGE_VERSION)
|
||||||
|
strip_bracket(PACKAGE_VERSION)
|
||||||
|
list(GET CONFIGURE_AC_PACKAGE_INFO 2 PACKAGE_BUGREPORT)
|
||||||
|
strip_bracket(PACKAGE_BUGREPORT)
|
||||||
|
list(GET CONFIGURE_AC_PACKAGE_INFO 3 PACKAGE_URL)
|
||||||
|
strip_bracket(PACKAGE_URL)
|
||||||
|
|
||||||
|
# Build more info.
|
||||||
|
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||||
|
set(PACKAGE_TARNAME ${PACKAGE_NAME})
|
||||||
|
set(VERSION ${PACKAGE_VERSION})
|
||||||
4
codereview.settings
Normal file
4
codereview.settings
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# This file is used by git cl to get repository specific information.
|
||||||
|
GERRIT_HOST: True
|
||||||
|
CODE_REVIEW_SERVER: chromium-review.googlesource.com
|
||||||
|
GERRIT_SQUASH_UPLOADS: False
|
||||||
328
configure.ac
328
configure.ac
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libwebp], [0.5.0],
|
AC_INIT([libwebp], [1.2.1],
|
||||||
[https://bugs.chromium.org/p/webp],,
|
[https://bugs.chromium.org/p/webp],,
|
||||||
[http://developers.google.com/speed/webp])
|
[http://developers.google.com/speed/webp])
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
@@ -10,6 +10,7 @@ dnl === it must occur before LT_INIT (AC_PROG_LIBTOOL).
|
|||||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||||
|
|
||||||
AC_PROG_LIBTOOL
|
AC_PROG_LIBTOOL
|
||||||
|
AC_PROG_SED
|
||||||
AM_PROG_CC_C_O
|
AM_PROG_CC_C_O
|
||||||
|
|
||||||
dnl === Enable less verbose output when building.
|
dnl === Enable less verbose output when building.
|
||||||
@@ -31,6 +32,40 @@ AC_ARG_ENABLE([everything],
|
|||||||
SET_IF_UNSET([enable_libwebpextras], [$enableval])
|
SET_IF_UNSET([enable_libwebpextras], [$enableval])
|
||||||
SET_IF_UNSET([enable_libwebpmux], [$enableval])])
|
SET_IF_UNSET([enable_libwebpmux], [$enableval])])
|
||||||
|
|
||||||
|
dnl === Check whether libwebpmux should be built
|
||||||
|
AC_MSG_CHECKING(whether libwebpmux is to be built)
|
||||||
|
AC_ARG_ENABLE([libwebpmux],
|
||||||
|
AS_HELP_STRING([--disable-libwebpmux],
|
||||||
|
[Disable libwebpmux @<:@default=no@:>@]),
|
||||||
|
[], [enable_libwebpmux=yes])
|
||||||
|
AC_MSG_RESULT(${enable_libwebpmux-no})
|
||||||
|
AM_CONDITIONAL([BUILD_MUX], [test "$enable_libwebpmux" = "yes"])
|
||||||
|
|
||||||
|
dnl === Check whether libwebpdemux should be built
|
||||||
|
AC_MSG_CHECKING(whether libwebpdemux is to be built)
|
||||||
|
AC_ARG_ENABLE([libwebpdemux],
|
||||||
|
AS_HELP_STRING([--disable-libwebpdemux],
|
||||||
|
[Disable libwebpdemux @<:@default=no@:>@]),
|
||||||
|
[], [enable_libwebpdemux=yes])
|
||||||
|
AC_MSG_RESULT(${enable_libwebpdemux-no})
|
||||||
|
AM_CONDITIONAL([BUILD_DEMUX], [test "$enable_libwebpdemux" = "yes"])
|
||||||
|
|
||||||
|
dnl === Check whether decoder library should be built.
|
||||||
|
AC_MSG_CHECKING(whether decoder library is to be built)
|
||||||
|
AC_ARG_ENABLE([libwebpdecoder],
|
||||||
|
AS_HELP_STRING([--enable-libwebpdecoder],
|
||||||
|
[Build libwebpdecoder @<:@default=no@:>@]))
|
||||||
|
AC_MSG_RESULT(${enable_libwebpdecoder-no})
|
||||||
|
AM_CONDITIONAL([BUILD_LIBWEBPDECODER], [test "$enable_libwebpdecoder" = "yes"])
|
||||||
|
|
||||||
|
dnl === Check whether libwebpextras should be built
|
||||||
|
AC_MSG_CHECKING(whether libwebpextras is to be built)
|
||||||
|
AC_ARG_ENABLE([libwebpextras],
|
||||||
|
AS_HELP_STRING([--enable-libwebpextras],
|
||||||
|
[Build libwebpextras @<:@default=no@:>@]))
|
||||||
|
AC_MSG_RESULT(${enable_libwebpextras-no})
|
||||||
|
AM_CONDITIONAL([BUILD_EXTRAS], [test "$enable_libwebpextras" = "yes"])
|
||||||
|
|
||||||
dnl === If --enable-asserts is not defined, define NDEBUG
|
dnl === If --enable-asserts is not defined, define NDEBUG
|
||||||
|
|
||||||
AC_MSG_CHECKING(whether asserts are enabled)
|
AC_MSG_CHECKING(whether asserts are enabled)
|
||||||
@@ -66,15 +101,20 @@ AC_DEFUN([TEST_AND_ADD_CFLAGS],
|
|||||||
CFLAGS="$SAVED_CFLAGS"])
|
CFLAGS="$SAVED_CFLAGS"])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-fvisibility=hidden])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-fvisibility=hidden])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wall])
|
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], [-Wdeclaration-after-statement])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wextra])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat-nonliteral])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wfloat-conversion])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat-security])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-nonliteral])
|
||||||
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wformat -Wformat-security])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-declarations])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-declarations])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wmissing-prototypes])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wold-style-definition])
|
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], [-Wshadow])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wshorten-64-to-32])
|
||||||
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wundef])
|
||||||
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code-aggressive])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunreachable-code])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused-but-set-variable])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused-but-set-variable])
|
||||||
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused])
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wunused])
|
||||||
@@ -117,31 +157,6 @@ AS_IF([test "$GCC" = "yes" ], [
|
|||||||
AC_SUBST([AM_CFLAGS])
|
AC_SUBST([AM_CFLAGS])
|
||||||
|
|
||||||
dnl === Check for machine specific flags
|
dnl === Check for machine specific flags
|
||||||
AC_ARG_ENABLE([avx2],
|
|
||||||
AS_HELP_STRING([--disable-avx2],
|
|
||||||
[Disable detection of AVX2 support
|
|
||||||
@<:@default=auto@:>@]))
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_avx2" != "xno" -a "x$enable_sse4_1" != "xno" \
|
|
||||||
-a "x$enable_sse2" != "xno"], [
|
|
||||||
AVX2_CFLAGS="$INTRINSICS_CFLAGS $AVX2_FLAGS"
|
|
||||||
TEST_AND_ADD_CFLAGS([AVX2_FLAGS], [-mavx2])
|
|
||||||
AS_IF([test -n "$AVX2_FLAGS"], [
|
|
||||||
SAVED_CFLAGS=$CFLAGS
|
|
||||||
CFLAGS="$CFLAGS $AVX2_FLAGS"
|
|
||||||
AC_CHECK_HEADER([immintrin.h],
|
|
||||||
[AC_DEFINE(WEBP_HAVE_AVX2, [1],
|
|
||||||
[Set to 1 if AVX2 is supported])],
|
|
||||||
[AVX2_FLAGS=""],
|
|
||||||
dnl it's illegal to directly include avx2intrin.h, but it's
|
|
||||||
dnl included conditionally in immintrin.h, tricky!
|
|
||||||
[#ifndef __AVX2__
|
|
||||||
#error avx2 is not enabled
|
|
||||||
#endif
|
|
||||||
])
|
|
||||||
CFLAGS=$SAVED_CFLAGS])
|
|
||||||
AC_SUBST([AVX2_FLAGS])])
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([sse4.1],
|
AC_ARG_ENABLE([sse4.1],
|
||||||
AS_HELP_STRING([--disable-sse4.1],
|
AS_HELP_STRING([--disable-sse4.1],
|
||||||
[Disable detection of SSE4.1 support
|
[Disable detection of SSE4.1 support
|
||||||
@@ -178,6 +193,78 @@ AS_IF([test "x$enable_sse2" != "xno"], [
|
|||||||
CFLAGS=$SAVED_CFLAGS])
|
CFLAGS=$SAVED_CFLAGS])
|
||||||
AC_SUBST([SSE2_FLAGS])])
|
AC_SUBST([SSE2_FLAGS])])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([neon],
|
||||||
|
AS_HELP_STRING([--disable-neon],
|
||||||
|
[Disable detection of NEON support
|
||||||
|
@<:@default=auto@:>@]))
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([neon_rtcd],
|
||||||
|
AS_HELP_STRING([--disable-neon-rtcd],
|
||||||
|
[Disable runtime detection of NEON support via
|
||||||
|
/proc/cpuinfo on Linux hosts
|
||||||
|
@<:@default=auto@:>@]))
|
||||||
|
# For ARM(7) hosts:
|
||||||
|
# Both NEON flags unset and NEON support detected = build all modules with NEON
|
||||||
|
# NEON detected with the use of -mfpu=neon = build only NEON modules with NEON
|
||||||
|
AS_IF([test "x$enable_neon" != "xno"], [
|
||||||
|
case "$host_cpu" in
|
||||||
|
arm|armv7*)
|
||||||
|
# Test for NEON support without flags before falling back to -mfpu=neon
|
||||||
|
for flag in '' '-mfpu=neon'; do
|
||||||
|
LOCAL_NEON_FLAGS="$INTRINSICS_CFLAGS $NEON_FLAGS"
|
||||||
|
TEST_AND_ADD_CFLAGS([LOCAL_NEON_FLAGS], [$flag])
|
||||||
|
SAVED_CFLAGS=$CFLAGS
|
||||||
|
CFLAGS="$CFLAGS $LOCAL_NEON_FLAGS"
|
||||||
|
|
||||||
|
dnl Note AC_LANG_PROGRAM([]) uses an old-style main definition.
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#include <arm_neon.h>
|
||||||
|
int main(void) {
|
||||||
|
int8x8_t v = vdup_n_s8(0);
|
||||||
|
(void)v;
|
||||||
|
return 0;
|
||||||
|
}])],
|
||||||
|
[NEON_FLAGS="$(echo $LOCAL_NEON_FLAGS | $SED 's/^ *//')"
|
||||||
|
AS_IF([test -n "$NEON_FLAGS"], [
|
||||||
|
AS_IF([test "${host_os%%-*}" = "linux" -o \
|
||||||
|
"x$enable_neon_rtcd" = "xno"], [
|
||||||
|
CFLAGS=$SAVED_CFLAGS
|
||||||
|
AC_DEFINE(WEBP_HAVE_NEON, [1], [Set to 1 if NEON is supported])
|
||||||
|
break
|
||||||
|
],[
|
||||||
|
AC_MSG_WARN(m4_normalize([NEON runtime cpu-detection is
|
||||||
|
unavailable for ${host_os%%-*}. Force
|
||||||
|
with CFLAGS=-mfpu=neon or
|
||||||
|
--disable-neon-rtcd.]))
|
||||||
|
enable_neon_rtcd=no
|
||||||
|
NEON_FLAGS=""
|
||||||
|
])
|
||||||
|
],[
|
||||||
|
CFLAGS=$SAVED_CFLAGS
|
||||||
|
AC_DEFINE(WEBP_HAVE_NEON, [1], [Set to 1 if NEON is supported])
|
||||||
|
break
|
||||||
|
])])
|
||||||
|
CFLAGS=$SAVED_CFLAGS
|
||||||
|
done
|
||||||
|
|
||||||
|
AS_IF([test -n "$NEON_FLAGS"], [
|
||||||
|
# If NEON is available and rtcd is disabled apply NEON_FLAGS globally.
|
||||||
|
AS_IF([test "x$enable_neon_rtcd" = "xno"], [
|
||||||
|
AM_CFLAGS="$AM_CFLAGS $NEON_FLAGS"
|
||||||
|
NEON_FLAGS=""],
|
||||||
|
[AC_DEFINE(WEBP_HAVE_NEON_RTCD, [1],
|
||||||
|
[Set to 1 if runtime detection of NEON is enabled])])])
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
*android*) AC_CHECK_HEADERS([cpu-features.h]) ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
aarch64*|arm64*)
|
||||||
|
AC_DEFINE(WEBP_HAVE_NEON, [1], [Set to 1 if NEON is supported])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
AC_SUBST([NEON_FLAGS])])
|
||||||
|
|
||||||
dnl === CLEAR_LIBVARS([var_pfx])
|
dnl === CLEAR_LIBVARS([var_pfx])
|
||||||
dnl === Clears <var_pfx>_{INCLUDES,LIBS}.
|
dnl === Clears <var_pfx>_{INCLUDES,LIBS}.
|
||||||
AC_DEFUN([CLEAR_LIBVARS], [$1_INCLUDES=""; $1_LIBS=""])
|
AC_DEFUN([CLEAR_LIBVARS], [$1_INCLUDES=""; $1_LIBS=""])
|
||||||
@@ -221,7 +308,7 @@ dnl === AC_DEFINE'ing <define> if successful.
|
|||||||
AC_DEFUN([CHECK_FOR_BUILTIN],
|
AC_DEFUN([CHECK_FOR_BUILTIN],
|
||||||
[AC_LANG_PUSH([C])
|
[AC_LANG_PUSH([C])
|
||||||
AC_MSG_CHECKING([for $1])
|
AC_MSG_CHECKING([for $1])
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [$1($2)])],
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [(void)$1($2)])],
|
||||||
[AC_MSG_RESULT([yes])
|
[AC_MSG_RESULT([yes])
|
||||||
AC_DEFINE([$3], [1],
|
AC_DEFINE([$3], [1],
|
||||||
[Set to 1 if $1 is available])],
|
[Set to 1 if $1 is available])],
|
||||||
@@ -273,6 +360,8 @@ AS_IF([test "x$enable_gl" != "xno"], [
|
|||||||
# override with --with-gl*
|
# override with --with-gl*
|
||||||
glut_cflags="$glut_cflags|-framework GLUT -framework OpenGL"
|
glut_cflags="$glut_cflags|-framework GLUT -framework OpenGL"
|
||||||
glut_ldflags="$glut_ldflags|-framework GLUT -framework OpenGL"
|
glut_ldflags="$glut_ldflags|-framework GLUT -framework OpenGL"
|
||||||
|
# quiet deprecation warnings for glut
|
||||||
|
TEST_AND_ADD_CFLAGS([AM_CFLAGS], [-Wno-deprecated-declarations])
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@@ -357,10 +446,75 @@ AS_IF([test "x$enable_gl" != "xno"], [
|
|||||||
|
|
||||||
if test "$glut_support" = "yes" -a "$enable_libwebpdemux" = "yes"; then
|
if test "$glut_support" = "yes" -a "$enable_libwebpdemux" = "yes"; then
|
||||||
build_vwebp=yes
|
build_vwebp=yes
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE(
|
||||||
|
m4_normalize([Not building vwebp.
|
||||||
|
OpenGL libraries and --enable-libwebpdemux are required.]))
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
AM_CONDITIONAL([BUILD_VWEBP], [test "$build_vwebp" = "yes"])
|
AM_CONDITIONAL([BUILD_VWEBP], [test "$build_vwebp" = "yes"])
|
||||||
|
|
||||||
|
dnl === check for SDL support ===
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([sdl],
|
||||||
|
AS_HELP_STRING([--disable-sdl],
|
||||||
|
[Disable detection of SDL support
|
||||||
|
@<:@default=auto@:>@]))
|
||||||
|
AS_IF([test "x$enable_sdl" != "xno"], [
|
||||||
|
CLEAR_LIBVARS([SDL])
|
||||||
|
AC_PATH_PROGS([LIBSDL_CONFIG], [sdl-config])
|
||||||
|
if test -n "$LIBSDL_CONFIG"; then
|
||||||
|
SDL_INCLUDES=`$LIBSDL_CONFIG --cflags`
|
||||||
|
SDL_LIBS="`$LIBSDL_CONFIG --libs`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
WITHLIB_OPTION([sdl], [SDL])
|
||||||
|
|
||||||
|
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)])])
|
||||||
|
if test x"$sdl_header" != "xno"; then
|
||||||
|
AC_LANG_PUSH(C)
|
||||||
|
SDL_SAVED_LIBS="$LIBS"
|
||||||
|
for lib in "" "-lSDL" "-lSDLmain -lSDL"; do
|
||||||
|
LIBS="$SDL_SAVED_LIBS $lib"
|
||||||
|
# Perform a full link to ensure SDL_main is resolved if needed.
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
[AC_LANG_SOURCE([
|
||||||
|
#include <$sdl_header>
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
SDL_Init(0);
|
||||||
|
return 0;
|
||||||
|
}])],
|
||||||
|
[SDL_LIBS="$LDFLAGS $LIBS"
|
||||||
|
SDL_INCLUDES="$SDL_INCLUDES -DWEBP_HAVE_SDL"
|
||||||
|
AC_DEFINE(WEBP_HAVE_SDL, [1],
|
||||||
|
[Set to 1 if SDL library is installed])
|
||||||
|
sdl_support=yes]
|
||||||
|
)
|
||||||
|
if test x"$sdl_support" = "xyes"; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# LIBS is restored by LIBCHECK_EPILOGUE
|
||||||
|
AC_LANG_POP
|
||||||
|
if test x"$sdl_header" = "xSDL.h"; then
|
||||||
|
SDL_INCLUDES="$SDL_INCLUDES -DWEBP_HAVE_JUST_SDL_H"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
LIBCHECK_EPILOGUE([SDL])
|
||||||
|
|
||||||
|
if test x"$sdl_support" = "xyes"; then
|
||||||
|
build_vwebp_sdl=yes
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE([Not building vwebp-sdl. SDL library is required.])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
AM_CONDITIONAL([BUILD_VWEBP_SDL], [test "$build_vwebp_sdl" = "yes"])
|
||||||
|
|
||||||
dnl === check for PNG support ===
|
dnl === check for PNG support ===
|
||||||
|
|
||||||
AC_ARG_ENABLE([png], AS_HELP_STRING([--disable-png],
|
AC_ARG_ENABLE([png], AS_HELP_STRING([--disable-png],
|
||||||
@@ -478,17 +632,39 @@ AS_IF([test "x$enable_gif" != "xno"], [
|
|||||||
|
|
||||||
if test "$gif_support" = "yes" -a \
|
if test "$gif_support" = "yes" -a \
|
||||||
"$enable_libwebpdemux" = "yes"; then
|
"$enable_libwebpdemux" = "yes"; then
|
||||||
build_animdiff=yes
|
build_anim_diff=yes
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE(
|
||||||
|
[Not building anim_diff. libgif and --enable-libwebpdemux are required.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$gif_support" = "yes" -a \
|
if test "$gif_support" = "yes" -a \
|
||||||
"$enable_libwebpmux" = "yes"; then
|
"$enable_libwebpmux" = "yes"; then
|
||||||
build_gif2webp=yes
|
build_gif2webp=yes
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE(
|
||||||
|
[Not building gif2webp. libgif and --enable-libwebpmux are required.])
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_animdiff}" = "yes"])
|
AM_CONDITIONAL([BUILD_ANIMDIFF], [test "${build_anim_diff}" = "yes"])
|
||||||
AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"])
|
AM_CONDITIONAL([BUILD_GIF2WEBP], [test "${build_gif2webp}" = "yes"])
|
||||||
|
|
||||||
|
if test "$enable_libwebpdemux" = "yes" -a "$enable_libwebpmux" = "yes"; then
|
||||||
|
build_img2webp=yes
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE(
|
||||||
|
m4_normalize([Not building img2webp.
|
||||||
|
--enable-libwebpdemux & --enable-libwebpmux are required.]))
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL([BUILD_IMG2WEBP], [test "${build_img2webp}" = "yes"])
|
||||||
|
|
||||||
|
if test "$enable_libwebpmux" = "yes"; then
|
||||||
|
build_webpinfo=yes
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE([Not building webpinfo. --enable-libwebpdemux is required.])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL([BUILD_WEBPINFO], [test "${build_webpinfo}" = "yes"])
|
||||||
|
|
||||||
dnl === check for WIC support ===
|
dnl === check for WIC support ===
|
||||||
|
|
||||||
AC_ARG_ENABLE([wic],
|
AC_ARG_ENABLE([wic],
|
||||||
@@ -541,20 +717,7 @@ if test "$enable_wic" = "yes"; then
|
|||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
|
|
||||||
dnl === If --enable-aligned is defined, define WEBP_FORCE_ALIGNED
|
dnl === If --enable-swap-16bit-csp is defined, add -DWEBP_SWAP_16BIT_CSP=1
|
||||||
|
|
||||||
AC_MSG_CHECKING(if --enable-aligned option is specified)
|
|
||||||
AC_ARG_ENABLE([aligned],
|
|
||||||
AS_HELP_STRING([--enable-aligned],
|
|
||||||
[Force aligned memory operations in non-dsp code
|
|
||||||
(may be slower)]))
|
|
||||||
if test "$enable_aligned" = "yes"; then
|
|
||||||
AC_DEFINE(WEBP_FORCE_ALIGNED, [1],
|
|
||||||
[Define to 1 to force aligned memory operations])
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT(${enable_aligned-no})
|
|
||||||
|
|
||||||
dnl === If --enable-swap-16bit-csp is defined, add -DWEBP_SWAP_16BIT_CSP
|
|
||||||
|
|
||||||
USE_SWAP_16BIT_CSP=""
|
USE_SWAP_16BIT_CSP=""
|
||||||
AC_MSG_CHECKING(if --enable-swap-16bit-csp option is specified)
|
AC_MSG_CHECKING(if --enable-swap-16bit-csp option is specified)
|
||||||
@@ -562,68 +725,37 @@ AC_ARG_ENABLE([swap-16bit-csp],
|
|||||||
AS_HELP_STRING([--enable-swap-16bit-csp],
|
AS_HELP_STRING([--enable-swap-16bit-csp],
|
||||||
[Enable byte swap for 16 bit colorspaces]))
|
[Enable byte swap for 16 bit colorspaces]))
|
||||||
if test "$enable_swap_16bit_csp" = "yes"; then
|
if test "$enable_swap_16bit_csp" = "yes"; then
|
||||||
USE_SWAP_16BIT_CSP="-DWEBP_SWAP_16BIT_CSP"
|
USE_SWAP_16BIT_CSP="-DWEBP_SWAP_16BIT_CSP=1"
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT(${enable_swap_16bit_csp-no})
|
AC_MSG_RESULT(${enable_swap_16bit_csp-no})
|
||||||
AC_SUBST(USE_SWAP_16BIT_CSP)
|
AC_SUBST(USE_SWAP_16BIT_CSP)
|
||||||
|
|
||||||
dnl === If --enable-experimental is defined, add -DWEBP_EXPERIMENTAL_FEATURES
|
dnl === If --disable-near-lossless is defined, add -DWEBP_NEAR_LOSSLESS=0
|
||||||
|
|
||||||
USE_EXPERIMENTAL_CODE=""
|
AC_DEFINE(WEBP_NEAR_LOSSLESS, [1], [Enable near lossless encoding])
|
||||||
AC_MSG_CHECKING(if --enable-experimental option is specified)
|
AC_MSG_CHECKING(if --disable-near-lossless option is specified)
|
||||||
AC_ARG_ENABLE([experimental], AS_HELP_STRING([--enable-experimental],
|
AC_ARG_ENABLE([near_lossless],
|
||||||
[Activate experimental features]))
|
AS_HELP_STRING([--disable-near-lossless],
|
||||||
if test "$enable_experimental" = "yes"; then
|
[Disable near lossless encoding]),
|
||||||
AC_DEFINE(WEBP_EXPERIMENTAL_FEATURES, [1], [Enable experimental code])
|
[], [enable_near_lossless=yes])
|
||||||
USE_EXPERIMENTAL_CODE="-DWEBP_EXPERIMENTAL_FEATURES"
|
if test "$enable_near_lossless" = "no"; then
|
||||||
|
AC_DEFINE(WEBP_NEAR_LOSSLESS, [0], [Enable near lossless encoding])
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT(${enable_experimental-no})
|
|
||||||
AC_SUBST(USE_EXPERIMENTAL_CODE)
|
|
||||||
|
|
||||||
dnl === Check whether libwebpmux should be built
|
|
||||||
AC_MSG_CHECKING(whether libwebpmux is to be built)
|
|
||||||
AC_ARG_ENABLE([libwebpmux],
|
|
||||||
AS_HELP_STRING([--enable-libwebpmux],
|
|
||||||
[Build libwebpmux @<:@default=no@:>@]))
|
|
||||||
AC_MSG_RESULT(${enable_libwebpmux-no})
|
|
||||||
AM_CONDITIONAL([WANT_MUX], [test "$enable_libwebpmux" = "yes"])
|
|
||||||
|
|
||||||
dnl === Check whether libwebpdemux should be built
|
|
||||||
AC_MSG_CHECKING(whether libwebpdemux is to be built)
|
|
||||||
AC_ARG_ENABLE([libwebpdemux],
|
|
||||||
AS_HELP_STRING([--enable-libwebpdemux],
|
|
||||||
[Build libwebpdemux @<:@default=no@:>@]))
|
|
||||||
AC_MSG_RESULT(${enable_libwebpdemux-no})
|
|
||||||
AM_CONDITIONAL([WANT_DEMUX], [test "$enable_libwebpdemux" = "yes"])
|
|
||||||
|
|
||||||
dnl === Check whether decoder library should be built.
|
|
||||||
AC_MSG_CHECKING(whether decoder library is to be built)
|
|
||||||
AC_ARG_ENABLE([libwebpdecoder],
|
|
||||||
AS_HELP_STRING([--enable-libwebpdecoder],
|
|
||||||
[Build libwebpdecoder @<:@default=no@:>@]))
|
|
||||||
AC_MSG_RESULT(${enable_libwebpdecoder-no})
|
|
||||||
AM_CONDITIONAL([BUILD_LIBWEBPDECODER], [test "$enable_libwebpdecoder" = "yes"])
|
|
||||||
|
|
||||||
dnl === Check whether libwebpextras should be built
|
|
||||||
AC_MSG_CHECKING(whether libwebpextras is to be built)
|
|
||||||
AC_ARG_ENABLE([libwebpextras],
|
|
||||||
AS_HELP_STRING([--enable-libwebpextras],
|
|
||||||
[Build libwebpextras @<:@default=no@:>@]))
|
|
||||||
AC_MSG_RESULT(${enable_libwebpextras-no})
|
|
||||||
AM_CONDITIONAL([WANT_EXTRAS], [test "$enable_libwebpextras" = "yes"])
|
|
||||||
|
|
||||||
dnl =========================
|
dnl =========================
|
||||||
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_HEADERS([src/webp/config.h])
|
AC_CONFIG_HEADERS([src/webp/config.h])
|
||||||
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \
|
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \
|
||||||
examples/Makefile src/dec/Makefile \
|
examples/Makefile extras/Makefile imageio/Makefile \
|
||||||
src/enc/Makefile src/dsp/Makefile \
|
src/dec/Makefile src/enc/Makefile src/dsp/Makefile \
|
||||||
src/demux/Makefile src/mux/Makefile \
|
src/demux/Makefile src/mux/Makefile \
|
||||||
src/utils/Makefile src/extras/Makefile \
|
src/utils/Makefile \
|
||||||
src/libwebp.pc src/libwebpdecoder.pc \
|
src/libwebp.pc src/libwebpdecoder.pc \
|
||||||
src/demux/libwebpdemux.pc src/mux/libwebpmux.pc \
|
src/demux/libwebpdemux.pc src/mux/libwebpmux.pc])
|
||||||
src/extras/libwebpextras.pc])
|
|
||||||
|
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
@@ -642,21 +774,25 @@ libwebpmux: ${enable_libwebpmux-no}
|
|||||||
libwebpextras: ${enable_libwebpextras-no}
|
libwebpextras: ${enable_libwebpextras-no}
|
||||||
|
|
||||||
Tools:
|
Tools:
|
||||||
cwebp : yes
|
cwebp : ${enable_libwebpdemux-no}
|
||||||
Input format support
|
Input format support
|
||||||
====================
|
====================
|
||||||
JPEG : ${jpeg_support-no}
|
JPEG : ${jpeg_support-no}
|
||||||
PNG : ${png_support-no}
|
PNG : ${png_support-no}
|
||||||
TIFF : ${tiff_support-no}
|
TIFF : ${tiff_support-no}
|
||||||
WIC : ${wic_support-no}
|
WIC : ${wic_support-no}
|
||||||
dwebp : yes
|
dwebp : ${enable_libwebpdemux-no}
|
||||||
Output format support
|
Output format support
|
||||||
=====================
|
=====================
|
||||||
PNG : ${png_support-no}
|
PNG : ${png_support-no}
|
||||||
WIC : ${wic_support-no}
|
WIC : ${wic_support-no}
|
||||||
GIF support : ${gif_support-no}
|
GIF support : ${gif_support-no}
|
||||||
anim_diff : ${build_animdiff-no}
|
anim_diff : ${build_anim_diff-no}
|
||||||
gif2webp : ${build_gif2webp-no}
|
gif2webp : ${build_gif2webp-no}
|
||||||
|
img2webp : ${build_img2webp-no}
|
||||||
webpmux : ${enable_libwebpmux-no}
|
webpmux : ${enable_libwebpmux-no}
|
||||||
vwebp : ${build_vwebp-no}
|
vwebp : ${build_vwebp-no}
|
||||||
|
webpinfo : ${build_webpinfo-no}
|
||||||
|
SDL support : ${sdl_support-no}
|
||||||
|
vwebp_sdl : ${build_vwebp_sdl-no}
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -53,10 +53,6 @@ document are to be interpreted as described in [RFC 2119][].
|
|||||||
Bit numbering in chunk diagrams starts at `0` for the most significant bit
|
Bit numbering in chunk diagrams starts at `0` for the most significant bit
|
||||||
('MSB 0') as described in [RFC 1166][].
|
('MSB 0') as described in [RFC 1166][].
|
||||||
|
|
||||||
**Note:** Out of the features mentioned above, lossy compression, lossless
|
|
||||||
compression, transparency, metadata, color profile and animation are finalized
|
|
||||||
and are to be considered stable.
|
|
||||||
|
|
||||||
Terminology & Basics
|
Terminology & Basics
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
@@ -269,7 +265,7 @@ An extended format file consists of:
|
|||||||
|
|
||||||
* An optional 'XMP ' chunk with XMP metadata.
|
* An optional 'XMP ' chunk with XMP metadata.
|
||||||
|
|
||||||
* An optional list of [unknown chunks](#unknown-chunks). _\[status: experimental\]_
|
* An optional list of [unknown chunks](#unknown-chunks).
|
||||||
|
|
||||||
For a _still image_, the _image data_ consists of a single frame, which is made
|
For a _still image_, the _image data_ consists of a single frame, which is made
|
||||||
up of:
|
up of:
|
||||||
@@ -446,8 +442,9 @@ Frame Height Minus One: 24 bits (_uint24_)
|
|||||||
Frame Duration: 24 bits (_uint24_)
|
Frame Duration: 24 bits (_uint24_)
|
||||||
|
|
||||||
: The time to wait before displaying the next frame, in 1 millisecond units.
|
: The time to wait before displaying the next frame, in 1 millisecond units.
|
||||||
In particular, frame duration of 0 is useful when one wants to update
|
Note the interpretation of frame duration of 0 (and often <= 10) is
|
||||||
multiple areas of the canvas at once during the animation.
|
implementation defined. Many tools and browsers assign a minimum duration
|
||||||
|
similar to GIF.
|
||||||
|
|
||||||
Reserved: 6 bits
|
Reserved: 6 bits
|
||||||
|
|
||||||
@@ -704,7 +701,7 @@ XMP Metadata: _Chunk Size_ bytes
|
|||||||
Additional guidance about handling metadata can be found in the
|
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 _\[status: experimental\]_
|
#### Unknown Chunks
|
||||||
|
|
||||||
A RIFF chunk (described in [this](#terminology-amp-basics) section) whose _chunk
|
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
|
tag_ is different from any of the chunks described in this document, is
|
||||||
@@ -815,7 +812,7 @@ RIFF/WEBP
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
[vp8spec]: http://tools.ietf.org/html/rfc6386
|
[vp8spec]: http://tools.ietf.org/html/rfc6386
|
||||||
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
|
[webpllspec]: https://chromium.googlesource.com/webm/libwebp/+/HEAD/doc/webp-lossless-bitstream-spec.txt
|
||||||
[iccspec]: http://www.color.org/icc_specs2.xalter
|
[iccspec]: http://www.color.org/icc_specs2.xalter
|
||||||
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
|
[metadata]: http://www.metadataworkinggroup.org/pdf/mwg_guidance.pdf
|
||||||
[rfc 1166]: http://tools.ietf.org/html/rfc1166
|
[rfc 1166]: http://tools.ietf.org/html/rfc1166
|
||||||
|
|||||||
@@ -429,6 +429,11 @@ int8 ColorTransformDelta(int8 t, int8 c) {
|
|||||||
}
|
}
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A conversion from the 8-bit unsigned representation (uint8) to the 8-bit
|
||||||
|
signed one (int8) is required before calling ColorTransformDelta().
|
||||||
|
It should be performed using 8-bit two's complement (that is: uint8 range
|
||||||
|
\[128-255\] is mapped to the \[-128, -1\] range of its converted int8 value).
|
||||||
|
|
||||||
The multiplication is to be done using more precision (with at least
|
The multiplication is to be done using more precision (with at least
|
||||||
16-bit dynamics). The sign extension property of the shift operation
|
16-bit dynamics). The sign extension property of the shift operation
|
||||||
does not matter here: only the lowest 8 bits are used from the result,
|
does not matter here: only the lowest 8 bits are used from the result,
|
||||||
|
|||||||
@@ -24,15 +24,9 @@ include $(CLEAR_VARS)
|
|||||||
# minor modification to their Android.mk files.
|
# minor modification to their Android.mk files.
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
cwebp.c \
|
cwebp.c \
|
||||||
jpegdec.c \
|
|
||||||
metadata.c \
|
|
||||||
pngdec.c \
|
|
||||||
tiffdec.c \
|
|
||||||
webpdec.c \
|
|
||||||
|
|
||||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
|
LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpdemux webp
|
||||||
LOCAL_STATIC_LIBRARIES := example_util webp
|
|
||||||
|
|
||||||
LOCAL_MODULE := cwebp
|
LOCAL_MODULE := cwebp
|
||||||
|
|
||||||
@@ -47,9 +41,7 @@ LOCAL_SRC_FILES := \
|
|||||||
dwebp.c \
|
dwebp.c \
|
||||||
|
|
||||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
|
LOCAL_STATIC_LIBRARIES := example_util imagedec imageenc webpdemux webp
|
||||||
LOCAL_STATIC_LIBRARIES := example_util webp
|
|
||||||
|
|
||||||
LOCAL_MODULE := dwebp
|
LOCAL_MODULE := dwebp
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
@@ -63,9 +55,39 @@ LOCAL_SRC_FILES := \
|
|||||||
webpmux.c \
|
webpmux.c \
|
||||||
|
|
||||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
|
LOCAL_STATIC_LIBRARIES := example_util imageio_util webpmux webp
|
||||||
LOCAL_STATIC_LIBRARIES := example_util webpmux webp
|
|
||||||
|
|
||||||
LOCAL_MODULE := webpmux_example
|
LOCAL_MODULE := webpmux_example
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# img2webp
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
img2webp.c \
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
|
LOCAL_STATIC_LIBRARIES := example_util imageio_util imagedec webpmux webpdemux \
|
||||||
|
webp
|
||||||
|
|
||||||
|
LOCAL_MODULE := img2webp_example
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# webpinfo
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
webpinfo.c \
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
|
LOCAL_STATIC_LIBRARIES := example_util imageio_util webp
|
||||||
|
|
||||||
|
LOCAL_MODULE := webpinfo_example
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|||||||
@@ -1,66 +1,119 @@
|
|||||||
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
|
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
|
||||||
|
|
||||||
bin_PROGRAMS = dwebp cwebp
|
bin_PROGRAMS =
|
||||||
if BUILD_VWEBP
|
if BUILD_DEMUX
|
||||||
bin_PROGRAMS += vwebp
|
bin_PROGRAMS += dwebp cwebp
|
||||||
endif
|
endif
|
||||||
if WANT_MUX
|
if BUILD_ANIMDIFF
|
||||||
bin_PROGRAMS += webpmux
|
noinst_PROGRAMS = anim_diff anim_dump
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_GIF2WEBP
|
if BUILD_GIF2WEBP
|
||||||
bin_PROGRAMS += gif2webp
|
bin_PROGRAMS += gif2webp
|
||||||
endif
|
endif
|
||||||
|
if BUILD_IMG2WEBP
|
||||||
noinst_LTLIBRARIES = libexampleutil.la
|
bin_PROGRAMS += img2webp
|
||||||
|
endif
|
||||||
libexampleutil_la_SOURCES = example_util.c example_util.h stopwatch.h
|
if BUILD_MUX
|
||||||
|
bin_PROGRAMS += webpmux
|
||||||
if BUILD_ANIMDIFF
|
endif
|
||||||
noinst_PROGRAMS = anim_diff
|
if BUILD_VWEBP
|
||||||
|
bin_PROGRAMS += vwebp
|
||||||
|
endif
|
||||||
|
if BUILD_WEBPINFO
|
||||||
|
bin_PROGRAMS += webpinfo
|
||||||
endif
|
endif
|
||||||
|
|
||||||
anim_diff_SOURCES = anim_diff.c anim_util.c anim_util.h
|
noinst_LTLIBRARIES = libexample_util.la
|
||||||
|
|
||||||
|
libexample_util_la_SOURCES = example_util.c example_util.h
|
||||||
|
libexample_util_la_LIBADD = ../src/libwebp.la
|
||||||
|
|
||||||
|
anim_diff_SOURCES = anim_diff.c anim_util.c anim_util.h gifdec.c gifdec.h
|
||||||
anim_diff_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES)
|
anim_diff_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES)
|
||||||
anim_diff_LDADD = ../src/demux/libwebpdemux.la
|
anim_diff_LDADD =
|
||||||
anim_diff_LDADD += libexampleutil.la
|
anim_diff_LDADD += ../src/demux/libwebpdemux.la
|
||||||
|
anim_diff_LDADD += libexample_util.la
|
||||||
|
anim_diff_LDADD += ../imageio/libimageio_util.la
|
||||||
anim_diff_LDADD += $(GIF_LIBS) -lm
|
anim_diff_LDADD += $(GIF_LIBS) -lm
|
||||||
|
|
||||||
dwebp_SOURCES = dwebp.c stopwatch.h
|
anim_dump_SOURCES = anim_dump.c anim_util.c anim_util.h gifdec.c gifdec.h
|
||||||
dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
|
anim_dump_CPPFLAGS = $(AM_CPPFLAGS) $(PNG_INCLUDES)
|
||||||
dwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES)
|
anim_dump_CPPFLAGS += $(GIF_INCLUDES)
|
||||||
dwebp_LDADD = libexampleutil.la $(PNG_LIBS) $(JPEG_LIBS)
|
anim_dump_LDADD =
|
||||||
|
anim_dump_LDADD += ../src/demux/libwebpdemux.la
|
||||||
|
anim_dump_LDADD += libexample_util.la
|
||||||
|
anim_dump_LDADD += ../imageio/libimageio_util.la
|
||||||
|
anim_dump_LDADD += ../imageio/libimageenc.la
|
||||||
|
anim_dump_LDADD += $(PNG_LIBS) $(GIF_LIBS) $(TIFF_LIBS) -lm
|
||||||
|
|
||||||
cwebp_SOURCES = cwebp.c metadata.c metadata.h stopwatch.h
|
cwebp_SOURCES = cwebp.c stopwatch.h
|
||||||
cwebp_SOURCES += jpegdec.c jpegdec.h
|
cwebp_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
cwebp_SOURCES += pngdec.c pngdec.h
|
cwebp_LDADD =
|
||||||
cwebp_SOURCES += tiffdec.c tiffdec.h
|
cwebp_LDADD += libexample_util.la
|
||||||
cwebp_SOURCES += webpdec.c webpdec.h
|
cwebp_LDADD += ../imageio/libimageio_util.la
|
||||||
cwebp_SOURCES += wicdec.c wicdec.h
|
cwebp_LDADD += ../imageio/libimagedec.la
|
||||||
cwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
|
cwebp_LDADD += ../src/libwebp.la
|
||||||
cwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES)
|
|
||||||
cwebp_LDADD = libexampleutil.la ../src/libwebp.la
|
|
||||||
cwebp_LDADD += $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS)
|
cwebp_LDADD += $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS)
|
||||||
|
|
||||||
|
dwebp_SOURCES = dwebp.c stopwatch.h
|
||||||
|
dwebp_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
dwebp_CPPFLAGS += $(JPEG_INCLUDES) $(PNG_INCLUDES)
|
||||||
|
dwebp_LDADD =
|
||||||
|
dwebp_LDADD += libexample_util.la
|
||||||
|
dwebp_LDADD += ../imageio/libimagedec.la
|
||||||
|
dwebp_LDADD += ../imageio/libimageenc.la
|
||||||
|
dwebp_LDADD += ../imageio/libimageio_util.la
|
||||||
|
dwebp_LDADD += ../src/libwebp.la
|
||||||
|
dwebp_LDADD +=$(PNG_LIBS) $(JPEG_LIBS)
|
||||||
|
|
||||||
gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h
|
gif2webp_SOURCES = gif2webp.c gifdec.c gifdec.h
|
||||||
gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GIF_INCLUDES)
|
gif2webp_CPPFLAGS = $(AM_CPPFLAGS) $(GIF_INCLUDES)
|
||||||
gif2webp_LDADD = libexampleutil.la ../src/mux/libwebpmux.la ../src/libwebp.la
|
gif2webp_LDADD =
|
||||||
|
gif2webp_LDADD += libexample_util.la
|
||||||
|
gif2webp_LDADD += ../imageio/libimageio_util.la
|
||||||
|
gif2webp_LDADD += ../src/mux/libwebpmux.la
|
||||||
|
gif2webp_LDADD += ../src/libwebp.la
|
||||||
gif2webp_LDADD += $(GIF_LIBS)
|
gif2webp_LDADD += $(GIF_LIBS)
|
||||||
|
|
||||||
webpmux_SOURCES = webpmux.c
|
|
||||||
webpmux_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
|
|
||||||
webpmux_LDADD = libexampleutil.la ../src/mux/libwebpmux.la ../src/libwebp.la
|
|
||||||
|
|
||||||
vwebp_SOURCES = vwebp.c
|
vwebp_SOURCES = vwebp.c
|
||||||
vwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) $(GL_INCLUDES)
|
vwebp_CPPFLAGS = $(AM_CPPFLAGS) $(GL_INCLUDES)
|
||||||
vwebp_LDADD = libexampleutil.la ../src/demux/libwebpdemux.la $(GL_LIBS)
|
vwebp_LDADD =
|
||||||
|
vwebp_LDADD += libexample_util.la
|
||||||
|
vwebp_LDADD += ../imageio/libimageio_util.la
|
||||||
|
vwebp_LDADD += ../src/demux/libwebpdemux.la
|
||||||
|
vwebp_LDADD += $(GL_LIBS)
|
||||||
|
|
||||||
|
webpmux_SOURCES = webpmux.c
|
||||||
|
webpmux_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
webpmux_LDADD =
|
||||||
|
webpmux_LDADD += libexample_util.la
|
||||||
|
webpmux_LDADD += ../imageio/libimageio_util.la
|
||||||
|
webpmux_LDADD += ../src/mux/libwebpmux.la
|
||||||
|
webpmux_LDADD += ../src/libwebp.la
|
||||||
|
|
||||||
|
img2webp_SOURCES = img2webp.c
|
||||||
|
img2webp_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
img2webp_LDADD =
|
||||||
|
img2webp_LDADD += libexample_util.la
|
||||||
|
img2webp_LDADD += ../imageio/libimageio_util.la
|
||||||
|
img2webp_LDADD += ../imageio/libimagedec.la
|
||||||
|
img2webp_LDADD += ../src/mux/libwebpmux.la
|
||||||
|
img2webp_LDADD += ../src/libwebp.la
|
||||||
|
img2webp_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS)
|
||||||
|
|
||||||
|
webpinfo_SOURCES = webpinfo.c
|
||||||
|
webpinfo_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
webpinfo_LDADD =
|
||||||
|
webpinfo_LDADD += libexample_util.la
|
||||||
|
webpinfo_LDADD += ../imageio/libimageio_util.la
|
||||||
|
webpinfo_LDADD += ../src/libwebp.la
|
||||||
|
|
||||||
if BUILD_LIBWEBPDECODER
|
if BUILD_LIBWEBPDECODER
|
||||||
anim_diff_LDADD += ../src/libwebpdecoder.la
|
anim_diff_LDADD += ../src/libwebpdecoder.la
|
||||||
dwebp_LDADD += ../src/libwebpdecoder.la
|
anim_dump_LDADD += ../src/libwebpdecoder.la
|
||||||
vwebp_LDADD += ../src/libwebpdecoder.la
|
vwebp_LDADD += ../src/libwebpdecoder.la
|
||||||
else
|
else
|
||||||
anim_diff_LDADD += ../src/libwebp.la
|
anim_diff_LDADD += ../src/libwebp.la
|
||||||
dwebp_LDADD += ../src/libwebp.la
|
anim_dump_LDADD += ../src/libwebp.la
|
||||||
vwebp_LDADD += ../src/libwebp.la
|
vwebp_LDADD += ../src/libwebp.la
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -13,12 +13,15 @@
|
|||||||
//
|
//
|
||||||
// example: anim_diff foo.gif bar.webp
|
// example: anim_diff foo.gif bar.webp
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h> // for 'strtod'.
|
#include <stdlib.h> // for 'strtod'.
|
||||||
#include <string.h> // for 'strcmp'.
|
#include <string.h> // for 'strcmp'.
|
||||||
|
|
||||||
#include "./anim_util.h"
|
#include "./anim_util.h"
|
||||||
|
#include "./example_util.h"
|
||||||
|
#include "./unicode.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
@@ -29,20 +32,67 @@ static int AdditionWillOverflow(int a, int b) {
|
|||||||
return (b > 0) && (a > INT_MAX - b);
|
return (b > 0) && (a > INT_MAX - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Minimize number of frames by combining successive frames that have exact same
|
static int FramesAreEqual(const uint8_t* const rgba1,
|
||||||
// ARGB data into a single longer duration frame.
|
const uint8_t* const rgba2, int width, int height) {
|
||||||
static void MinimizeAnimationFrames(AnimatedImage* const img) {
|
const int stride = width * 4; // Always true for 'DecodedFrame.rgba'.
|
||||||
|
return !memcmp(rgba1, rgba2, stride * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst,
|
||||||
|
int max_allowed_diff) {
|
||||||
|
const int src_a = (src >> 24) & 0xff;
|
||||||
|
const int src_r = (src >> 16) & 0xff;
|
||||||
|
const int src_g = (src >> 8) & 0xff;
|
||||||
|
const int src_b = (src >> 0) & 0xff;
|
||||||
|
const int dst_a = (dst >> 24) & 0xff;
|
||||||
|
const int dst_r = (dst >> 16) & 0xff;
|
||||||
|
const int dst_g = (dst >> 8) & 0xff;
|
||||||
|
const int dst_b = (dst >> 0) & 0xff;
|
||||||
|
|
||||||
|
return (abs(src_r * src_a - dst_r * dst_a) <= (max_allowed_diff * 255)) &&
|
||||||
|
(abs(src_g * src_a - dst_g * dst_a) <= (max_allowed_diff * 255)) &&
|
||||||
|
(abs(src_b * src_a - dst_b * dst_a) <= (max_allowed_diff * 255)) &&
|
||||||
|
(abs(src_a - dst_a) <= max_allowed_diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int FramesAreSimilar(const uint8_t* const rgba1,
|
||||||
|
const uint8_t* const rgba2,
|
||||||
|
int width, int height, int max_allowed_diff) {
|
||||||
|
int i, j;
|
||||||
|
assert(max_allowed_diff > 0);
|
||||||
|
for (j = 0; j < height; ++j) {
|
||||||
|
for (i = 0; i < width; ++i) {
|
||||||
|
const int stride = width * 4;
|
||||||
|
const size_t offset = j * stride + i;
|
||||||
|
if (!PixelsAreSimilar(rgba1[offset], rgba2[offset], max_allowed_diff)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minimize number of frames by combining successive frames that have at max
|
||||||
|
// 'max_diff' difference per channel between corresponding pixels.
|
||||||
|
static void MinimizeAnimationFrames(AnimatedImage* const img, int max_diff) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 1; i < img->num_frames; ++i) {
|
for (i = 1; i < img->num_frames; ++i) {
|
||||||
DecodedFrame* const frame1 = &img->frames[i - 1];
|
DecodedFrame* const frame1 = &img->frames[i - 1];
|
||||||
DecodedFrame* const frame2 = &img->frames[i];
|
DecodedFrame* const frame2 = &img->frames[i];
|
||||||
const uint8_t* const rgba1 = frame1->rgba;
|
const uint8_t* const rgba1 = frame1->rgba;
|
||||||
const uint8_t* const rgba2 = frame2->rgba;
|
const uint8_t* const rgba2 = frame2->rgba;
|
||||||
|
int should_merge_frames = 0;
|
||||||
// If merging frames will result in integer overflow for 'duration',
|
// If merging frames will result in integer overflow for 'duration',
|
||||||
// skip merging.
|
// skip merging.
|
||||||
if (AdditionWillOverflow(frame1->duration, frame2->duration)) continue;
|
if (AdditionWillOverflow(frame1->duration, frame2->duration)) continue;
|
||||||
if (!memcmp(rgba1, rgba2, img->canvas_width * 4 * img->canvas_height)) {
|
if (max_diff > 0) {
|
||||||
// Merge 'i+1'th frame into 'i'th frame.
|
should_merge_frames = FramesAreSimilar(rgba1, rgba2, img->canvas_width,
|
||||||
|
img->canvas_height, max_diff);
|
||||||
|
} else {
|
||||||
|
should_merge_frames =
|
||||||
|
FramesAreEqual(rgba1, rgba2, img->canvas_width, img->canvas_height);
|
||||||
|
}
|
||||||
|
if (should_merge_frames) { // Merge 'i+1'th frame into 'i'th frame.
|
||||||
frame1->duration += frame2->duration;
|
frame1->duration += frame2->duration;
|
||||||
if (i + 1 < img->num_frames) {
|
if (i + 1 < img->num_frames) {
|
||||||
memmove(&img->frames[i], &img->frames[i + 1],
|
memmove(&img->frames[i], &img->frames[i + 1],
|
||||||
@@ -62,6 +112,20 @@ static int CompareValues(uint32_t a, uint32_t b, const char* output_str) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CompareBackgroundColor(uint32_t bg1, uint32_t bg2, int premultiply) {
|
||||||
|
if (premultiply) {
|
||||||
|
const int alpha1 = (bg1 >> 24) & 0xff;
|
||||||
|
const int alpha2 = (bg2 >> 24) & 0xff;
|
||||||
|
if (alpha1 == 0 && alpha2 == 0) return 1;
|
||||||
|
}
|
||||||
|
if (bg1 != bg2) {
|
||||||
|
fprintf(stderr, "Background color mismatch: 0x%08x vs 0x%08x\n",
|
||||||
|
bg1, bg2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Note: As long as frame durations and reconstructed frames are identical, it
|
// Note: As long as frame durations and reconstructed frames are identical, it
|
||||||
// is OK for other aspects like offsets, dispose/blend method to vary.
|
// is OK for other aspects like offsets, dispose/blend method to vary.
|
||||||
static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
||||||
@@ -81,10 +145,20 @@ static int CompareAnimatedImagePair(const AnimatedImage* const img1,
|
|||||||
if (!ok) return 0; // These are fatal failures, can't proceed.
|
if (!ok) return 0; // These are fatal failures, can't proceed.
|
||||||
|
|
||||||
if (is_multi_frame_image) { // Checks relevant for multi-frame images only.
|
if (is_multi_frame_image) { // Checks relevant for multi-frame images only.
|
||||||
ok = CompareValues(img1->loop_count, img2->loop_count,
|
int max_loop_count_workaround = 0;
|
||||||
"Loop count mismatch") && ok;
|
// Transcodes to webp increase the gif loop count by 1 for compatibility.
|
||||||
ok = CompareValues(img1->bgcolor, img2->bgcolor,
|
// When the gif has the maximum value the webp value will be off by one.
|
||||||
"Background color mismatch") && ok;
|
if ((img1->format == ANIM_GIF && img1->loop_count == 65536 &&
|
||||||
|
img2->format == ANIM_WEBP && img2->loop_count == 65535) ||
|
||||||
|
(img1->format == ANIM_WEBP && img1->loop_count == 65535 &&
|
||||||
|
img2->format == ANIM_GIF && img2->loop_count == 65536)) {
|
||||||
|
max_loop_count_workaround = 1;
|
||||||
|
}
|
||||||
|
ok = (max_loop_count_workaround ||
|
||||||
|
CompareValues(img1->loop_count, img2->loop_count,
|
||||||
|
"Loop count mismatch")) && ok;
|
||||||
|
ok = CompareBackgroundColor(img1->bgcolor, img2->bgcolor,
|
||||||
|
premultiply) && ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < img1->num_frames; ++i) {
|
for (i = 0; i < img1->num_frames; ++i) {
|
||||||
@@ -125,6 +199,11 @@ static void Help(void) {
|
|||||||
printf(" -min_psnr <float> ... minimum per-frame PSNR\n");
|
printf(" -min_psnr <float> ... minimum per-frame PSNR\n");
|
||||||
printf(" -raw_comparison ..... if this flag is not used, RGB is\n");
|
printf(" -raw_comparison ..... if this flag is not used, RGB is\n");
|
||||||
printf(" premultiplied before comparison\n");
|
printf(" premultiplied before comparison\n");
|
||||||
|
printf(" -max_diff <int> ..... maximum allowed difference per channel\n"
|
||||||
|
" between corresponding pixels in subsequent\n"
|
||||||
|
" frames\n");
|
||||||
|
printf(" -h .................. this help\n");
|
||||||
|
printf(" -version ............ print version number and exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
@@ -135,45 +214,54 @@ int main(int argc, const char* argv[]) {
|
|||||||
int got_input1 = 0;
|
int got_input1 = 0;
|
||||||
int got_input2 = 0;
|
int got_input2 = 0;
|
||||||
int premultiply = 1;
|
int premultiply = 1;
|
||||||
|
int max_diff = 0;
|
||||||
int i, c;
|
int i, c;
|
||||||
const char* files[2] = { NULL, NULL };
|
const char* files[2] = { NULL, NULL };
|
||||||
AnimatedImage images[2];
|
AnimatedImage images[2];
|
||||||
|
|
||||||
if (argc < 3) {
|
INIT_WARGV(argc, argv);
|
||||||
Help();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
if (!strcmp(argv[c], "-dump_frames")) {
|
if (!strcmp(argv[c], "-dump_frames")) {
|
||||||
if (c < argc - 1) {
|
if (c < argc - 1) {
|
||||||
dump_frames = 1;
|
dump_frames = 1;
|
||||||
dump_folder = argv[++c];
|
dump_folder = (const char*)GET_WARGV(argv, ++c);
|
||||||
} else {
|
} else {
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[c], "-min_psnr")) {
|
} else if (!strcmp(argv[c], "-min_psnr")) {
|
||||||
if (c < argc - 1) {
|
if (c < argc - 1) {
|
||||||
const char* const v = argv[++c];
|
min_psnr = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
char* end = NULL;
|
|
||||||
const double d = strtod(v, &end);
|
|
||||||
if (end == v) {
|
|
||||||
parse_error = 1;
|
|
||||||
fprintf(stderr, "Error! '%s' is not a floating point number.\n", v);
|
|
||||||
}
|
|
||||||
min_psnr = d;
|
|
||||||
} else {
|
} else {
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[c], "-raw_comparison")) {
|
} else if (!strcmp(argv[c], "-raw_comparison")) {
|
||||||
premultiply = 0;
|
premultiply = 0;
|
||||||
|
} else if (!strcmp(argv[c], "-max_diff")) {
|
||||||
|
if (c < argc - 1) {
|
||||||
|
max_diff = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
} else {
|
||||||
|
parse_error = 1;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
|
Help();
|
||||||
|
FREE_WARGV_AND_RETURN(0);
|
||||||
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
|
int dec_version, demux_version;
|
||||||
|
GetAnimatedImageVersions(&dec_version, &demux_version);
|
||||||
|
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
||||||
|
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
||||||
|
(dec_version >> 0) & 0xff,
|
||||||
|
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
|
||||||
|
(demux_version >> 0) & 0xff);
|
||||||
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else {
|
} else {
|
||||||
if (!got_input1) {
|
if (!got_input1) {
|
||||||
files[0] = argv[c];
|
files[0] = (const char*)GET_WARGV(argv, c);
|
||||||
got_input1 = 1;
|
got_input1 = 1;
|
||||||
} else if (!got_input2) {
|
} else if (!got_input2) {
|
||||||
files[1] = argv[c];
|
files[1] = (const char*)GET_WARGV(argv, c);
|
||||||
got_input2 = 1;
|
got_input2 = 1;
|
||||||
} else {
|
} else {
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
@@ -181,40 +269,49 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
if (parse_error) {
|
if (parse_error) {
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (argc < 3) {
|
||||||
|
Help();
|
||||||
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!got_input2) {
|
if (!got_input2) {
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dump_frames) {
|
if (dump_frames) {
|
||||||
printf("Dumping decoded frames in: %s\n", dump_folder);
|
WPRINTF("Dumping decoded frames in: %s\n", (const W_CHAR*)dump_folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(images, 0, sizeof(images));
|
memset(images, 0, sizeof(images));
|
||||||
for (i = 0; i < 2; ++i) {
|
for (i = 0; i < 2; ++i) {
|
||||||
printf("Decoding file: %s\n", files[i]);
|
WPRINTF("Decoding file: %s\n", (const W_CHAR*)files[i]);
|
||||||
if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) {
|
if (!ReadAnimatedImage(files[i], &images[i], dump_frames, dump_folder)) {
|
||||||
fprintf(stderr, "Error decoding file: %s\n Aborting.\n", files[i]);
|
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n",
|
||||||
|
(const W_CHAR*)files[i]);
|
||||||
return_code = -2;
|
return_code = -2;
|
||||||
goto End;
|
goto End;
|
||||||
} else {
|
} else {
|
||||||
MinimizeAnimationFrames(&images[i]);
|
MinimizeAnimationFrames(&images[i], max_diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CompareAnimatedImagePair(&images[0], &images[1],
|
if (!CompareAnimatedImagePair(&images[0], &images[1],
|
||||||
premultiply, min_psnr)) {
|
premultiply, min_psnr)) {
|
||||||
fprintf(stderr, "\nFiles %s and %s differ.\n", files[0], files[1]);
|
WFPRINTF(stderr, "\nFiles %s and %s differ.\n", (const W_CHAR*)files[0],
|
||||||
|
(const W_CHAR*)files[1]);
|
||||||
return_code = -3;
|
return_code = -3;
|
||||||
} else {
|
} else {
|
||||||
printf("\nFiles %s and %s are identical.\n", files[0], files[1]);
|
WPRINTF("\nFiles %s and %s are identical.\n", (const W_CHAR*)files[0],
|
||||||
|
(const W_CHAR*)files[1]);
|
||||||
return_code = 0;
|
return_code = 0;
|
||||||
}
|
}
|
||||||
End:
|
End:
|
||||||
ClearAnimatedImage(&images[0]);
|
ClearAnimatedImage(&images[0]);
|
||||||
ClearAnimatedImage(&images[1]);
|
ClearAnimatedImage(&images[1]);
|
||||||
return return_code;
|
FREE_WARGV_AND_RETURN(return_code);
|
||||||
}
|
}
|
||||||
|
|||||||
121
examples/anim_dump.c
Normal file
121
examples/anim_dump.c
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// Copyright 2017 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Decodes an animated WebP file and dumps the decoded frames as PNG or TIFF.
|
||||||
|
//
|
||||||
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h> // for 'strcmp'.
|
||||||
|
|
||||||
|
#include "./anim_util.h"
|
||||||
|
#include "webp/decode.h"
|
||||||
|
#include "../imageio/image_enc.h"
|
||||||
|
#include "./unicode.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void Help(void) {
|
||||||
|
printf("Usage: anim_dump [options] files...\n");
|
||||||
|
printf("\nOptions:\n");
|
||||||
|
printf(" -folder <string> .... dump folder (default: '.')\n");
|
||||||
|
printf(" -prefix <string> .... prefix for dumped frames "
|
||||||
|
"(default: 'dump_')\n");
|
||||||
|
printf(" -tiff ............... save frames as TIFF\n");
|
||||||
|
printf(" -pam ................ save frames as PAM\n");
|
||||||
|
printf(" -h .................. this help\n");
|
||||||
|
printf(" -version ............ print version number and exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
int error = 0;
|
||||||
|
const W_CHAR* dump_folder = TO_W_CHAR(".");
|
||||||
|
const W_CHAR* prefix = TO_W_CHAR("dump_");
|
||||||
|
const W_CHAR* suffix = TO_W_CHAR("png");
|
||||||
|
WebPOutputFileFormat format = PNG;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
INIT_WARGV(argc, argv);
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
Help();
|
||||||
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (c = 1; !error && c < argc; ++c) {
|
||||||
|
if (!strcmp(argv[c], "-folder")) {
|
||||||
|
if (c + 1 == argc) {
|
||||||
|
fprintf(stderr, "missing argument after option '%s'\n", argv[c]);
|
||||||
|
error = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dump_folder = GET_WARGV(argv, ++c);
|
||||||
|
} else if (!strcmp(argv[c], "-prefix")) {
|
||||||
|
if (c + 1 == argc) {
|
||||||
|
fprintf(stderr, "missing argument after option '%s'\n", argv[c]);
|
||||||
|
error = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prefix = GET_WARGV(argv, ++c);
|
||||||
|
} else if (!strcmp(argv[c], "-tiff")) {
|
||||||
|
format = TIFF;
|
||||||
|
suffix = TO_W_CHAR("tiff");
|
||||||
|
} else if (!strcmp(argv[c], "-pam")) {
|
||||||
|
format = PAM;
|
||||||
|
suffix = TO_W_CHAR("pam");
|
||||||
|
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
|
Help();
|
||||||
|
FREE_WARGV_AND_RETURN(0);
|
||||||
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
|
int dec_version, demux_version;
|
||||||
|
GetAnimatedImageVersions(&dec_version, &demux_version);
|
||||||
|
printf("WebP Decoder version: %d.%d.%d\nWebP Demux version: %d.%d.%d\n",
|
||||||
|
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
||||||
|
(dec_version >> 0) & 0xff,
|
||||||
|
(demux_version >> 16) & 0xff, (demux_version >> 8) & 0xff,
|
||||||
|
(demux_version >> 0) & 0xff);
|
||||||
|
FREE_WARGV_AND_RETURN(0);
|
||||||
|
} else {
|
||||||
|
uint32_t i;
|
||||||
|
AnimatedImage image;
|
||||||
|
const W_CHAR* const file = GET_WARGV(argv, c);
|
||||||
|
memset(&image, 0, sizeof(image));
|
||||||
|
WPRINTF("Decoding file: %s as %s/%sxxxx.%s\n",
|
||||||
|
file, dump_folder, prefix, suffix);
|
||||||
|
if (!ReadAnimatedImage((const char*)file, &image, 0, NULL)) {
|
||||||
|
WFPRINTF(stderr, "Error decoding file: %s\n Aborting.\n", file);
|
||||||
|
error = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (i = 0; !error && i < image.num_frames; ++i) {
|
||||||
|
W_CHAR out_file[1024];
|
||||||
|
WebPDecBuffer buffer;
|
||||||
|
WebPInitDecBuffer(&buffer);
|
||||||
|
buffer.colorspace = MODE_RGBA;
|
||||||
|
buffer.is_external_memory = 1;
|
||||||
|
buffer.width = image.canvas_width;
|
||||||
|
buffer.height = image.canvas_height;
|
||||||
|
buffer.u.RGBA.rgba = image.frames[i].rgba;
|
||||||
|
buffer.u.RGBA.stride = buffer.width * sizeof(uint32_t);
|
||||||
|
buffer.u.RGBA.size = buffer.u.RGBA.stride * buffer.height;
|
||||||
|
WSNPRINTF(out_file, sizeof(out_file), "%s/%s%.4d.%s",
|
||||||
|
dump_folder, prefix, i, suffix);
|
||||||
|
if (!WebPSaveImage(&buffer, format, (const char*)out_file)) {
|
||||||
|
WFPRINTF(stderr, "Error while saving image '%s'\n", out_file);
|
||||||
|
error = 1;
|
||||||
|
}
|
||||||
|
WebPFreeDecBuffer(&buffer);
|
||||||
|
}
|
||||||
|
ClearAnimatedImage(&image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FREE_WARGV_AND_RETURN(error ? 1 : 0);
|
||||||
|
}
|
||||||
@@ -16,13 +16,16 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef WEBP_HAVE_GIF
|
#if defined(WEBP_HAVE_GIF)
|
||||||
#include <gif_lib.h>
|
#include <gif_lib.h>
|
||||||
#endif
|
#endif
|
||||||
#include "webp/format_constants.h"
|
#include "webp/format_constants.h"
|
||||||
#include "webp/decode.h"
|
#include "webp/decode.h"
|
||||||
#include "webp/demux.h"
|
#include "webp/demux.h"
|
||||||
#include "./example_util.h"
|
#include "../imageio/imageio_util.h"
|
||||||
|
#include "./gifdec.h"
|
||||||
|
#include "./unicode.h"
|
||||||
|
#include "./unicode_gif.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
@@ -33,26 +36,39 @@ static const int kNumChannels = 4;
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Common utilities.
|
// Common utilities.
|
||||||
|
|
||||||
|
#if defined(WEBP_HAVE_GIF)
|
||||||
// Returns true if the frame covers the full canvas.
|
// Returns true if the frame covers the full canvas.
|
||||||
static int IsFullFrame(int width, int height,
|
static int IsFullFrame(int width, int height,
|
||||||
int canvas_width, int canvas_height) {
|
int canvas_width, int canvas_height) {
|
||||||
return (width == canvas_width && height == canvas_height);
|
return (width == canvas_width && height == canvas_height);
|
||||||
}
|
}
|
||||||
|
#endif // WEBP_HAVE_GIF
|
||||||
|
|
||||||
|
static int CheckSizeForOverflow(uint64_t size) {
|
||||||
|
return (size == (size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
static int AllocateFrames(AnimatedImage* const image, uint32_t num_frames) {
|
static int AllocateFrames(AnimatedImage* const image, uint32_t num_frames) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
const size_t rgba_size =
|
uint8_t* mem = NULL;
|
||||||
image->canvas_width * kNumChannels * image->canvas_height;
|
DecodedFrame* frames = NULL;
|
||||||
uint8_t* const mem = (uint8_t*)malloc(num_frames * rgba_size * sizeof(*mem));
|
const uint64_t rgba_size =
|
||||||
DecodedFrame* const frames =
|
(uint64_t)image->canvas_width * kNumChannels * image->canvas_height;
|
||||||
(DecodedFrame*)malloc(num_frames * sizeof(*frames));
|
const uint64_t total_size = (uint64_t)num_frames * rgba_size * sizeof(*mem);
|
||||||
|
const uint64_t total_frame_size = (uint64_t)num_frames * sizeof(*frames);
|
||||||
if (mem == NULL || frames == NULL) {
|
if (!CheckSizeForOverflow(total_size) ||
|
||||||
free(mem);
|
!CheckSizeForOverflow(total_frame_size)) {
|
||||||
free(frames);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
free(image->raw_mem);
|
mem = (uint8_t*)WebPMalloc((size_t)total_size);
|
||||||
|
frames = (DecodedFrame*)WebPMalloc((size_t)total_frame_size);
|
||||||
|
|
||||||
|
if (mem == NULL || frames == NULL) {
|
||||||
|
WebPFree(mem);
|
||||||
|
WebPFree(frames);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
WebPFree(image->raw_mem);
|
||||||
image->num_frames = num_frames;
|
image->num_frames = num_frames;
|
||||||
image->frames = frames;
|
image->frames = frames;
|
||||||
for (i = 0; i < num_frames; ++i) {
|
for (i = 0; i < num_frames; ++i) {
|
||||||
@@ -66,14 +82,15 @@ static int AllocateFrames(AnimatedImage* const image, uint32_t num_frames) {
|
|||||||
|
|
||||||
void ClearAnimatedImage(AnimatedImage* const image) {
|
void ClearAnimatedImage(AnimatedImage* const image) {
|
||||||
if (image != NULL) {
|
if (image != NULL) {
|
||||||
free(image->raw_mem);
|
WebPFree(image->raw_mem);
|
||||||
free(image->frames);
|
WebPFree(image->frames);
|
||||||
image->num_frames = 0;
|
image->num_frames = 0;
|
||||||
image->frames = NULL;
|
image->frames = NULL;
|
||||||
image->raw_mem = NULL;
|
image->raw_mem = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(WEBP_HAVE_GIF)
|
||||||
// Clear the canvas to transparent.
|
// Clear the canvas to transparent.
|
||||||
static void ZeroFillCanvas(uint8_t* rgba,
|
static void ZeroFillCanvas(uint8_t* rgba,
|
||||||
uint32_t canvas_width, uint32_t canvas_height) {
|
uint32_t canvas_width, uint32_t canvas_height) {
|
||||||
@@ -115,6 +132,7 @@ static void CopyFrameRectangle(const uint8_t* src, uint8_t* dst, int stride,
|
|||||||
dst += stride;
|
dst += stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // WEBP_HAVE_GIF
|
||||||
|
|
||||||
// Canonicalize all transparent pixels to transparent black to aid comparison.
|
// Canonicalize all transparent pixels to transparent black to aid comparison.
|
||||||
static void CleanupTransparentPixels(uint32_t* rgba,
|
static void CleanupTransparentPixels(uint32_t* rgba,
|
||||||
@@ -136,46 +154,50 @@ static int DumpFrame(const char filename[], const char dump_folder[],
|
|||||||
int ok = 0;
|
int ok = 0;
|
||||||
size_t max_len;
|
size_t max_len;
|
||||||
int y;
|
int y;
|
||||||
const char* base_name = NULL;
|
const W_CHAR* base_name = NULL;
|
||||||
char* file_name = NULL;
|
W_CHAR* file_name = NULL;
|
||||||
FILE* f = NULL;
|
FILE* f = NULL;
|
||||||
|
const char* row;
|
||||||
|
|
||||||
base_name = strrchr(filename, '/');
|
if (dump_folder == NULL) dump_folder = (const char*)TO_W_CHAR(".");
|
||||||
base_name = (base_name == NULL) ? filename : base_name + 1;
|
|
||||||
max_len = strlen(dump_folder) + 1 + strlen(base_name)
|
base_name = WSTRRCHR(filename, '/');
|
||||||
|
base_name = (base_name == NULL) ? (const W_CHAR*)filename : base_name + 1;
|
||||||
|
max_len = WSTRLEN(dump_folder) + 1 + WSTRLEN(base_name)
|
||||||
+ strlen("_frame_") + strlen(".pam") + 8;
|
+ strlen("_frame_") + strlen(".pam") + 8;
|
||||||
file_name = (char*)malloc(max_len * sizeof(*file_name));
|
file_name = (W_CHAR*)WebPMalloc(max_len * sizeof(*file_name));
|
||||||
if (file_name == NULL) goto End;
|
if (file_name == NULL) goto End;
|
||||||
|
|
||||||
if (snprintf(file_name, max_len, "%s/%s_frame_%d.pam",
|
if (WSNPRINTF(file_name, max_len, "%s/%s_frame_%d.pam",
|
||||||
dump_folder, base_name, frame_num) < 0) {
|
(const W_CHAR*)dump_folder, base_name, frame_num) < 0) {
|
||||||
fprintf(stderr, "Error while generating file name\n");
|
fprintf(stderr, "Error while generating file name\n");
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fopen(file_name, "wb");
|
f = WFOPEN(file_name, "wb");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
fprintf(stderr, "Error opening file for writing: %s\n", file_name);
|
WFPRINTF(stderr, "Error opening file for writing: %s\n", file_name);
|
||||||
ok = 0;
|
ok = 0;
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
if (fprintf(f, "P7\nWIDTH %d\nHEIGHT %d\n"
|
if (fprintf(f, "P7\nWIDTH %d\nHEIGHT %d\n"
|
||||||
"DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
|
"DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
|
||||||
canvas_width, canvas_height) < 0) {
|
canvas_width, canvas_height) < 0) {
|
||||||
fprintf(stderr, "Write error for file %s\n", file_name);
|
WFPRINTF(stderr, "Write error for file %s\n", file_name);
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
row = (const char*)rgba;
|
||||||
for (y = 0; y < canvas_height; ++y) {
|
for (y = 0; y < canvas_height; ++y) {
|
||||||
if (fwrite((const char*)(rgba) + y * canvas_width * kNumChannels,
|
if (fwrite(row, canvas_width * kNumChannels, 1, f) != 1) {
|
||||||
canvas_width * kNumChannels, 1, f) != 1) {
|
WFPRINTF(stderr, "Error writing to file: %s\n", file_name);
|
||||||
fprintf(stderr, "Error writing to file: %s\n", file_name);
|
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
row += canvas_width * kNumChannels;
|
||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
End:
|
End:
|
||||||
if (f != NULL) fclose(f);
|
if (f != NULL) fclose(f);
|
||||||
free(file_name);
|
WebPFree(file_name);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +209,7 @@ static int IsWebP(const WebPData* const webp_data) {
|
|||||||
return (WebPGetInfo(webp_data->bytes, webp_data->size, NULL, NULL) != 0);
|
return (WebPGetInfo(webp_data->bytes, webp_data->size, NULL, NULL) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read animated WebP bitstream 'file_str' into 'AnimatedImage' struct.
|
// Read animated WebP bitstream 'webp_data' into 'AnimatedImage' struct.
|
||||||
static int ReadAnimatedWebP(const char filename[],
|
static int ReadAnimatedWebP(const char filename[],
|
||||||
const WebPData* const webp_data,
|
const WebPData* const webp_data,
|
||||||
AnimatedImage* const image, int dump_frames,
|
AnimatedImage* const image, int dump_frames,
|
||||||
@@ -203,7 +225,7 @@ static int ReadAnimatedWebP(const char filename[],
|
|||||||
|
|
||||||
dec = WebPAnimDecoderNew(webp_data, NULL);
|
dec = WebPAnimDecoderNew(webp_data, NULL);
|
||||||
if (dec == NULL) {
|
if (dec == NULL) {
|
||||||
fprintf(stderr, "Error parsing image: %s\n", filename);
|
WFPRINTF(stderr, "Error parsing image: %s\n", (const W_CHAR*)filename);
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,6 +254,7 @@ static int ReadAnimatedWebP(const char filename[],
|
|||||||
fprintf(stderr, "Error decoding frame #%u\n", frame_index);
|
fprintf(stderr, "Error decoding frame #%u\n", frame_index);
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
assert(frame_index < anim_info.frame_count);
|
||||||
curr_frame = &image->frames[frame_index];
|
curr_frame = &image->frames[frame_index];
|
||||||
curr_rgba = curr_frame->rgba;
|
curr_rgba = curr_frame->rgba;
|
||||||
curr_frame->duration = timestamp - prev_frame_timestamp;
|
curr_frame->duration = timestamp - prev_frame_timestamp;
|
||||||
@@ -255,6 +278,7 @@ static int ReadAnimatedWebP(const char filename[],
|
|||||||
prev_frame_timestamp = timestamp;
|
prev_frame_timestamp = timestamp;
|
||||||
}
|
}
|
||||||
ok = dump_ok;
|
ok = dump_ok;
|
||||||
|
if (ok) image->format = ANIM_WEBP;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
WebPAnimDecoderDelete(dec);
|
WebPAnimDecoderDelete(dec);
|
||||||
@@ -264,6 +288,8 @@ static int ReadAnimatedWebP(const char filename[],
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// GIF Decoding.
|
// GIF Decoding.
|
||||||
|
|
||||||
|
#if defined(WEBP_HAVE_GIF)
|
||||||
|
|
||||||
// Returns true if this is a valid GIF bitstream.
|
// Returns true if this is a valid GIF bitstream.
|
||||||
static int IsGIF(const WebPData* const data) {
|
static int IsGIF(const WebPData* const data) {
|
||||||
return data->size > GIF_STAMP_LEN &&
|
return data->size > GIF_STAMP_LEN &&
|
||||||
@@ -272,8 +298,6 @@ static int IsGIF(const WebPData* const data) {
|
|||||||
!memcmp(GIF89_STAMP, data->bytes, GIF_STAMP_LEN));
|
!memcmp(GIF89_STAMP, data->bytes, GIF_STAMP_LEN));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WEBP_HAVE_GIF
|
|
||||||
|
|
||||||
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
// GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
|
||||||
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR)
|
||||||
# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
# define LOCAL_GIF_VERSION ((GIFLIB_MAJOR << 8) | GIFLIB_MINOR)
|
||||||
@@ -349,26 +373,6 @@ static int DGifSavedExtensionToGCB(GifFileType* GifFile, int ImageIndex,
|
|||||||
#define DGifCloseFile(a, b) DGifCloseFile(a)
|
#define DGifCloseFile(a, b) DGifCloseFile(a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void GIFDisplayError(const GifFileType* const gif, int gif_error) {
|
|
||||||
// libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
|
|
||||||
#if LOCAL_GIF_PREREQ(4, 2)
|
|
||||||
#if LOCAL_GIF_PREREQ(5, 0)
|
|
||||||
const char* error_str =
|
|
||||||
GifErrorString((gif == NULL) ? gif_error : gif->Error);
|
|
||||||
#else
|
|
||||||
const char* error_str = GifErrorString();
|
|
||||||
(void)gif;
|
|
||||||
#endif
|
|
||||||
if (error_str == NULL) error_str = "Unknown error";
|
|
||||||
fprintf(stderr, "GIFLib Error %d: %s\n", gif_error, error_str);
|
|
||||||
#else
|
|
||||||
(void)gif;
|
|
||||||
fprintf(stderr, "GIFLib Error %d: ", gif_error);
|
|
||||||
PrintGifError();
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose,
|
static int IsKeyFrameGIF(const GifImageDesc* prev_desc, int prev_dispose,
|
||||||
const DecodedFrame* const prev_frame,
|
const DecodedFrame* const prev_frame,
|
||||||
int canvas_width, int canvas_height) {
|
int canvas_width, int canvas_height) {
|
||||||
@@ -395,13 +399,13 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) {
|
|||||||
const ColorMapObject* const color_map = gif->SColorMap;
|
const ColorMapObject* const color_map = gif->SColorMap;
|
||||||
if (transparent_index != NO_TRANSPARENT_COLOR &&
|
if (transparent_index != NO_TRANSPARENT_COLOR &&
|
||||||
gif->SBackGroundColor == transparent_index) {
|
gif->SBackGroundColor == transparent_index) {
|
||||||
return 0x00ffffff; // Special case: transparent white.
|
return 0x00000000; // Special case: transparent black.
|
||||||
} else if (color_map == NULL || color_map->Colors == NULL
|
} else if (color_map == NULL || color_map->Colors == NULL
|
||||||
|| gif->SBackGroundColor >= color_map->ColorCount) {
|
|| gif->SBackGroundColor >= color_map->ColorCount) {
|
||||||
return 0xffffffff; // Invalid: assume white.
|
return 0xffffffff; // Invalid: assume white.
|
||||||
} else {
|
} else {
|
||||||
const GifColorType color = color_map->Colors[gif->SBackGroundColor];
|
const GifColorType color = color_map->Colors[gif->SBackGroundColor];
|
||||||
return (0xff << 24) |
|
return (0xffu << 24) |
|
||||||
(color.Red << 16) |
|
(color.Red << 16) |
|
||||||
(color.Green << 8) |
|
(color.Green << 8) |
|
||||||
(color.Blue << 0);
|
(color.Blue << 0);
|
||||||
@@ -409,6 +413,11 @@ static uint32_t GetBackgroundColorGIF(GifFileType* gif) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find appropriate app extension and get loop count from the next extension.
|
// Find appropriate app extension and get loop count from the next extension.
|
||||||
|
// We use Chrome's interpretation of the 'loop_count' semantics:
|
||||||
|
// if not present -> loop once
|
||||||
|
// if present and loop_count == 0, return 0 ('infinite').
|
||||||
|
// if present and loop_count != 0, it's the number of *extra* loops
|
||||||
|
// so we need to return loop_count + 1 as total loop number.
|
||||||
static uint32_t GetLoopCountGIF(const GifFileType* const gif) {
|
static uint32_t GetLoopCountGIF(const GifFileType* const gif) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < gif->ImageCount; ++i) {
|
for (i = 0; i < gif->ImageCount; ++i) {
|
||||||
@@ -426,12 +435,13 @@ static uint32_t GetLoopCountGIF(const GifFileType* const gif) {
|
|||||||
if (signature_is_ok &&
|
if (signature_is_ok &&
|
||||||
eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 &&
|
eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount >= 3 &&
|
||||||
eb2->Bytes[0] == 1) {
|
eb2->Bytes[0] == 1) {
|
||||||
return ((uint32_t)(eb2->Bytes[2]) << 8) +
|
const uint32_t extra_loop = ((uint32_t)(eb2->Bytes[2]) << 8) +
|
||||||
((uint32_t)(eb2->Bytes[1]) << 0);
|
((uint32_t)(eb2->Bytes[1]) << 0);
|
||||||
|
return (extra_loop > 0) ? extra_loop + 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0; // Default.
|
return 1; // Default.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get duration of 'n'th frame in milliseconds.
|
// Get duration of 'n'th frame in milliseconds.
|
||||||
@@ -503,15 +513,15 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
int gif_error;
|
int gif_error;
|
||||||
GifFileType* gif;
|
GifFileType* gif;
|
||||||
|
|
||||||
gif = DGifOpenFileName(filename, NULL);
|
gif = DGifOpenFileUnicode((const W_CHAR*)filename, NULL);
|
||||||
if (gif == NULL) {
|
if (gif == NULL) {
|
||||||
fprintf(stderr, "Could not read file: %s.\n", filename);
|
WFPRINTF(stderr, "Could not read file: %s.\n", (const W_CHAR*)filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gif_error = DGifSlurp(gif);
|
gif_error = DGifSlurp(gif);
|
||||||
if (gif_error != GIF_OK) {
|
if (gif_error != GIF_OK) {
|
||||||
fprintf(stderr, "Could not parse image: %s.\n", filename);
|
WFPRINTF(stderr, "Could not parse image: %s.\n", (const W_CHAR*)filename);
|
||||||
GIFDisplayError(gif, gif_error);
|
GIFDisplayError(gif, gif_error);
|
||||||
DGifCloseFile(gif, NULL);
|
DGifCloseFile(gif, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -567,6 +577,9 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
curr_frame = &image->frames[i];
|
curr_frame = &image->frames[i];
|
||||||
curr_rgba = curr_frame->rgba;
|
curr_rgba = curr_frame->rgba;
|
||||||
curr_frame->duration = GetFrameDurationGIF(gif, i);
|
curr_frame->duration = GetFrameDurationGIF(gif, i);
|
||||||
|
// Force frames with a small or no duration to 100ms to be consistent
|
||||||
|
// with web browsers and other transcoding tools (like gif2webp itself).
|
||||||
|
if (curr_frame->duration <= 10) curr_frame->duration = 100;
|
||||||
|
|
||||||
if (i == 0) { // Initialize as transparent.
|
if (i == 0) { // Initialize as transparent.
|
||||||
curr_frame->is_key_frame = 1;
|
curr_frame->is_key_frame = 1;
|
||||||
@@ -658,12 +671,18 @@ static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
image->format = ANIM_GIF;
|
||||||
DGifCloseFile(gif, NULL);
|
DGifCloseFile(gif, NULL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
static int IsGIF(const WebPData* const data) {
|
||||||
|
(void)data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
static int ReadAnimatedGIF(const char filename[], AnimatedImage* const image,
|
||||||
int dump_frames, const char dump_folder[]) {
|
int dump_frames, const char dump_folder[]) {
|
||||||
(void)filename;
|
(void)filename;
|
||||||
@@ -687,8 +706,8 @@ int ReadAnimatedImage(const char filename[], AnimatedImage* const image,
|
|||||||
WebPDataInit(&webp_data);
|
WebPDataInit(&webp_data);
|
||||||
memset(image, 0, sizeof(*image));
|
memset(image, 0, sizeof(*image));
|
||||||
|
|
||||||
if (!ExUtilReadFile(filename, &webp_data.bytes, &webp_data.size)) {
|
if (!ImgIoUtilReadFile(filename, &webp_data.bytes, &webp_data.size)) {
|
||||||
fprintf(stderr, "Error reading file: %s\n", filename);
|
WFPRINTF(stderr, "Error reading file: %s\n", (const W_CHAR*)filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,9 +717,9 @@ int ReadAnimatedImage(const char filename[], AnimatedImage* const image,
|
|||||||
} else if (IsGIF(&webp_data)) {
|
} else if (IsGIF(&webp_data)) {
|
||||||
ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder);
|
ok = ReadAnimatedGIF(filename, image, dump_frames, dump_folder);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
WFPRINTF(stderr,
|
||||||
"Unknown file type: %s. Supported file types are WebP and GIF\n",
|
"Unknown file type: %s. Supported file types are WebP and GIF\n",
|
||||||
filename);
|
(const W_CHAR*)filename);
|
||||||
ok = 0;
|
ok = 0;
|
||||||
}
|
}
|
||||||
if (!ok) ClearAnimatedImage(image);
|
if (!ok) ClearAnimatedImage(image);
|
||||||
@@ -726,7 +745,7 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
|
|||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
for (x = 0; x < stride; x += kNumChannels) {
|
for (x = 0; x < stride; x += kNumChannels) {
|
||||||
int k;
|
int k;
|
||||||
const size_t offset = y * stride + x;
|
const size_t offset = (size_t)y * stride + x;
|
||||||
const int alpha1 = rgba1[offset + kAlphaChannel];
|
const int alpha1 = rgba1[offset + kAlphaChannel];
|
||||||
const int alpha2 = rgba2[offset + kAlphaChannel];
|
const int alpha2 = rgba2[offset + kAlphaChannel];
|
||||||
Accumulate(alpha1, alpha2, &f_max_diff, &sse);
|
Accumulate(alpha1, alpha2, &f_max_diff, &sse);
|
||||||
@@ -752,3 +771,9 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
|
|||||||
*psnr = 4.3429448 * log(255. * 255. / sse);
|
*psnr = 4.3429448 * log(255. * 255. / sse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetAnimatedImageVersions(int* const decoder_version,
|
||||||
|
int* const demux_version) {
|
||||||
|
*decoder_version = WebPGetDecoderVersion();
|
||||||
|
*demux_version = WebPGetDemuxVersion();
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,11 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ANIM_GIF,
|
||||||
|
ANIM_WEBP
|
||||||
|
} AnimatedFileFormat;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t* rgba; // Decoded and reconstructed full frame.
|
uint8_t* rgba; // Decoded and reconstructed full frame.
|
||||||
int duration; // Frame duration in milliseconds.
|
int duration; // Frame duration in milliseconds.
|
||||||
@@ -29,6 +34,7 @@ typedef struct {
|
|||||||
} DecodedFrame;
|
} DecodedFrame;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
AnimatedFileFormat format;
|
||||||
uint32_t canvas_width;
|
uint32_t canvas_width;
|
||||||
uint32_t canvas_height;
|
uint32_t canvas_height;
|
||||||
uint32_t bgcolor;
|
uint32_t bgcolor;
|
||||||
@@ -56,6 +62,10 @@ void GetDiffAndPSNR(const uint8_t rgba1[], const uint8_t rgba2[],
|
|||||||
uint32_t width, uint32_t height, int premultiply,
|
uint32_t width, uint32_t height, int premultiply,
|
||||||
int* const max_diff, double* const psnr);
|
int* const max_diff, double* const psnr);
|
||||||
|
|
||||||
|
// Return library versions used by anim_util.
|
||||||
|
void GetAnimatedImageVersions(int* const decoder_version,
|
||||||
|
int* const demux_version);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
510
examples/cwebp.c
510
examples/cwebp.c
@@ -12,6 +12,7 @@
|
|||||||
//
|
//
|
||||||
// Author: Skal (pascal.massimino@gmail.com)
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -20,17 +21,13 @@
|
|||||||
#include "webp/config.h"
|
#include "webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "../examples/example_util.h"
|
||||||
|
#include "../imageio/image_dec.h"
|
||||||
#include "./example_util.h"
|
#include "../imageio/imageio_util.h"
|
||||||
#include "./metadata.h"
|
#include "../imageio/webpdec.h"
|
||||||
#include "./stopwatch.h"
|
#include "./stopwatch.h"
|
||||||
|
#include "./unicode.h"
|
||||||
#include "./jpegdec.h"
|
#include "webp/encode.h"
|
||||||
#include "./pngdec.h"
|
|
||||||
#include "./tiffdec.h"
|
|
||||||
#include "./webpdec.h"
|
|
||||||
#include "./wicdec.h"
|
|
||||||
|
|
||||||
#ifndef WEBP_DLL
|
#ifndef WEBP_DLL
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -50,13 +47,12 @@ static int verbose = 0;
|
|||||||
|
|
||||||
static int ReadYUV(const uint8_t* const data, size_t data_size,
|
static int ReadYUV(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic) {
|
WebPPicture* const pic) {
|
||||||
int y;
|
|
||||||
const int use_argb = pic->use_argb;
|
const int use_argb = pic->use_argb;
|
||||||
const int uv_width = (pic->width + 1) / 2;
|
const int uv_width = (pic->width + 1) / 2;
|
||||||
const int uv_height = (pic->height + 1) / 2;
|
const int uv_height = (pic->height + 1) / 2;
|
||||||
|
const int y_plane_size = pic->width * pic->height;
|
||||||
const int uv_plane_size = uv_width * uv_height;
|
const int uv_plane_size = uv_width * uv_height;
|
||||||
const size_t expected_data_size =
|
const size_t expected_data_size = y_plane_size + 2 * uv_plane_size;
|
||||||
pic->width * pic->height + 2 * uv_plane_size;
|
|
||||||
|
|
||||||
if (data_size != expected_data_size) {
|
if (data_size != expected_data_size) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -67,18 +63,12 @@ static int ReadYUV(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
pic->use_argb = 0;
|
pic->use_argb = 0;
|
||||||
if (!WebPPictureAlloc(pic)) return 0;
|
if (!WebPPictureAlloc(pic)) return 0;
|
||||||
|
ImgIoUtilCopyPlane(data, pic->width, pic->y, pic->y_stride,
|
||||||
for (y = 0; y < pic->height; ++y) {
|
pic->width, pic->height);
|
||||||
memcpy(pic->y + y * pic->y_stride, data + y * pic->width,
|
ImgIoUtilCopyPlane(data + y_plane_size, uv_width,
|
||||||
pic->width * sizeof(*pic->y));
|
pic->u, pic->uv_stride, uv_width, uv_height);
|
||||||
}
|
ImgIoUtilCopyPlane(data + y_plane_size + uv_plane_size, uv_width,
|
||||||
for (y = 0; y < uv_height; ++y) {
|
pic->v, pic->uv_stride, uv_width, uv_height);
|
||||||
const uint8_t* const uv_data = data + pic->height * pic->y_stride;
|
|
||||||
memcpy(pic->u + y * pic->uv_stride, uv_data + y * uv_width,
|
|
||||||
uv_width * sizeof(*uv_data));
|
|
||||||
memcpy(pic->v + y * pic->uv_stride, uv_data + y * uv_width + uv_plane_size,
|
|
||||||
uv_width * sizeof(*uv_data));
|
|
||||||
}
|
|
||||||
return use_argb ? WebPPictureYUVAToARGB(pic) : 1;
|
return use_argb ? WebPPictureYUVAToARGB(pic) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,85 +80,48 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
|
|||||||
const uint8_t* data = NULL;
|
const uint8_t* data = NULL;
|
||||||
size_t data_size = 0;
|
size_t data_size = 0;
|
||||||
if (pic->width != 0 && pic->height != 0) {
|
if (pic->width != 0 && pic->height != 0) {
|
||||||
ok = ExUtilReadFile(filename, &data, &data_size);
|
ok = ImgIoUtilReadFile(filename, &data, &data_size);
|
||||||
ok = ok && ReadYUV(data, data_size, pic);
|
ok = ok && ReadYUV(data, data_size, pic);
|
||||||
} else {
|
} else {
|
||||||
// If no size specified, try to decode it using WIC.
|
// If no size specified, try to decode it using WIC.
|
||||||
ok = ReadPictureWithWIC(filename, pic, keep_alpha, metadata);
|
ok = ReadPictureWithWIC(filename, pic, keep_alpha, metadata);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
ok = ExUtilReadFile(filename, &data, &data_size);
|
ok = ImgIoUtilReadFile(filename, &data, &data_size);
|
||||||
ok = ok && ReadWebP(data, data_size, pic, keep_alpha, metadata);
|
ok = ok && ReadWebP(data, data_size, pic, keep_alpha, metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr, "Error! Could not process file %s\n", filename);
|
WFPRINTF(stderr, "Error! Could not process file %s\n",
|
||||||
|
(const W_CHAR*)filename);
|
||||||
}
|
}
|
||||||
free((void*)data);
|
WebPFree((void*)data);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !HAVE_WINCODEC_H
|
#else // !HAVE_WINCODEC_H
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PNG_ = 0,
|
|
||||||
JPEG_,
|
|
||||||
TIFF_, // 'TIFF' clashes with libtiff
|
|
||||||
WEBP_,
|
|
||||||
UNSUPPORTED
|
|
||||||
} InputFileFormat;
|
|
||||||
|
|
||||||
static uint32_t GetBE32(const uint8_t buf[]) {
|
|
||||||
return ((uint32_t)buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
static InputFileFormat GuessImageType(const uint8_t buf[12]) {
|
|
||||||
InputFileFormat format = UNSUPPORTED;
|
|
||||||
const uint32_t magic1 = GetBE32(buf + 0);
|
|
||||||
const uint32_t magic2 = GetBE32(buf + 8);
|
|
||||||
if (magic1 == 0x89504E47U) {
|
|
||||||
format = PNG_;
|
|
||||||
} else if (magic1 >= 0xFFD8FF00U && magic1 <= 0xFFD8FFFFU) {
|
|
||||||
format = JPEG_;
|
|
||||||
} else if (magic1 == 0x49492A00 || magic1 == 0x4D4D002A) {
|
|
||||||
format = TIFF_;
|
|
||||||
} else if (magic1 == 0x52494646 && magic2 == 0x57454250) {
|
|
||||||
format = WEBP_;
|
|
||||||
}
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ReadPicture(const char* const filename, WebPPicture* const pic,
|
static int ReadPicture(const char* const filename, WebPPicture* const pic,
|
||||||
int keep_alpha, Metadata* const metadata) {
|
int keep_alpha, Metadata* const metadata) {
|
||||||
const uint8_t* data = NULL;
|
const uint8_t* data = NULL;
|
||||||
size_t data_size = 0;
|
size_t data_size = 0;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
|
|
||||||
ok = ExUtilReadFile(filename, &data, &data_size);
|
ok = ImgIoUtilReadFile(filename, &data, &data_size);
|
||||||
if (!ok) goto End;
|
if (!ok) goto End;
|
||||||
|
|
||||||
if (pic->width == 0 || pic->height == 0) {
|
if (pic->width == 0 || pic->height == 0) {
|
||||||
ok = 0;
|
WebPImageReader reader = WebPGuessImageReader(data, data_size);
|
||||||
if (data_size >= 12) {
|
ok = reader(data, data_size, pic, keep_alpha, metadata);
|
||||||
const InputFileFormat format = GuessImageType(data);
|
|
||||||
if (format == PNG_) {
|
|
||||||
ok = ReadPNG(data, data_size, pic, keep_alpha, metadata);
|
|
||||||
} else if (format == JPEG_) {
|
|
||||||
ok = ReadJPEG(data, data_size, pic, metadata);
|
|
||||||
} else if (format == TIFF_) {
|
|
||||||
ok = ReadTIFF(data, data_size, pic, keep_alpha, metadata);
|
|
||||||
} else if (format == WEBP_) {
|
|
||||||
ok = ReadWebP(data, data_size, pic, keep_alpha, metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// If image size is specified, infer it as YUV format.
|
// If image size is specified, infer it as YUV format.
|
||||||
ok = ReadYUV(data, data_size, pic);
|
ok = ReadYUV(data, data_size, pic);
|
||||||
}
|
}
|
||||||
End:
|
End:
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr, "Error! Could not process file %s\n", filename);
|
WFPRINTF(stderr, "Error! Could not process file %s\n",
|
||||||
|
(const W_CHAR*)filename);
|
||||||
}
|
}
|
||||||
free((void*)data);
|
WebPFree((void*)data);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +130,8 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
|
|||||||
static void AllocExtraInfo(WebPPicture* const pic) {
|
static void AllocExtraInfo(WebPPicture* const pic) {
|
||||||
const int mb_w = (pic->width + 15) / 16;
|
const int mb_w = (pic->width + 15) / 16;
|
||||||
const int mb_h = (pic->height + 15) / 16;
|
const int mb_h = (pic->height + 15) / 16;
|
||||||
pic->extra_info = (uint8_t*)malloc(mb_w * mb_h * sizeof(*pic->extra_info));
|
pic->extra_info =
|
||||||
|
(uint8_t*)WebPMalloc(mb_w * mb_h * sizeof(*pic->extra_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintByteCount(const int bytes[4], int total_size,
|
static void PrintByteCount(const int bytes[4], int total_size,
|
||||||
@@ -192,10 +146,11 @@ static void PrintByteCount(const int bytes[4], int total_size,
|
|||||||
fprintf(stderr, "| %7d (%.1f%%)\n", total, 100.f * total / total_size);
|
fprintf(stderr, "| %7d (%.1f%%)\n", total, 100.f * total / total_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintPercents(const int counts[4], int total) {
|
static void PrintPercents(const int counts[4]) {
|
||||||
int s;
|
int s;
|
||||||
|
const int total = counts[0] + counts[1] + counts[2] + counts[3];
|
||||||
for (s = 0; s < 4; ++s) {
|
for (s = 0; s < 4; ++s) {
|
||||||
fprintf(stderr, "| %2d%%", 100 * counts[s] / total);
|
fprintf(stderr, "| %3d%%", (int)(100. * counts[s] / total + .5));
|
||||||
}
|
}
|
||||||
fprintf(stderr, "| %7d\n", total);
|
fprintf(stderr, "| %7d\n", total);
|
||||||
}
|
}
|
||||||
@@ -236,9 +191,10 @@ static void PrintExtraInfoLossless(const WebPPicture* const pic,
|
|||||||
if (short_output) {
|
if (short_output) {
|
||||||
fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]);
|
fprintf(stderr, "%7d %2.2f\n", stats->coded_size, stats->PSNR[3]);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "File: %s\n", file_name);
|
WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name);
|
||||||
fprintf(stderr, "Dimension: %d x %d\n", pic->width, pic->height);
|
fprintf(stderr, "Dimension: %d x %d\n", pic->width, pic->height);
|
||||||
fprintf(stderr, "Output: %d bytes\n", stats->coded_size);
|
fprintf(stderr, "Output: %d bytes (%.2f bpp)\n", stats->coded_size,
|
||||||
|
8.f * stats->coded_size / pic->width / pic->height);
|
||||||
PrintFullLosslessInfo(stats, "ARGB");
|
PrintFullLosslessInfo(stats, "ARGB");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,20 +210,23 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
|||||||
const int num_i16 = stats->block_count[1];
|
const int num_i16 = stats->block_count[1];
|
||||||
const int num_skip = stats->block_count[2];
|
const int num_skip = stats->block_count[2];
|
||||||
const int total = num_i4 + num_i16;
|
const int total = num_i4 + num_i16;
|
||||||
fprintf(stderr, "File: %s\n", file_name);
|
WFPRINTF(stderr, "File: %s\n", (const W_CHAR*)file_name);
|
||||||
fprintf(stderr, "Dimension: %d x %d%s\n",
|
fprintf(stderr, "Dimension: %d x %d%s\n",
|
||||||
pic->width, pic->height,
|
pic->width, pic->height,
|
||||||
stats->alpha_data_size ? " (with alpha)" : "");
|
stats->alpha_data_size ? " (with alpha)" : "");
|
||||||
fprintf(stderr, "Output: "
|
fprintf(stderr, "Output: "
|
||||||
"%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n",
|
"%d bytes Y-U-V-All-PSNR %2.2f %2.2f %2.2f %2.2f dB\n"
|
||||||
|
" (%.2f bpp)\n",
|
||||||
stats->coded_size,
|
stats->coded_size,
|
||||||
stats->PSNR[0], stats->PSNR[1], stats->PSNR[2], stats->PSNR[3]);
|
stats->PSNR[0], stats->PSNR[1], stats->PSNR[2], stats->PSNR[3],
|
||||||
|
8.f * stats->coded_size / pic->width / pic->height);
|
||||||
if (total > 0) {
|
if (total > 0) {
|
||||||
int totals[4] = { 0, 0, 0, 0 };
|
int totals[4] = { 0, 0, 0, 0 };
|
||||||
fprintf(stderr, "block count: intra4: %d\n"
|
fprintf(stderr, "block count: intra4: %6d (%.2f%%)\n"
|
||||||
" intra16: %d (-> %.2f%%)\n",
|
" intra16: %6d (%.2f%%)\n"
|
||||||
num_i4, num_i16, 100.f * num_i16 / total);
|
" skipped: %6d (%.2f%%)\n",
|
||||||
fprintf(stderr, " skipped block: %d (%.2f%%)\n",
|
num_i4, 100.f * num_i4 / total,
|
||||||
|
num_i16, 100.f * num_i16 / total,
|
||||||
num_skip, 100.f * num_skip / total);
|
num_skip, 100.f * num_skip / total);
|
||||||
fprintf(stderr, "bytes used: header: %6d (%.1f%%)\n"
|
fprintf(stderr, "bytes used: header: %6d (%.1f%%)\n"
|
||||||
" mode-partition: %6d (%.1f%%)\n",
|
" mode-partition: %6d (%.1f%%)\n",
|
||||||
@@ -291,7 +250,7 @@ static void PrintExtraInfoLossy(const WebPPicture* const pic, int short_output,
|
|||||||
PrintByteCount(stats->residual_bytes[2], stats->coded_size, totals);
|
PrintByteCount(stats->residual_bytes[2], stats->coded_size, totals);
|
||||||
}
|
}
|
||||||
fprintf(stderr, " macroblocks: ");
|
fprintf(stderr, " macroblocks: ");
|
||||||
PrintPercents(stats->segment_size, total);
|
PrintPercents(stats->segment_size);
|
||||||
fprintf(stderr, " quantizer: ");
|
fprintf(stderr, " quantizer: ");
|
||||||
PrintValues(stats->segment_quant);
|
PrintValues(stats->segment_quant);
|
||||||
fprintf(stderr, " filter level: ");
|
fprintf(stderr, " filter level: ");
|
||||||
@@ -349,27 +308,31 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) {
|
|||||||
const int uv_width = (picture->width + 1) / 2;
|
const int uv_width = (picture->width + 1) / 2;
|
||||||
const int uv_height = (picture->height + 1) / 2;
|
const int uv_height = (picture->height + 1) / 2;
|
||||||
const int stride = (picture->width + 1) & ~1;
|
const int stride = (picture->width + 1) & ~1;
|
||||||
|
const uint8_t* src_y = picture->y;
|
||||||
|
const uint8_t* src_u = picture->u;
|
||||||
|
const uint8_t* src_v = picture->v;
|
||||||
|
const uint8_t* src_a = picture->a;
|
||||||
const int alpha_height =
|
const int alpha_height =
|
||||||
WebPPictureHasTransparency(picture) ? picture->height : 0;
|
WebPPictureHasTransparency(picture) ? picture->height : 0;
|
||||||
const int height = picture->height + uv_height + alpha_height;
|
const int height = picture->height + uv_height + alpha_height;
|
||||||
FILE* const f = fopen(PGM_name, "wb");
|
FILE* const f = WFOPEN(PGM_name, "wb");
|
||||||
if (f == NULL) return 0;
|
if (f == NULL) return 0;
|
||||||
fprintf(f, "P5\n%d %d\n255\n", stride, height);
|
fprintf(f, "P5\n%d %d\n255\n", stride, height);
|
||||||
for (y = 0; y < picture->height; ++y) {
|
for (y = 0; y < picture->height; ++y) {
|
||||||
if (fwrite(picture->y + y * picture->y_stride, picture->width, 1, f) != 1)
|
if (fwrite(src_y, picture->width, 1, f) != 1) return 0;
|
||||||
return 0;
|
|
||||||
if (picture->width & 1) fputc(0, f); // pad
|
if (picture->width & 1) fputc(0, f); // pad
|
||||||
|
src_y += picture->y_stride;
|
||||||
}
|
}
|
||||||
for (y = 0; y < uv_height; ++y) {
|
for (y = 0; y < uv_height; ++y) {
|
||||||
if (fwrite(picture->u + y * picture->uv_stride, uv_width, 1, f) != 1)
|
if (fwrite(src_u, uv_width, 1, f) != 1) return 0;
|
||||||
return 0;
|
if (fwrite(src_v, uv_width, 1, f) != 1) return 0;
|
||||||
if (fwrite(picture->v + y * picture->uv_stride, uv_width, 1, f) != 1)
|
src_u += picture->uv_stride;
|
||||||
return 0;
|
src_v += picture->uv_stride;
|
||||||
}
|
}
|
||||||
for (y = 0; y < alpha_height; ++y) {
|
for (y = 0; y < alpha_height; ++y) {
|
||||||
if (fwrite(picture->a + y * picture->a_stride, picture->width, 1, f) != 1)
|
if (fwrite(src_a, picture->width, 1, f) != 1) return 0;
|
||||||
return 0;
|
|
||||||
if (picture->width & 1) fputc(0, f); // pad
|
if (picture->width & 1) fputc(0, f); // pad
|
||||||
|
src_a += picture->a_stride;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -511,8 +474,9 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
} else {
|
} else {
|
||||||
const int is_lossless = !memcmp(webp, "VP8L", kTagSize);
|
const int is_lossless = !memcmp(webp, "VP8L", kTagSize);
|
||||||
if (is_lossless) {
|
if (is_lossless) {
|
||||||
// Presence of alpha is stored in the 29th bit of VP8L data.
|
// Presence of alpha is stored in the 37th bit (29th after the
|
||||||
if (webp[kChunkHeaderSize + 3] & (1 << 5)) flags |= kAlphaFlag;
|
// signature) of VP8L data.
|
||||||
|
if (webp[kChunkHeaderSize + 4] & (1 << 4)) flags |= kAlphaFlag;
|
||||||
}
|
}
|
||||||
ok = ok && (fwrite(kVP8XHeader, kChunkHeaderSize, 1, out) == 1);
|
ok = ok && (fwrite(kVP8XHeader, kChunkHeaderSize, 1, out) == 1);
|
||||||
ok = ok && WriteLE32(out, flags);
|
ok = ok && WriteLE32(out, flags);
|
||||||
@@ -534,10 +498,10 @@ static int WriteWebPWithMetadata(FILE* const out,
|
|||||||
*metadata_written |= METADATA_XMP;
|
*metadata_written |= METADATA_XMP;
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
} else {
|
|
||||||
// No metadata, just write the original image file.
|
|
||||||
return (fwrite(webp, webp_size, 1, out) == 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No metadata, just write the original image file.
|
||||||
|
return (fwrite(webp, webp_size, 1, out) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -563,15 +527,17 @@ static void HelpLong(void) {
|
|||||||
printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n");
|
printf(" cwebp [-preset <...>] [options] in_file [-o out_file]\n\n");
|
||||||
printf("If input size (-s) for an image is not specified, it is\n"
|
printf("If input size (-s) for an image is not specified, it is\n"
|
||||||
"assumed to be a PNG, JPEG, TIFF or WebP file.\n");
|
"assumed to be a PNG, JPEG, TIFF or WebP file.\n");
|
||||||
|
printf("Note: Animated PNG and WebP files are not supported.\n");
|
||||||
#ifdef HAVE_WINCODEC_H
|
#ifdef HAVE_WINCODEC_H
|
||||||
printf("Windows builds can take as input any of the files handled by WIC.\n");
|
printf("Windows builds can take as input any of the files handled by WIC.\n");
|
||||||
#endif
|
#endif
|
||||||
printf("\nOptions:\n");
|
printf("\nOptions:\n");
|
||||||
printf(" -h / -help ............ short help\n");
|
printf(" -h / -help ............. short help\n");
|
||||||
printf(" -H / -longhelp ........ long help\n");
|
printf(" -H / -longhelp ......... long help\n");
|
||||||
printf(" -q <float> ............. quality factor (0:small..100:big)\n");
|
printf(" -q <float> ............. quality factor (0:small..100:big), "
|
||||||
printf(" -alpha_q <int> ......... transparency-compression quality "
|
"default=75\n");
|
||||||
"(0..100)\n");
|
printf(" -alpha_q <int> ......... transparency-compression quality (0..100),"
|
||||||
|
"\n default=100\n");
|
||||||
printf(" -preset <string> ....... preset setting, one of:\n");
|
printf(" -preset <string> ....... preset setting, one of:\n");
|
||||||
printf(" default, photo, picture,\n");
|
printf(" default, photo, picture,\n");
|
||||||
printf(" drawing, icon, text\n");
|
printf(" drawing, icon, text\n");
|
||||||
@@ -579,23 +545,31 @@ static void HelpLong(void) {
|
|||||||
printf(" -z <int> ............... activates lossless preset with given\n"
|
printf(" -z <int> ............... activates lossless preset with given\n"
|
||||||
" level in [0:fast, ..., 9:slowest]\n");
|
" level in [0:fast, ..., 9:slowest]\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" -m <int> ............... compression method (0=fast, 6=slowest)\n");
|
printf(" -m <int> ............... compression method (0=fast, 6=slowest), "
|
||||||
printf(" -segments <int> ........ number of segments to use (1..4)\n");
|
"default=4\n");
|
||||||
|
printf(" -segments <int> ........ number of segments to use (1..4), "
|
||||||
|
"default=4\n");
|
||||||
printf(" -size <int> ............ target size (in bytes)\n");
|
printf(" -size <int> ............ target size (in bytes)\n");
|
||||||
printf(" -psnr <float> .......... target PSNR (in dB. typically: 42)\n");
|
printf(" -psnr <float> .......... target PSNR (in dB. typically: 42)\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" -s <int> <int> ......... input size (width x height) for YUV\n");
|
printf(" -s <int> <int> ......... input size (width x height) for YUV\n");
|
||||||
printf(" -sns <int> ............. spatial noise shaping (0:off, 100:max)\n");
|
printf(" -sns <int> ............. spatial noise shaping (0:off, 100:max), "
|
||||||
printf(" -f <int> ............... filter strength (0=off..100)\n");
|
"default=50\n");
|
||||||
|
printf(" -f <int> ............... filter strength (0=off..100), "
|
||||||
|
"default=60\n");
|
||||||
printf(" -sharpness <int> ....... "
|
printf(" -sharpness <int> ....... "
|
||||||
"filter sharpness (0:most .. 7:least sharp)\n");
|
"filter sharpness (0:most .. 7:least sharp), default=0\n");
|
||||||
printf(" -strong ................ use strong filter instead "
|
printf(" -strong ................ use strong filter instead "
|
||||||
"of simple (default)\n");
|
"of simple (default)\n");
|
||||||
printf(" -nostrong .............. use simple filter instead of strong\n");
|
printf(" -nostrong .............. use simple filter instead of strong\n");
|
||||||
|
printf(" -sharp_yuv ............. use sharper (and slower) RGB->YUV "
|
||||||
|
"conversion\n");
|
||||||
printf(" -partition_limit <int> . limit quality to fit the 512k limit on\n");
|
printf(" -partition_limit <int> . limit quality to fit the 512k limit on\n");
|
||||||
printf(" "
|
printf(" "
|
||||||
"the first partition (0=no degradation ... 100=full)\n");
|
"the first partition (0=no degradation ... 100=full)\n");
|
||||||
printf(" -pass <int> ............ analysis pass number (1..10)\n");
|
printf(" -pass <int> ............ analysis pass number (1..10)\n");
|
||||||
|
printf(" -qrange <min> <max> .... specifies the permissible quality range\n"
|
||||||
|
" (default: 0 100)\n");
|
||||||
printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n");
|
printf(" -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(" -mt .................... use multi-threading if available\n");
|
||||||
@@ -605,22 +579,21 @@ static void HelpLong(void) {
|
|||||||
printf(" -print_ssim ............ prints averaged SSIM distortion\n");
|
printf(" -print_ssim ............ prints averaged SSIM distortion\n");
|
||||||
printf(" -print_lsim ............ prints local-similarity distortion\n");
|
printf(" -print_lsim ............ prints local-similarity distortion\n");
|
||||||
printf(" -d <file.pgm> .......... dump the compressed output (PGM file)\n");
|
printf(" -d <file.pgm> .......... dump the compressed output (PGM file)\n");
|
||||||
printf(" -alpha_method <int> .... transparency-compression method (0..1)\n");
|
printf(" -alpha_method <int> .... transparency-compression method (0..1), "
|
||||||
|
"default=1\n");
|
||||||
printf(" -alpha_filter <string> . predictive filtering for alpha plane,\n");
|
printf(" -alpha_filter <string> . predictive filtering for alpha plane,\n");
|
||||||
printf(" one of: none, fast (default) or best\n");
|
printf(" one of: none, fast (default) or best\n");
|
||||||
printf(" -exact ................. preserve RGB values in transparent area"
|
printf(" -exact ................. preserve RGB values in transparent area, "
|
||||||
"\n");
|
"default=off\n");
|
||||||
printf(" -blend_alpha <hex> ..... blend colors against background color\n"
|
printf(" -blend_alpha <hex> ..... blend colors against background color\n"
|
||||||
" expressed as RGB values written in\n"
|
" expressed as RGB values written in\n"
|
||||||
" hexadecimal, e.g. 0xc0e0d0 for red=0xc0\n"
|
" hexadecimal, e.g. 0xc0e0d0 for red=0xc0\n"
|
||||||
" green=0xe0 and blue=0xd0\n");
|
" green=0xe0 and blue=0xd0\n");
|
||||||
printf(" -noalpha ............... discard any transparency information\n");
|
printf(" -noalpha ............... discard any transparency information\n");
|
||||||
printf(" -lossless .............. encode image losslessly\n");
|
printf(" -lossless .............. encode image losslessly, default=off\n");
|
||||||
printf(" -near_lossless <int> ... use near-lossless image\n"
|
printf(" -near_lossless <int> ... use near-lossless image\n"
|
||||||
" preprocessing (0..100=off)\n");
|
" preprocessing (0..100=off), "
|
||||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
"default=100\n");
|
||||||
printf(" -delta_palettization ... use delta palettization\n");
|
|
||||||
#endif // WEBP_EXPERIMENTAL_FEATURES
|
|
||||||
printf(" -hint <string> ......... specify image characteristics hint,\n");
|
printf(" -hint <string> ......... specify image characteristics hint,\n");
|
||||||
printf(" one of: photo, picture or graph\n");
|
printf(" one of: photo, picture or graph\n");
|
||||||
|
|
||||||
@@ -673,10 +646,10 @@ static const char* const kErrorMessages[VP8_ENC_ERROR_LAST] = {
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
int return_value = -1;
|
int return_value = -1;
|
||||||
const char *in_file = NULL, *out_file = NULL, *dump_file = NULL;
|
const char* in_file = NULL, *out_file = NULL, *dump_file = NULL;
|
||||||
FILE *out = NULL;
|
FILE* out = NULL;
|
||||||
int c;
|
int c;
|
||||||
int short_output = 0;
|
int short_output = 0;
|
||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
@@ -696,35 +669,38 @@ int main(int argc, const char *argv[]) {
|
|||||||
WebPConfig config;
|
WebPConfig config;
|
||||||
WebPAuxStats stats;
|
WebPAuxStats stats;
|
||||||
WebPMemoryWriter memory_writer;
|
WebPMemoryWriter memory_writer;
|
||||||
|
int use_memory_writer;
|
||||||
Metadata metadata;
|
Metadata metadata;
|
||||||
Stopwatch stop_watch;
|
Stopwatch stop_watch;
|
||||||
|
|
||||||
|
INIT_WARGV(argc, argv);
|
||||||
|
|
||||||
MetadataInit(&metadata);
|
MetadataInit(&metadata);
|
||||||
WebPMemoryWriterInit(&memory_writer);
|
WebPMemoryWriterInit(&memory_writer);
|
||||||
if (!WebPPictureInit(&picture) ||
|
if (!WebPPictureInit(&picture) ||
|
||||||
!WebPPictureInit(&original_picture) ||
|
!WebPPictureInit(&original_picture) ||
|
||||||
!WebPConfigInit(&config)) {
|
!WebPConfigInit(&config)) {
|
||||||
fprintf(stderr, "Error! Version mismatch!\n");
|
fprintf(stderr, "Error! Version mismatch!\n");
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
HelpShort();
|
HelpShort();
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
HelpShort();
|
HelpShort();
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
|
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
|
||||||
HelpLong();
|
HelpLong();
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-o") && c + 1 < argc) {
|
||||||
out_file = argv[++c];
|
out_file = (const char*)GET_WARGV(argv, ++c);
|
||||||
} else if (!strcmp(argv[c], "-d") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-d") && c + 1 < argc) {
|
||||||
dump_file = argv[++c];
|
dump_file = (const char*)GET_WARGV(argv, ++c);
|
||||||
config.show_compressed = 1;
|
config.show_compressed = 1;
|
||||||
} else if (!strcmp(argv[c], "-print_psnr")) {
|
} else if (!strcmp(argv[c], "-print_psnr")) {
|
||||||
config.show_compressed = 1;
|
config.show_compressed = 1;
|
||||||
@@ -737,7 +713,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
print_distortion = 2;
|
print_distortion = 2;
|
||||||
} else if (!strcmp(argv[c], "-short")) {
|
} else if (!strcmp(argv[c], "-short")) {
|
||||||
++short_output;
|
++short_output;
|
||||||
} else if (!strcmp(argv[c], "-s") && c < argc - 2) {
|
} else if (!strcmp(argv[c], "-s") && c + 2 < argc) {
|
||||||
picture.width = ExUtilGetInt(argv[++c], 0, &parse_error);
|
picture.width = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 ||
|
if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 ||
|
||||||
@@ -747,30 +723,30 @@ int main(int argc, const char *argv[]) {
|
|||||||
picture.width, picture.height);
|
picture.width, picture.height);
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[c], "-m") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-m") && c + 1 < argc) {
|
||||||
config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
use_lossless_preset = 0; // disable -z option
|
use_lossless_preset = 0; // disable -z option
|
||||||
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-q") && c + 1 < argc) {
|
||||||
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
|
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
use_lossless_preset = 0; // disable -z option
|
use_lossless_preset = 0; // disable -z option
|
||||||
} else if (!strcmp(argv[c], "-z") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-z") && c + 1 < argc) {
|
||||||
lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error);
|
lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
if (use_lossless_preset != 0) use_lossless_preset = 1;
|
if (use_lossless_preset != 0) use_lossless_preset = 1;
|
||||||
} else if (!strcmp(argv[c], "-alpha_q") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-alpha_q") && c + 1 < argc) {
|
||||||
config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-alpha_method") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-alpha_method") && c + 1 < argc) {
|
||||||
config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-alpha_cleanup")) {
|
} else if (!strcmp(argv[c], "-alpha_cleanup")) {
|
||||||
// This flag is obsolete, does opposite of -exact.
|
// This flag is obsolete, does opposite of -exact.
|
||||||
config.exact = 0;
|
config.exact = 0;
|
||||||
} else if (!strcmp(argv[c], "-exact")) {
|
} else if (!strcmp(argv[c], "-exact")) {
|
||||||
config.exact = 1;
|
config.exact = 1;
|
||||||
} else if (!strcmp(argv[c], "-blend_alpha") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-blend_alpha") && c + 1 < argc) {
|
||||||
blend_alpha = 1;
|
blend_alpha = 1;
|
||||||
// background color is given in hex with an optional '0x' prefix
|
// background color is given in hex with an optional '0x' prefix
|
||||||
background_color = ExUtilGetInt(argv[++c], 16, &parse_error);
|
background_color = ExUtilGetInt(argv[++c], 16, &parse_error);
|
||||||
background_color = background_color & 0x00ffffffu;
|
background_color = background_color & 0x00ffffffu;
|
||||||
} else if (!strcmp(argv[c], "-alpha_filter") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-alpha_filter") && c + 1 < argc) {
|
||||||
++c;
|
++c;
|
||||||
if (!strcmp(argv[c], "none")) {
|
if (!strcmp(argv[c], "none")) {
|
||||||
config.alpha_filtering = 0;
|
config.alpha_filtering = 0;
|
||||||
@@ -786,15 +762,10 @@ int main(int argc, const char *argv[]) {
|
|||||||
keep_alpha = 0;
|
keep_alpha = 0;
|
||||||
} else if (!strcmp(argv[c], "-lossless")) {
|
} else if (!strcmp(argv[c], "-lossless")) {
|
||||||
config.lossless = 1;
|
config.lossless = 1;
|
||||||
} else if (!strcmp(argv[c], "-near_lossless") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-near_lossless") && c + 1 < argc) {
|
||||||
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
config.lossless = 1; // use near-lossless only with lossless
|
config.lossless = 1; // use near-lossless only with lossless
|
||||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
} else if (!strcmp(argv[c], "-hint") && c + 1 < argc) {
|
||||||
} else if (!strcmp(argv[c], "-delta_palettization")) {
|
|
||||||
config.delta_palettization = 1;
|
|
||||||
config.lossless = 1; // use delta-palettization only with lossless
|
|
||||||
#endif // WEBP_EXPERIMENTAL_FEATURES
|
|
||||||
} else if (!strcmp(argv[c], "-hint") && c < argc - 1) {
|
|
||||||
++c;
|
++c;
|
||||||
if (!strcmp(argv[c], "photo")) {
|
if (!strcmp(argv[c], "photo")) {
|
||||||
config.image_hint = WEBP_HINT_PHOTO;
|
config.image_hint = WEBP_HINT_PHOTO;
|
||||||
@@ -806,13 +777,13 @@ int main(int argc, const char *argv[]) {
|
|||||||
fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]);
|
fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]);
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[c], "-size") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-size") && c + 1 < argc) {
|
||||||
config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-psnr") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-psnr") && c + 1 < argc) {
|
||||||
config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error);
|
config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-sns") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-sns") && c + 1 < argc) {
|
||||||
config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-f") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-f") && c + 1 < argc) {
|
||||||
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-af")) {
|
} else if (!strcmp(argv[c], "-af")) {
|
||||||
config.autofilter = 1;
|
config.autofilter = 1;
|
||||||
@@ -826,25 +797,32 @@ int main(int argc, const char *argv[]) {
|
|||||||
config.filter_type = 1;
|
config.filter_type = 1;
|
||||||
} else if (!strcmp(argv[c], "-nostrong")) {
|
} else if (!strcmp(argv[c], "-nostrong")) {
|
||||||
config.filter_type = 0;
|
config.filter_type = 0;
|
||||||
} else if (!strcmp(argv[c], "-sharpness") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-sharpness") && c + 1 < argc) {
|
||||||
config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-pass") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-sharp_yuv")) {
|
||||||
|
config.use_sharp_yuv = 1;
|
||||||
|
} else if (!strcmp(argv[c], "-pass") && c + 1 < argc) {
|
||||||
config.pass = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.pass = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-pre") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-qrange") && c + 2 < argc) {
|
||||||
|
config.qmin = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
config.qmax = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
if (config.qmin < 0) config.qmin = 0;
|
||||||
|
if (config.qmax > 100) config.qmax = 100;
|
||||||
|
} else if (!strcmp(argv[c], "-pre") && c + 1 < argc) {
|
||||||
config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-segments") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-segments") && c + 1 < argc) {
|
||||||
config.segments = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.segments = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-partition_limit") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-partition_limit") && c + 1 < argc) {
|
||||||
config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-map") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-map") && c + 1 < argc) {
|
||||||
picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error);
|
picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
|
} else if (!strcmp(argv[c], "-crop") && c + 4 < argc) {
|
||||||
crop = 1;
|
crop = 1;
|
||||||
crop_x = ExUtilGetInt(argv[++c], 0, &parse_error);
|
crop_x = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
crop_y = ExUtilGetInt(argv[++c], 0, &parse_error);
|
crop_y = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
crop_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
crop_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
crop_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
crop_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-resize") && c < argc - 2) {
|
} else if (!strcmp(argv[c], "-resize") && c + 2 < argc) {
|
||||||
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
#ifndef WEBP_DLL
|
#ifndef WEBP_DLL
|
||||||
@@ -855,12 +833,12 @@ int main(int argc, const char *argv[]) {
|
|||||||
const int version = WebPGetEncoderVersion();
|
const int version = WebPGetEncoderVersion();
|
||||||
printf("%d.%d.%d\n",
|
printf("%d.%d.%d\n",
|
||||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-progress")) {
|
} else if (!strcmp(argv[c], "-progress")) {
|
||||||
show_progress = 1;
|
show_progress = 1;
|
||||||
} else if (!strcmp(argv[c], "-quiet")) {
|
} else if (!strcmp(argv[c], "-quiet")) {
|
||||||
quiet = 1;
|
quiet = 1;
|
||||||
} else if (!strcmp(argv[c], "-preset") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-preset") && c + 1 < argc) {
|
||||||
WebPPreset preset;
|
WebPPreset preset;
|
||||||
++c;
|
++c;
|
||||||
if (!strcmp(argv[c], "default")) {
|
if (!strcmp(argv[c], "default")) {
|
||||||
@@ -883,7 +861,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
fprintf(stderr, "Error! Could initialize configuration with preset.\n");
|
fprintf(stderr, "Error! Could initialize configuration with preset.\n");
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[c], "-metadata") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-metadata") && c + 1 < argc) {
|
||||||
static const struct {
|
static const struct {
|
||||||
const char* option;
|
const char* option;
|
||||||
int flag;
|
int flag;
|
||||||
@@ -917,8 +895,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (i == kNumTokens) {
|
if (i == kNumTokens) {
|
||||||
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
|
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
|
||||||
(int)(token - start), start);
|
(int)(token - start), start);
|
||||||
HelpLong();
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
start = token + 1;
|
start = token + 1;
|
||||||
}
|
}
|
||||||
@@ -932,19 +909,19 @@ int main(int argc, const char *argv[]) {
|
|||||||
} else if (!strcmp(argv[c], "-v")) {
|
} else if (!strcmp(argv[c], "-v")) {
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
} else if (!strcmp(argv[c], "--")) {
|
} else if (!strcmp(argv[c], "--")) {
|
||||||
if (c < argc - 1) in_file = argv[++c];
|
if (c + 1 < argc) in_file = (const char*)GET_WARGV(argv, ++c);
|
||||||
break;
|
break;
|
||||||
} else if (argv[c][0] == '-') {
|
} else if (argv[c][0] == '-') {
|
||||||
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
|
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
|
||||||
HelpLong();
|
HelpLong();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
} else {
|
} else {
|
||||||
in_file = argv[c];
|
in_file = (const char*)GET_WARGV(argv, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parse_error) {
|
if (parse_error) {
|
||||||
HelpLong();
|
HelpLong();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (in_file == NULL) {
|
if (in_file == NULL) {
|
||||||
@@ -972,6 +949,11 @@ int main(int argc, const char *argv[]) {
|
|||||||
" encoding. Ignoring this option!\n");
|
" encoding. Ignoring this option!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If a target size or PSNR was given, but somehow the -pass option was
|
||||||
|
// omitted, force a reasonable value.
|
||||||
|
if (config.target_size > 0 || config.target_PSNR > 0) {
|
||||||
|
if (config.pass == 1) config.pass = 6;
|
||||||
|
}
|
||||||
|
|
||||||
if (!WebPValidateConfig(&config)) {
|
if (!WebPValidateConfig(&config)) {
|
||||||
fprintf(stderr, "Error! Invalid configuration.\n");
|
fprintf(stderr, "Error! Invalid configuration.\n");
|
||||||
@@ -981,14 +963,16 @@ int main(int argc, const char *argv[]) {
|
|||||||
// Read the input. We need to decide if we prefer ARGB or YUVA
|
// Read the input. We need to decide if we prefer ARGB or YUVA
|
||||||
// samples, depending on the expected compression mode (this saves
|
// samples, depending on the expected compression mode (this saves
|
||||||
// some conversion steps).
|
// some conversion steps).
|
||||||
picture.use_argb = (config.lossless || config.preprocessing > 0 ||
|
picture.use_argb = (config.lossless || config.use_sharp_yuv ||
|
||||||
|
config.preprocessing > 0 ||
|
||||||
crop || (resize_w | resize_h) > 0);
|
crop || (resize_w | resize_h) > 0);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
StopwatchReset(&stop_watch);
|
StopwatchReset(&stop_watch);
|
||||||
}
|
}
|
||||||
if (!ReadPicture(in_file, &picture, keep_alpha,
|
if (!ReadPicture(in_file, &picture, keep_alpha,
|
||||||
(keep_metadata == 0) ? NULL : &metadata)) {
|
(keep_metadata == 0) ? NULL : &metadata)) {
|
||||||
fprintf(stderr, "Error! Cannot read input picture file '%s'\n", in_file);
|
WFPRINTF(stderr, "Error! Cannot read input picture file '%s'\n",
|
||||||
|
(const W_CHAR*)in_file);
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
picture.progress_hook = (show_progress && !quiet) ? ProgressReport : NULL;
|
picture.progress_hook = (show_progress && !quiet) ? ProgressReport : NULL;
|
||||||
@@ -1001,28 +985,41 @@ int main(int argc, const char *argv[]) {
|
|||||||
const double read_time = StopwatchReadAndReset(&stop_watch);
|
const double read_time = StopwatchReadAndReset(&stop_watch);
|
||||||
fprintf(stderr, "Time to read input: %.3fs\n", read_time);
|
fprintf(stderr, "Time to read input: %.3fs\n", read_time);
|
||||||
}
|
}
|
||||||
|
// The bitstream should be kept in memory when metadata must be appended
|
||||||
|
// before writing it to a file/stream, and/or when the near-losslessly encoded
|
||||||
|
// bitstream must be decoded for distortion computation (lossy will modify the
|
||||||
|
// 'picture' but not the lossless pipeline).
|
||||||
|
// Otherwise directly write the bitstream to a file.
|
||||||
|
use_memory_writer = (out_file != NULL && keep_metadata) ||
|
||||||
|
(!quiet && print_distortion >= 0 && config.lossless &&
|
||||||
|
config.near_lossless < 100);
|
||||||
|
|
||||||
// Open the output
|
// Open the output
|
||||||
if (out_file != NULL) {
|
if (out_file != NULL) {
|
||||||
const int use_stdout = !strcmp(out_file, "-");
|
const int use_stdout = !WSTRCMP(out_file, "-");
|
||||||
out = use_stdout ? ExUtilSetBinaryMode(stdout) : fopen(out_file, "wb");
|
out = use_stdout ? ImgIoUtilSetBinaryMode(stdout) : WFOPEN(out_file, "wb");
|
||||||
if (out == NULL) {
|
if (out == NULL) {
|
||||||
fprintf(stderr, "Error! Cannot open output file '%s'\n", out_file);
|
WFPRINTF(stderr, "Error! Cannot open output file '%s'\n",
|
||||||
|
(const W_CHAR*)out_file);
|
||||||
goto Error;
|
goto Error;
|
||||||
} else {
|
} else {
|
||||||
if (!short_output && !quiet) {
|
if (!short_output && !quiet) {
|
||||||
fprintf(stderr, "Saving file '%s'\n", out_file);
|
WFPRINTF(stderr, "Saving file '%s'\n", (const W_CHAR*)out_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (keep_metadata == 0) {
|
if (use_memory_writer) {
|
||||||
picture.writer = MyWriter;
|
|
||||||
picture.custom_ptr = (void*)out;
|
|
||||||
} else {
|
|
||||||
picture.writer = WebPMemoryWrite;
|
picture.writer = WebPMemoryWrite;
|
||||||
picture.custom_ptr = (void*)&memory_writer;
|
picture.custom_ptr = (void*)&memory_writer;
|
||||||
|
} else {
|
||||||
|
picture.writer = MyWriter;
|
||||||
|
picture.custom_ptr = (void*)out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
out = NULL;
|
out = NULL;
|
||||||
|
if (use_memory_writer) {
|
||||||
|
picture.writer = WebPMemoryWrite;
|
||||||
|
picture.custom_ptr = (void*)&memory_writer;
|
||||||
|
}
|
||||||
if (!quiet && !short_output) {
|
if (!quiet && !short_output) {
|
||||||
fprintf(stderr, "No output file specified (no -o flag). Encoding will\n");
|
fprintf(stderr, "No output file specified (no -o flag). Encoding will\n");
|
||||||
fprintf(stderr, "be performed, but its results discarded.\n\n");
|
fprintf(stderr, "be performed, but its results discarded.\n\n");
|
||||||
@@ -1045,10 +1042,53 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((resize_w | resize_h) > 0) {
|
if ((resize_w | resize_h) > 0) {
|
||||||
|
WebPPicture picture_no_alpha;
|
||||||
|
if (config.exact) {
|
||||||
|
// If -exact, we can't premultiply RGB by A otherwise RGB is lost if A=0.
|
||||||
|
// We rescale an opaque copy and assemble scaled A and non-premultiplied
|
||||||
|
// RGB channels. This is slower but it's a very uncommon use case. Color
|
||||||
|
// leak at sharp alpha edges is possible.
|
||||||
|
if (!WebPPictureCopy(&picture, &picture_no_alpha)) {
|
||||||
|
fprintf(stderr, "Error! Cannot copy temporary picture\n");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We enforced picture.use_argb = 1 above. Now, remove the alpha values.
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
uint32_t* argb_no_alpha = picture_no_alpha.argb;
|
||||||
|
for (y = 0; y < picture_no_alpha.height; ++y) {
|
||||||
|
for (x = 0; x < picture_no_alpha.width; ++x) {
|
||||||
|
argb_no_alpha[x] |= 0xff000000; // Opaque copy.
|
||||||
|
}
|
||||||
|
argb_no_alpha += picture_no_alpha.argb_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WebPPictureRescale(&picture_no_alpha, resize_w, resize_h)) {
|
||||||
|
fprintf(stderr, "Error! Cannot resize temporary picture\n");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!WebPPictureRescale(&picture, resize_w, resize_h)) {
|
if (!WebPPictureRescale(&picture, resize_w, resize_h)) {
|
||||||
fprintf(stderr, "Error! Cannot resize picture\n");
|
fprintf(stderr, "Error! Cannot resize picture\n");
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.exact) { // Put back the alpha information.
|
||||||
|
int x, y;
|
||||||
|
uint32_t* argb_no_alpha = picture_no_alpha.argb;
|
||||||
|
uint32_t* argb = picture.argb;
|
||||||
|
for (y = 0; y < picture_no_alpha.height; ++y) {
|
||||||
|
for (x = 0; x < picture_no_alpha.width; ++x) {
|
||||||
|
argb[x] = (argb[x] & 0xff000000) | (argb_no_alpha[x] & 0x00ffffff);
|
||||||
|
}
|
||||||
|
argb_no_alpha += picture_no_alpha.argb_stride;
|
||||||
|
argb += picture.argb_stride;
|
||||||
|
}
|
||||||
|
WebPPictureFree(&picture_no_alpha);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) {
|
if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) {
|
||||||
const double preproc_time = StopwatchReadAndReset(&stop_watch);
|
const double preproc_time = StopwatchReadAndReset(&stop_watch);
|
||||||
@@ -1058,8 +1098,12 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (picture.extra_info_type > 0) {
|
if (picture.extra_info_type > 0) {
|
||||||
AllocExtraInfo(&picture);
|
AllocExtraInfo(&picture);
|
||||||
}
|
}
|
||||||
if (print_distortion >= 0) { // Save original picture for later comparison
|
// Save original picture for later comparison. Only for lossy as lossless does
|
||||||
WebPPictureCopy(&picture, &original_picture);
|
// not modify 'picture' (even near-lossless).
|
||||||
|
if (print_distortion >= 0 && !config.lossless &&
|
||||||
|
!WebPPictureCopy(&picture, &original_picture)) {
|
||||||
|
fprintf(stderr, "Error! Cannot copy temporary picture\n");
|
||||||
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress.
|
// Compress.
|
||||||
@@ -1077,40 +1121,71 @@ int main(int argc, const char *argv[]) {
|
|||||||
fprintf(stderr, "Time to encode picture: %.3fs\n", encode_time);
|
fprintf(stderr, "Time to encode picture: %.3fs\n", encode_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write info
|
// Get the decompressed image for the lossless pipeline.
|
||||||
|
if (!quiet && print_distortion >= 0 && config.lossless) {
|
||||||
|
if (config.near_lossless == 100) {
|
||||||
|
// Pure lossless: image was not modified, make 'original_picture' a view
|
||||||
|
// of 'picture' by copying all members except the freeable pointers.
|
||||||
|
original_picture = picture;
|
||||||
|
original_picture.memory_ = original_picture.memory_argb_ = NULL;
|
||||||
|
} else {
|
||||||
|
// Decode the bitstream stored in 'memory_writer' to get the altered image
|
||||||
|
// to 'picture'; save the 'original_picture' beforehand.
|
||||||
|
assert(use_memory_writer);
|
||||||
|
original_picture = picture;
|
||||||
|
if (!WebPPictureInit(&picture)) { // Do not free 'picture'.
|
||||||
|
fprintf(stderr, "Error! Version mismatch!\n");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
picture.use_argb = 1;
|
||||||
|
if (!ReadWebP(memory_writer.mem, memory_writer.size, &picture,
|
||||||
|
/*keep_alpha=*/WebPPictureHasTransparency(&picture),
|
||||||
|
/*metadata=*/NULL)) {
|
||||||
|
fprintf(stderr, "Error! Cannot decode encoded WebP bitstream\n");
|
||||||
|
fprintf(stderr, "Error code: %d (%s)\n", picture.error_code,
|
||||||
|
kErrorMessages[picture.error_code]);
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
picture.stats = original_picture.stats;
|
||||||
|
}
|
||||||
|
original_picture.stats = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the YUV planes to a PGM file. Only available for lossy.
|
||||||
if (dump_file) {
|
if (dump_file) {
|
||||||
if (picture.use_argb) {
|
if (picture.use_argb) {
|
||||||
fprintf(stderr, "Warning: can't dump file (-d option) in lossless mode.");
|
fprintf(stderr, "Warning: can't dump file (-d option) "
|
||||||
|
"in lossless mode.\n");
|
||||||
} else if (!DumpPicture(&picture, dump_file)) {
|
} else if (!DumpPicture(&picture, dump_file)) {
|
||||||
fprintf(stderr, "Warning, couldn't dump picture %s\n", dump_file);
|
WFPRINTF(stderr, "Warning, couldn't dump picture %s\n",
|
||||||
|
(const W_CHAR*)dump_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keep_metadata != 0) {
|
if (use_memory_writer && out != NULL &&
|
||||||
if (out != NULL) {
|
!WriteWebPWithMetadata(out, &picture, &memory_writer, &metadata,
|
||||||
if (!WriteWebPWithMetadata(out, &picture, &memory_writer,
|
keep_metadata, &metadata_written)) {
|
||||||
&metadata, keep_metadata, &metadata_written)) {
|
fprintf(stderr, "Error writing WebP file!\n");
|
||||||
fprintf(stderr, "Error writing WebP file with metadata!\n");
|
goto Error;
|
||||||
goto Error;
|
}
|
||||||
}
|
|
||||||
} else { // output is disabled, just display the metadata stats.
|
|
||||||
const struct {
|
|
||||||
const MetadataPayload* const payload;
|
|
||||||
int flag;
|
|
||||||
} *iter, info[] = {
|
|
||||||
{ &metadata.exif, METADATA_EXIF },
|
|
||||||
{ &metadata.iccp, METADATA_ICC },
|
|
||||||
{ &metadata.xmp, METADATA_XMP },
|
|
||||||
{ NULL, 0 }
|
|
||||||
};
|
|
||||||
uint32_t unused1 = 0;
|
|
||||||
uint64_t unused2 = 0;
|
|
||||||
|
|
||||||
for (iter = info; iter->payload != NULL; ++iter) {
|
if (out == NULL && keep_metadata) {
|
||||||
if (UpdateFlagsAndSize(iter->payload, !!(keep_metadata & iter->flag),
|
// output is disabled, just display the metadata stats.
|
||||||
0, &unused1, &unused2)) {
|
const struct {
|
||||||
metadata_written |= iter->flag;
|
const MetadataPayload* const payload;
|
||||||
}
|
int flag;
|
||||||
|
} *iter, info[] = {{&metadata.exif, METADATA_EXIF},
|
||||||
|
{&metadata.iccp, METADATA_ICC},
|
||||||
|
{&metadata.xmp, METADATA_XMP},
|
||||||
|
{NULL, 0}};
|
||||||
|
uint32_t unused1 = 0;
|
||||||
|
uint64_t unused2 = 0;
|
||||||
|
|
||||||
|
for (iter = info; iter->payload != NULL; ++iter) {
|
||||||
|
if (UpdateFlagsAndSize(iter->payload, !!(keep_metadata & iter->flag),
|
||||||
|
/*flag=*/0, &unused1, &unused2)) {
|
||||||
|
metadata_written |= iter->flag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1129,20 +1204,6 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (print_distortion >= 0) { // print distortion
|
if (print_distortion >= 0) { // print distortion
|
||||||
static const char* distortion_names[] = { "PSNR", "SSIM", "LSIM" };
|
static const char* distortion_names[] = { "PSNR", "SSIM", "LSIM" };
|
||||||
float values[5];
|
float values[5];
|
||||||
if (picture.use_argb != original_picture.use_argb) {
|
|
||||||
// Somehow, the WebPEncode() call converted the original picture.
|
|
||||||
// We need to make both match before calling WebPPictureDistortion().
|
|
||||||
int ok = 0;
|
|
||||||
if (picture.use_argb) {
|
|
||||||
ok = WebPPictureYUVAToARGB(&original_picture);
|
|
||||||
} else {
|
|
||||||
ok = WebPPictureARGBToYUVA(&original_picture, WEBP_YUV420A);
|
|
||||||
}
|
|
||||||
if (!ok) {
|
|
||||||
fprintf(stderr, "Error while converting original picture.\n");
|
|
||||||
goto Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!WebPPictureDistortion(&picture, &original_picture,
|
if (!WebPPictureDistortion(&picture, &original_picture,
|
||||||
print_distortion, values)) {
|
print_distortion, values)) {
|
||||||
fprintf(stderr, "Error while computing the distortion.\n");
|
fprintf(stderr, "Error while computing the distortion.\n");
|
||||||
@@ -1150,13 +1211,8 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
if (!short_output) {
|
if (!short_output) {
|
||||||
fprintf(stderr, "%s: ", distortion_names[print_distortion]);
|
fprintf(stderr, "%s: ", distortion_names[print_distortion]);
|
||||||
if (picture.use_argb) {
|
fprintf(stderr, "B:%.2f G:%.2f R:%.2f A:%.2f Total:%.2f\n",
|
||||||
fprintf(stderr, "B:%.2f G:%.2f R:%.2f A:%.2f Total:%.2f\n",
|
values[0], values[1], values[2], values[3], values[4]);
|
||||||
values[0], values[1], values[2], values[3], values[4]);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Y:%.2f U:%.2f V:%.2f A:%.2f Total:%.2f\n",
|
|
||||||
values[0], values[1], values[2], values[3], values[4]);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "%7d %.4f\n", picture.stats->coded_size, values[4]);
|
fprintf(stderr, "%7d %.4f\n", picture.stats->coded_size, values[4]);
|
||||||
}
|
}
|
||||||
@@ -1169,7 +1225,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
Error:
|
Error:
|
||||||
WebPMemoryWriterClear(&memory_writer);
|
WebPMemoryWriterClear(&memory_writer);
|
||||||
free(picture.extra_info);
|
WebPFree(picture.extra_info);
|
||||||
MetadataFree(&metadata);
|
MetadataFree(&metadata);
|
||||||
WebPPictureFree(&picture);
|
WebPPictureFree(&picture);
|
||||||
WebPPictureFree(&original_picture);
|
WebPPictureFree(&original_picture);
|
||||||
@@ -1177,7 +1233,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
fclose(out);
|
fclose(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
return return_value;
|
FREE_WARGV_AND_RETURN(return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
679
examples/dwebp.c
679
examples/dwebp.c
@@ -20,28 +20,11 @@
|
|||||||
#include "webp/config.h"
|
#include "webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WEBP_HAVE_PNG
|
#include "../examples/example_util.h"
|
||||||
#include <png.h>
|
#include "../imageio/image_enc.h"
|
||||||
#include <setjmp.h> // note: this must be included *after* png.h
|
#include "../imageio/webpdec.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_WINCODEC_H
|
|
||||||
#ifdef __MINGW32__
|
|
||||||
#define INITGUID // Without this GUIDs are declared extern and fail to link
|
|
||||||
#endif
|
|
||||||
#define CINTERFACE
|
|
||||||
#define COBJMACROS
|
|
||||||
#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++
|
|
||||||
// code with COBJMACROS.
|
|
||||||
#include <ole2.h> // CreateStreamOnHGlobal()
|
|
||||||
#include <shlwapi.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <wincodec.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "webp/decode.h"
|
|
||||||
#include "./example_util.h"
|
|
||||||
#include "./stopwatch.h"
|
#include "./stopwatch.h"
|
||||||
|
#include "./unicode.h"
|
||||||
|
|
||||||
static int verbose = 0;
|
static int verbose = 0;
|
||||||
static int quiet = 0;
|
static int quiet = 0;
|
||||||
@@ -57,464 +40,24 @@ extern void* VP8GetCPUInfo; // opaque forward declaration.
|
|||||||
#endif
|
#endif
|
||||||
#endif // WEBP_DLL
|
#endif // WEBP_DLL
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Output types
|
|
||||||
typedef enum {
|
|
||||||
PNG = 0,
|
|
||||||
PAM,
|
|
||||||
PPM,
|
|
||||||
PGM,
|
|
||||||
BMP,
|
|
||||||
TIFF,
|
|
||||||
YUV,
|
|
||||||
ALPHA_PLANE_ONLY // this is for experimenting only
|
|
||||||
} OutputFileFormat;
|
|
||||||
|
|
||||||
#ifdef HAVE_WINCODEC_H
|
|
||||||
|
|
||||||
#define IFS(fn) \
|
|
||||||
do { \
|
|
||||||
if (SUCCEEDED(hr)) { \
|
|
||||||
hr = (fn); \
|
|
||||||
if (FAILED(hr)) fprintf(stderr, #fn " failed %08lx\n", hr); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define MAKE_REFGUID(x) (x)
|
|
||||||
#else
|
|
||||||
#define MAKE_REFGUID(x) &(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static HRESULT CreateOutputStream(const char* out_file_name,
|
|
||||||
int write_to_mem, IStream** stream) {
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (write_to_mem) {
|
|
||||||
// Output to a memory buffer. This is freed when 'stream' is released.
|
|
||||||
IFS(CreateStreamOnHGlobal(NULL, TRUE, stream));
|
|
||||||
} else {
|
|
||||||
IFS(SHCreateStreamOnFileA(out_file_name, STGM_WRITE | STGM_CREATE, stream));
|
|
||||||
}
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
fprintf(stderr, "Error opening output file %s (%08lx)\n",
|
|
||||||
out_file_name, hr);
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout,
|
|
||||||
REFGUID container_guid,
|
|
||||||
uint8_t* rgb, int stride,
|
|
||||||
uint32_t width, uint32_t height, int has_alpha) {
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
IWICImagingFactory* factory = NULL;
|
|
||||||
IWICBitmapFrameEncode* frame = NULL;
|
|
||||||
IWICBitmapEncoder* encoder = NULL;
|
|
||||||
IStream* stream = NULL;
|
|
||||||
WICPixelFormatGUID pixel_format = has_alpha ? GUID_WICPixelFormat32bppBGRA
|
|
||||||
: GUID_WICPixelFormat24bppBGR;
|
|
||||||
|
|
||||||
IFS(CoInitialize(NULL));
|
|
||||||
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
|
||||||
CLSCTX_INPROC_SERVER,
|
|
||||||
MAKE_REFGUID(IID_IWICImagingFactory),
|
|
||||||
(LPVOID*)&factory));
|
|
||||||
if (hr == REGDB_E_CLASSNOTREG) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Couldn't access Windows Imaging Component (are you running "
|
|
||||||
"Windows XP SP3 or newer?). PNG support not available. "
|
|
||||||
"Use -ppm or -pgm for available PPM and PGM formats.\n");
|
|
||||||
}
|
|
||||||
IFS(CreateOutputStream(out_file_name, use_stdout, &stream));
|
|
||||||
IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL,
|
|
||||||
&encoder));
|
|
||||||
IFS(IWICBitmapEncoder_Initialize(encoder, stream,
|
|
||||||
WICBitmapEncoderNoCache));
|
|
||||||
IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL));
|
|
||||||
IFS(IWICBitmapFrameEncode_Initialize(frame, NULL));
|
|
||||||
IFS(IWICBitmapFrameEncode_SetSize(frame, width, height));
|
|
||||||
IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format));
|
|
||||||
IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride,
|
|
||||||
height * stride, rgb));
|
|
||||||
IFS(IWICBitmapFrameEncode_Commit(frame));
|
|
||||||
IFS(IWICBitmapEncoder_Commit(encoder));
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr) && use_stdout) {
|
|
||||||
HGLOBAL image;
|
|
||||||
IFS(GetHGlobalFromStream(stream, &image));
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
HANDLE std_output = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
DWORD mode;
|
|
||||||
const BOOL update_mode = GetConsoleMode(std_output, &mode);
|
|
||||||
const void* const image_mem = GlobalLock(image);
|
|
||||||
DWORD bytes_written = 0;
|
|
||||||
|
|
||||||
// Clear output processing if necessary, then output the image.
|
|
||||||
if (update_mode) SetConsoleMode(std_output, 0);
|
|
||||||
if (!WriteFile(std_output, image_mem, (DWORD)GlobalSize(image),
|
|
||||||
&bytes_written, NULL) ||
|
|
||||||
bytes_written != GlobalSize(image)) {
|
|
||||||
hr = E_FAIL;
|
|
||||||
}
|
|
||||||
if (update_mode) SetConsoleMode(std_output, mode);
|
|
||||||
GlobalUnlock(image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame != NULL) IUnknown_Release(frame);
|
|
||||||
if (encoder != NULL) IUnknown_Release(encoder);
|
|
||||||
if (factory != NULL) IUnknown_Release(factory);
|
|
||||||
if (stream != NULL) IUnknown_Release(stream);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int WritePNG(const char* out_file_name, int use_stdout,
|
|
||||||
const WebPDecBuffer* const buffer) {
|
|
||||||
const uint32_t width = buffer->width;
|
|
||||||
const uint32_t height = buffer->height;
|
|
||||||
uint8_t* const rgb = buffer->u.RGBA.rgba;
|
|
||||||
const int stride = buffer->u.RGBA.stride;
|
|
||||||
const int has_alpha = (buffer->colorspace == MODE_BGRA);
|
|
||||||
|
|
||||||
return SUCCEEDED(WriteUsingWIC(out_file_name, use_stdout,
|
|
||||||
MAKE_REFGUID(GUID_ContainerFormatPng),
|
|
||||||
rgb, stride, width, height, has_alpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
|
|
||||||
static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp dummy) {
|
|
||||||
(void)dummy; // remove variable-unused warning
|
|
||||||
longjmp(png_jmpbuf(png), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|
||||||
const uint32_t width = buffer->width;
|
|
||||||
const uint32_t height = buffer->height;
|
|
||||||
uint8_t* const rgb = buffer->u.RGBA.rgba;
|
|
||||||
const int stride = buffer->u.RGBA.stride;
|
|
||||||
const int has_alpha = (buffer->colorspace == MODE_RGBA);
|
|
||||||
volatile png_structp png;
|
|
||||||
volatile png_infop info;
|
|
||||||
png_uint_32 y;
|
|
||||||
|
|
||||||
png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
|
||||||
NULL, PNGErrorFunction, NULL);
|
|
||||||
if (png == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
info = png_create_info_struct(png);
|
|
||||||
if (info == NULL) {
|
|
||||||
png_destroy_write_struct((png_structpp)&png, NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (setjmp(png_jmpbuf(png))) {
|
|
||||||
png_destroy_write_struct((png_structpp)&png, (png_infopp)&info);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
png_init_io(png, out_file);
|
|
||||||
png_set_IHDR(png, info, width, height, 8,
|
|
||||||
has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
|
|
||||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
|
||||||
PNG_FILTER_TYPE_DEFAULT);
|
|
||||||
png_write_info(png, info);
|
|
||||||
for (y = 0; y < height; ++y) {
|
|
||||||
png_bytep row = rgb + y * stride;
|
|
||||||
png_write_rows(png, &row, 1);
|
|
||||||
}
|
|
||||||
png_write_end(png, info);
|
|
||||||
png_destroy_write_struct((png_structpp)&png, (png_infopp)&info);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#else // !HAVE_WINCODEC_H && !WEBP_HAVE_PNG
|
|
||||||
static int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
|
||||||
(void)out_file;
|
|
||||||
(void)buffer;
|
|
||||||
fprintf(stderr, "PNG support not compiled. Please install the libpng "
|
|
||||||
"development package before building.\n");
|
|
||||||
fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int WritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha) {
|
|
||||||
const uint32_t width = buffer->width;
|
|
||||||
const uint32_t height = buffer->height;
|
|
||||||
const uint8_t* const rgb = buffer->u.RGBA.rgba;
|
|
||||||
const int stride = buffer->u.RGBA.stride;
|
|
||||||
const size_t bytes_per_px = alpha ? 4 : 3;
|
|
||||||
uint32_t y;
|
|
||||||
|
|
||||||
if (alpha) {
|
|
||||||
fprintf(fout, "P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n"
|
|
||||||
"TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
|
|
||||||
} else {
|
|
||||||
fprintf(fout, "P6\n%u %u\n255\n", width, height);
|
|
||||||
}
|
|
||||||
for (y = 0; y < height; ++y) {
|
|
||||||
if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PutLE16(uint8_t* const dst, uint32_t value) {
|
|
||||||
dst[0] = (value >> 0) & 0xff;
|
|
||||||
dst[1] = (value >> 8) & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PutLE32(uint8_t* const dst, uint32_t value) {
|
|
||||||
PutLE16(dst + 0, (value >> 0) & 0xffff);
|
|
||||||
PutLE16(dst + 2, (value >> 16) & 0xffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BMP_HEADER_SIZE 54
|
|
||||||
static int WriteBMP(FILE* fout, const WebPDecBuffer* const buffer) {
|
|
||||||
const int has_alpha = (buffer->colorspace != MODE_BGR);
|
|
||||||
const uint32_t width = buffer->width;
|
|
||||||
const uint32_t height = buffer->height;
|
|
||||||
const uint8_t* const rgba = buffer->u.RGBA.rgba;
|
|
||||||
const int stride = buffer->u.RGBA.stride;
|
|
||||||
const uint32_t bytes_per_px = has_alpha ? 4 : 3;
|
|
||||||
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 total_size = bmp_stride * height + BMP_HEADER_SIZE;
|
|
||||||
uint8_t bmp_header[BMP_HEADER_SIZE] = { 0 };
|
|
||||||
|
|
||||||
// bitmap file header
|
|
||||||
PutLE16(bmp_header + 0, 0x4d42); // signature 'BM'
|
|
||||||
PutLE32(bmp_header + 2, total_size); // size including header
|
|
||||||
PutLE32(bmp_header + 6, 0); // reserved
|
|
||||||
PutLE32(bmp_header + 10, BMP_HEADER_SIZE); // offset to pixel array
|
|
||||||
// bitmap info header
|
|
||||||
PutLE32(bmp_header + 14, 40); // DIB header size
|
|
||||||
PutLE32(bmp_header + 18, width); // dimensions
|
|
||||||
PutLE32(bmp_header + 22, -(int)height); // vertical flip!
|
|
||||||
PutLE16(bmp_header + 26, 1); // number of planes
|
|
||||||
PutLE16(bmp_header + 28, bytes_per_px * 8); // bits per pixel
|
|
||||||
PutLE32(bmp_header + 30, 0); // no compression (BI_RGB)
|
|
||||||
PutLE32(bmp_header + 34, 0); // image size (dummy)
|
|
||||||
PutLE32(bmp_header + 38, 2400); // x pixels/meter
|
|
||||||
PutLE32(bmp_header + 42, 2400); // y pixels/meter
|
|
||||||
PutLE32(bmp_header + 46, 0); // number of palette colors
|
|
||||||
PutLE32(bmp_header + 50, 0); // important color count
|
|
||||||
|
|
||||||
// TODO(skal): color profile
|
|
||||||
|
|
||||||
// write header
|
|
||||||
if (fwrite(bmp_header, sizeof(bmp_header), 1, fout) != 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write pixel array
|
|
||||||
for (y = 0; y < height; ++y) {
|
|
||||||
if (fwrite(rgba + y * stride, line_size, 1, fout) != 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// write padding zeroes
|
|
||||||
if (bmp_stride != line_size) {
|
|
||||||
const uint8_t zeroes[3] = { 0 };
|
|
||||||
if (fwrite(zeroes, bmp_stride - line_size, 1, fout) != 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#undef BMP_HEADER_SIZE
|
|
||||||
|
|
||||||
#define NUM_IFD_ENTRIES 15
|
|
||||||
#define EXTRA_DATA_SIZE 16
|
|
||||||
// 10b for signature/header + n * 12b entries + 4b for IFD terminator:
|
|
||||||
#define EXTRA_DATA_OFFSET (10 + 12 * NUM_IFD_ENTRIES + 4)
|
|
||||||
#define TIFF_HEADER_SIZE (EXTRA_DATA_OFFSET + EXTRA_DATA_SIZE)
|
|
||||||
|
|
||||||
static int WriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) {
|
|
||||||
const int has_alpha = (buffer->colorspace != MODE_RGB);
|
|
||||||
const uint32_t width = buffer->width;
|
|
||||||
const uint32_t height = buffer->height;
|
|
||||||
const uint8_t* const rgba = buffer->u.RGBA.rgba;
|
|
||||||
const int stride = buffer->u.RGBA.stride;
|
|
||||||
const uint8_t bytes_per_px = has_alpha ? 4 : 3;
|
|
||||||
// For non-alpha case, we omit tag 0x152 (ExtraSamples).
|
|
||||||
const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES
|
|
||||||
: NUM_IFD_ENTRIES - 1;
|
|
||||||
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
|
|
||||||
// IFD (offset = 8). Entries must be written in increasing tag order.
|
|
||||||
num_ifd_entries, 0, // Number of entries in the IFD (12 bytes each).
|
|
||||||
0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD)
|
|
||||||
0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD)
|
|
||||||
0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888
|
|
||||||
EXTRA_DATA_OFFSET + 0, 0, 0, 0,
|
|
||||||
0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 46: Compression: none
|
|
||||||
0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB
|
|
||||||
0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset:
|
|
||||||
TIFF_HEADER_SIZE, 0, 0, 0, // data follows header
|
|
||||||
0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft
|
|
||||||
0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels
|
|
||||||
bytes_per_px, 0, 0, 0,
|
|
||||||
0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 106: Rows per strip (TBD)
|
|
||||||
0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD)
|
|
||||||
0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution
|
|
||||||
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
|
||||||
0x1b, 0x01, 5, 0, 1, 0, 0, 0, // 142: Y-resolution
|
|
||||||
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
|
||||||
0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration
|
|
||||||
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
|
|
||||||
0x52, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 178: ExtraSamples: rgbA
|
|
||||||
0, 0, 0, 0, // 190: IFD terminator
|
|
||||||
// EXTRA_DATA_OFFSET:
|
|
||||||
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
|
|
||||||
72, 0, 0, 0, 1, 0, 0, 0 // 72 pixels/inch, for X/Y-resolution
|
|
||||||
};
|
|
||||||
uint32_t y;
|
|
||||||
|
|
||||||
// Fill placeholders in IFD:
|
|
||||||
PutLE32(tiff_header + 10 + 8, width);
|
|
||||||
PutLE32(tiff_header + 22 + 8, height);
|
|
||||||
PutLE32(tiff_header + 106 + 8, height);
|
|
||||||
PutLE32(tiff_header + 118 + 8, width * bytes_per_px * height);
|
|
||||||
if (!has_alpha) PutLE32(tiff_header + 178, 0); // IFD terminator
|
|
||||||
|
|
||||||
// write header
|
|
||||||
if (fwrite(tiff_header, sizeof(tiff_header), 1, fout) != 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// write pixel values
|
|
||||||
for (y = 0; y < height; ++y) {
|
|
||||||
if (fwrite(rgba + y * stride, bytes_per_px, width, fout) != width) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef TIFF_HEADER_SIZE
|
|
||||||
#undef EXTRA_DATA_OFFSET
|
|
||||||
#undef EXTRA_DATA_SIZE
|
|
||||||
#undef NUM_IFD_ENTRIES
|
|
||||||
|
|
||||||
static int WriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
|
|
||||||
const uint32_t width = buffer->width;
|
|
||||||
const uint32_t height = buffer->height;
|
|
||||||
const uint8_t* const a = buffer->u.YUVA.a;
|
|
||||||
const int a_stride = buffer->u.YUVA.a_stride;
|
|
||||||
uint32_t y;
|
|
||||||
assert(a != NULL);
|
|
||||||
fprintf(fout, "P5\n%u %u\n255\n", width, height);
|
|
||||||
for (y = 0; y < height; ++y) {
|
|
||||||
if (fwrite(a + y * a_stride, width, 1, fout) != 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// format=PGM: save a grayscale PGM file using the IMC4 layout
|
|
||||||
// (http://www.fourcc.org/yuv.php#IMC4). This is a very convenient format for
|
|
||||||
// viewing the samples, esp. for odd dimensions.
|
|
||||||
// format=YUV: just save the Y/U/V/A planes sequentially without header.
|
|
||||||
static int WritePGMOrYUV(FILE* fout, const WebPDecBuffer* const buffer,
|
|
||||||
OutputFileFormat format) {
|
|
||||||
const int width = buffer->width;
|
|
||||||
const int height = buffer->height;
|
|
||||||
const WebPYUVABuffer* const yuv = &buffer->u.YUVA;
|
|
||||||
int ok = 1;
|
|
||||||
int y;
|
|
||||||
const int pad = (format == YUV) ? 0 : 1;
|
|
||||||
const int uv_width = (width + 1) / 2;
|
|
||||||
const int uv_height = (height + 1) / 2;
|
|
||||||
const int out_stride = (width + pad) & ~pad;
|
|
||||||
const int a_height = yuv->a ? height : 0;
|
|
||||||
if (format == PGM) {
|
|
||||||
fprintf(fout, "P5\n%d %d\n255\n",
|
|
||||||
out_stride, height + uv_height + a_height);
|
|
||||||
}
|
|
||||||
for (y = 0; ok && y < height; ++y) {
|
|
||||||
ok &= (fwrite(yuv->y + y * yuv->y_stride, width, 1, fout) == 1);
|
|
||||||
if (format == PGM) {
|
|
||||||
if (width & 1) fputc(0, fout); // padding byte
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (format == PGM) { // IMC4 layout
|
|
||||||
for (y = 0; ok && y < uv_height; ++y) {
|
|
||||||
ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1);
|
|
||||||
ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (y = 0; ok && y < uv_height; ++y) {
|
|
||||||
ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1);
|
|
||||||
}
|
|
||||||
for (y = 0; ok && y < uv_height; ++y) {
|
|
||||||
ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (y = 0; ok && y < a_height; ++y) {
|
|
||||||
ok &= (fwrite(yuv->a + y * yuv->a_stride, width, 1, fout) == 1);
|
|
||||||
if (format == PGM) {
|
|
||||||
if (width & 1) fputc(0, fout); // padding byte
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SaveOutput(const WebPDecBuffer* const buffer,
|
static int SaveOutput(const WebPDecBuffer* const buffer,
|
||||||
OutputFileFormat format, const char* const out_file) {
|
WebPOutputFileFormat format, const char* const out_file) {
|
||||||
FILE* fout = NULL;
|
const int use_stdout = (out_file != NULL) && !WSTRCMP(out_file, "-");
|
||||||
int needs_open_file = 1;
|
|
||||||
const int use_stdout = !strcmp(out_file, "-");
|
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
Stopwatch stop_watch;
|
Stopwatch stop_watch;
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
StopwatchReset(&stop_watch);
|
StopwatchReset(&stop_watch);
|
||||||
}
|
}
|
||||||
|
ok = WebPSaveImage(buffer, format, out_file);
|
||||||
|
|
||||||
#ifdef HAVE_WINCODEC_H
|
|
||||||
needs_open_file = (format != PNG);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (needs_open_file) {
|
|
||||||
fout = use_stdout ? ExUtilSetBinaryMode(stdout) : fopen(out_file, "wb");
|
|
||||||
if (fout == NULL) {
|
|
||||||
fprintf(stderr, "Error opening output file %s\n", out_file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format == PNG) {
|
|
||||||
#ifdef HAVE_WINCODEC_H
|
|
||||||
ok &= WritePNG(out_file, use_stdout, buffer);
|
|
||||||
#else
|
|
||||||
ok &= WritePNG(fout, buffer);
|
|
||||||
#endif
|
|
||||||
} else if (format == PAM) {
|
|
||||||
ok &= WritePPM(fout, buffer, 1);
|
|
||||||
} else if (format == PPM) {
|
|
||||||
ok &= WritePPM(fout, buffer, 0);
|
|
||||||
} else if (format == BMP) {
|
|
||||||
ok &= WriteBMP(fout, buffer);
|
|
||||||
} else if (format == TIFF) {
|
|
||||||
ok &= WriteTIFF(fout, buffer);
|
|
||||||
} else if (format == PGM || format == YUV) {
|
|
||||||
ok &= WritePGMOrYUV(fout, buffer, format);
|
|
||||||
} else if (format == ALPHA_PLANE_ONLY) {
|
|
||||||
ok &= WriteAlphaPlane(fout, buffer);
|
|
||||||
}
|
|
||||||
if (fout != NULL && fout != stdout) {
|
|
||||||
fclose(fout);
|
|
||||||
}
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
if (use_stdout) {
|
if (use_stdout) {
|
||||||
fprintf(stderr, "Saved to stdout\n");
|
fprintf(stderr, "Saved to stdout\n");
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Saved file %s\n", out_file);
|
WFPRINTF(stderr, "Saved file %s\n", (const W_CHAR*)out_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
@@ -525,7 +68,7 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
|
|||||||
if (use_stdout) {
|
if (use_stdout) {
|
||||||
fprintf(stderr, "Error writing to stdout !!\n");
|
fprintf(stderr, "Error writing to stdout !!\n");
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Error writing file %s !!\n", out_file);
|
WFPRINTF(stderr, "Error writing file %s !!\n", (const W_CHAR*)out_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
@@ -533,7 +76,8 @@ static int SaveOutput(const WebPDecBuffer* const buffer,
|
|||||||
|
|
||||||
static void Help(void) {
|
static void Help(void) {
|
||||||
printf("Usage: dwebp in_file [options] [-o out_file]\n\n"
|
printf("Usage: dwebp in_file [options] [-o out_file]\n\n"
|
||||||
"Decodes the WebP image file to PNG format [Default]\n"
|
"Decodes the WebP image file to PNG format [Default].\n"
|
||||||
|
"Note: Animated WebP files are not supported.\n\n"
|
||||||
"Use following options to convert into alternate image formats:\n"
|
"Use following options to convert into alternate image formats:\n"
|
||||||
" -pam ......... save the raw RGBA samples as a color PAM\n"
|
" -pam ......... save the raw RGBA samples as a color PAM\n"
|
||||||
" -ppm ......... save the raw RGB samples as a color PPM\n"
|
" -ppm ......... save the raw RGB samples as a color PPM\n"
|
||||||
@@ -544,7 +88,7 @@ static void Help(void) {
|
|||||||
" -yuv ......... save the raw YUV samples in flat layout\n"
|
" -yuv ......... save the raw YUV samples in flat layout\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Other options are:\n"
|
" Other options are:\n"
|
||||||
" -version .... print version number and exit\n"
|
" -version ..... print version number and exit\n"
|
||||||
" -nofancy ..... don't use the fancy YUV420 upscaler\n"
|
" -nofancy ..... don't use the fancy YUV420 upscaler\n"
|
||||||
" -nofilter .... disable in-loop filtering\n"
|
" -nofilter .... disable in-loop filtering\n"
|
||||||
" -nodither .... disable dithering\n"
|
" -nodither .... disable dithering\n"
|
||||||
@@ -556,8 +100,8 @@ static void Help(void) {
|
|||||||
" -flip ........ flip the output vertically\n"
|
" -flip ........ flip the output vertically\n"
|
||||||
" -alpha ....... only save the alpha plane\n"
|
" -alpha ....... only save the alpha plane\n"
|
||||||
" -incremental . use incremental decoding (useful for tests)\n"
|
" -incremental . use incremental decoding (useful for tests)\n"
|
||||||
" -h ....... this help message\n"
|
" -h ........... this help message\n"
|
||||||
" -v ....... verbose (e.g. print encoding/decoding times)\n"
|
" -v ........... verbose (e.g. print encoding/decoding times)\n"
|
||||||
" -quiet ....... quiet mode, don't print anything\n"
|
" -quiet ....... quiet mode, don't print anything\n"
|
||||||
#ifndef WEBP_DLL
|
#ifndef WEBP_DLL
|
||||||
" -noasm ....... disable all assembly optimizations\n"
|
" -noasm ....... disable all assembly optimizations\n"
|
||||||
@@ -569,30 +113,100 @@ static const char* const kFormatType[] = {
|
|||||||
"unspecified", "lossy", "lossless"
|
"unspecified", "lossy", "lossless"
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
||||||
|
WebPOutputFileFormat format,
|
||||||
|
int use_external_memory) {
|
||||||
|
uint8_t* external_buffer = NULL;
|
||||||
|
WebPDecBuffer* const output_buffer = &config->output;
|
||||||
|
int w = config->input.width;
|
||||||
|
int h = config->input.height;
|
||||||
|
if (config->options.use_scaling) {
|
||||||
|
w = config->options.scaled_width;
|
||||||
|
h = config->options.scaled_height;
|
||||||
|
} else if (config->options.use_cropping) {
|
||||||
|
w = config->options.crop_width;
|
||||||
|
h = config->options.crop_height;
|
||||||
|
}
|
||||||
|
if (format >= RGB && format <= rgbA_4444) {
|
||||||
|
const int bpp = (format == RGB || format == BGR) ? 3
|
||||||
|
: (format == RGBA_4444 || format == rgbA_4444 ||
|
||||||
|
format == RGB_565) ? 2
|
||||||
|
: 4;
|
||||||
|
uint32_t stride = bpp * w + 7; // <- just for exercising
|
||||||
|
external_buffer = (uint8_t*)WebPMalloc(stride * h);
|
||||||
|
if (external_buffer == NULL) return NULL;
|
||||||
|
output_buffer->u.RGBA.stride = stride;
|
||||||
|
output_buffer->u.RGBA.size = stride * h;
|
||||||
|
output_buffer->u.RGBA.rgba = external_buffer;
|
||||||
|
} else { // YUV and YUVA
|
||||||
|
const int has_alpha = WebPIsAlphaMode(output_buffer->colorspace);
|
||||||
|
uint8_t* tmp;
|
||||||
|
uint32_t stride = w + 3;
|
||||||
|
uint32_t uv_stride = (w + 1) / 2 + 13;
|
||||||
|
uint32_t total_size = stride * h * (has_alpha ? 2 : 1)
|
||||||
|
+ 2 * uv_stride * (h + 1) / 2;
|
||||||
|
assert(format >= YUV && format <= YUVA);
|
||||||
|
external_buffer = (uint8_t*)WebPMalloc(total_size);
|
||||||
|
if (external_buffer == NULL) return NULL;
|
||||||
|
tmp = external_buffer;
|
||||||
|
output_buffer->u.YUVA.y = tmp;
|
||||||
|
output_buffer->u.YUVA.y_stride = stride;
|
||||||
|
output_buffer->u.YUVA.y_size = stride * h;
|
||||||
|
tmp += output_buffer->u.YUVA.y_size;
|
||||||
|
if (has_alpha) {
|
||||||
|
output_buffer->u.YUVA.a = tmp;
|
||||||
|
output_buffer->u.YUVA.a_stride = stride;
|
||||||
|
output_buffer->u.YUVA.a_size = stride * h;
|
||||||
|
tmp += output_buffer->u.YUVA.a_size;
|
||||||
|
} else {
|
||||||
|
output_buffer->u.YUVA.a = NULL;
|
||||||
|
output_buffer->u.YUVA.a_stride = 0;
|
||||||
|
}
|
||||||
|
output_buffer->u.YUVA.u = tmp;
|
||||||
|
output_buffer->u.YUVA.u_stride = uv_stride;
|
||||||
|
output_buffer->u.YUVA.u_size = uv_stride * (h + 1) / 2;
|
||||||
|
tmp += output_buffer->u.YUVA.u_size;
|
||||||
|
|
||||||
|
output_buffer->u.YUVA.v = tmp;
|
||||||
|
output_buffer->u.YUVA.v_stride = uv_stride;
|
||||||
|
output_buffer->u.YUVA.v_size = uv_stride * (h + 1) / 2;
|
||||||
|
tmp += output_buffer->u.YUVA.v_size;
|
||||||
|
assert(tmp <= external_buffer + total_size);
|
||||||
|
}
|
||||||
|
output_buffer->is_external_memory = use_external_memory;
|
||||||
|
return external_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
const char *in_file = NULL;
|
const char* in_file = NULL;
|
||||||
const char *out_file = NULL;
|
const char* out_file = NULL;
|
||||||
|
|
||||||
WebPDecoderConfig config;
|
WebPDecoderConfig config;
|
||||||
WebPDecBuffer* const output_buffer = &config.output;
|
WebPDecBuffer* const output_buffer = &config.output;
|
||||||
WebPBitstreamFeatures* const bitstream = &config.input;
|
WebPBitstreamFeatures* const bitstream = &config.input;
|
||||||
OutputFileFormat format = PNG;
|
WebPOutputFileFormat format = PNG;
|
||||||
|
uint8_t* external_buffer = NULL;
|
||||||
|
int use_external_memory = 0;
|
||||||
|
const uint8_t* data = NULL;
|
||||||
|
|
||||||
int incremental = 0;
|
int incremental = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
INIT_WARGV(argc, argv);
|
||||||
|
|
||||||
if (!WebPInitDecoderConfig(&config)) {
|
if (!WebPInitDecoderConfig(&config)) {
|
||||||
fprintf(stderr, "Library version mismatch!\n");
|
fprintf(stderr, "Library version mismatch!\n");
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
Help();
|
Help();
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
|
||||||
out_file = argv[++c];
|
out_file = (const char*)GET_WARGV(argv, ++c);
|
||||||
} else if (!strcmp(argv[c], "-alpha")) {
|
} else if (!strcmp(argv[c], "-alpha")) {
|
||||||
format = ALPHA_PLANE_ONLY;
|
format = ALPHA_PLANE_ONLY;
|
||||||
} else if (!strcmp(argv[c], "-nofancy")) {
|
} else if (!strcmp(argv[c], "-nofancy")) {
|
||||||
@@ -613,11 +227,36 @@ int main(int argc, const char *argv[]) {
|
|||||||
const int version = WebPGetDecoderVersion();
|
const int version = WebPGetDecoderVersion();
|
||||||
printf("%d.%d.%d\n",
|
printf("%d.%d.%d\n",
|
||||||
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-pgm")) {
|
} else if (!strcmp(argv[c], "-pgm")) {
|
||||||
format = PGM;
|
format = PGM;
|
||||||
} else if (!strcmp(argv[c], "-yuv")) {
|
} else if (!strcmp(argv[c], "-yuv")) {
|
||||||
format = YUV;
|
format = RAW_YUV;
|
||||||
|
} else if (!strcmp(argv[c], "-pixel_format") && c < argc - 1) {
|
||||||
|
const char* const fmt = argv[++c];
|
||||||
|
if (!strcmp(fmt, "RGB")) format = RGB;
|
||||||
|
else if (!strcmp(fmt, "RGBA")) format = RGBA;
|
||||||
|
else if (!strcmp(fmt, "BGR")) format = BGR;
|
||||||
|
else if (!strcmp(fmt, "BGRA")) format = BGRA;
|
||||||
|
else if (!strcmp(fmt, "ARGB")) format = ARGB;
|
||||||
|
else if (!strcmp(fmt, "RGBA_4444")) format = RGBA_4444;
|
||||||
|
else if (!strcmp(fmt, "RGB_565")) format = RGB_565;
|
||||||
|
else if (!strcmp(fmt, "rgbA")) format = rgbA;
|
||||||
|
else if (!strcmp(fmt, "bgrA")) format = bgrA;
|
||||||
|
else if (!strcmp(fmt, "Argb")) format = Argb;
|
||||||
|
else if (!strcmp(fmt, "rgbA_4444")) format = rgbA_4444;
|
||||||
|
else if (!strcmp(fmt, "YUV")) format = YUV;
|
||||||
|
else if (!strcmp(fmt, "YUVA")) format = YUVA;
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Can't parse pixel_format %s\n", fmt);
|
||||||
|
parse_error = 1;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(argv[c], "-external_memory") && c < argc - 1) {
|
||||||
|
use_external_memory = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
parse_error |= (use_external_memory > 2 || use_external_memory < 0);
|
||||||
|
if (parse_error) {
|
||||||
|
fprintf(stderr, "Can't parse 'external_memory' value %s\n", argv[c]);
|
||||||
|
}
|
||||||
} else if (!strcmp(argv[c], "-mt")) {
|
} else if (!strcmp(argv[c], "-mt")) {
|
||||||
config.options.use_threads = 1;
|
config.options.use_threads = 1;
|
||||||
} else if (!strcmp(argv[c], "-alpha_dither")) {
|
} else if (!strcmp(argv[c], "-alpha_dither")) {
|
||||||
@@ -649,26 +288,26 @@ int main(int argc, const char *argv[]) {
|
|||||||
} else if (!strcmp(argv[c], "-incremental")) {
|
} else if (!strcmp(argv[c], "-incremental")) {
|
||||||
incremental = 1;
|
incremental = 1;
|
||||||
} else if (!strcmp(argv[c], "--")) {
|
} else if (!strcmp(argv[c], "--")) {
|
||||||
if (c < argc - 1) in_file = argv[++c];
|
if (c < argc - 1) in_file = (const char*)GET_WARGV(argv, ++c);
|
||||||
break;
|
break;
|
||||||
} else if (argv[c][0] == '-') {
|
} else if (argv[c][0] == '-') {
|
||||||
fprintf(stderr, "Unknown option '%s'\n", argv[c]);
|
fprintf(stderr, "Unknown option '%s'\n", argv[c]);
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
} else {
|
} else {
|
||||||
in_file = argv[c];
|
in_file = (const char*)GET_WARGV(argv, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parse_error) {
|
if (parse_error) {
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_file == NULL) {
|
if (in_file == NULL) {
|
||||||
fprintf(stderr, "missing input file!!\n");
|
fprintf(stderr, "missing input file!!\n");
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quiet) verbose = 0;
|
if (quiet) verbose = 0;
|
||||||
@@ -676,9 +315,8 @@ int main(int argc, const char *argv[]) {
|
|||||||
{
|
{
|
||||||
VP8StatusCode status = VP8_STATUS_OK;
|
VP8StatusCode status = VP8_STATUS_OK;
|
||||||
size_t data_size = 0;
|
size_t data_size = 0;
|
||||||
const uint8_t* data = NULL;
|
if (!LoadWebP(in_file, &data, &data_size, bitstream)) {
|
||||||
if (!ExUtilLoadWebP(in_file, &data, &data_size, bitstream)) {
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (format) {
|
switch (format) {
|
||||||
@@ -698,50 +336,75 @@ int main(int argc, const char *argv[]) {
|
|||||||
case BMP:
|
case BMP:
|
||||||
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
|
||||||
break;
|
break;
|
||||||
case TIFF: // note: force pre-multiplied alpha
|
case TIFF:
|
||||||
output_buffer->colorspace =
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB;
|
||||||
bitstream->has_alpha ? MODE_rgbA : MODE_RGB;
|
|
||||||
break;
|
break;
|
||||||
case PGM:
|
case PGM:
|
||||||
case YUV:
|
case RAW_YUV:
|
||||||
output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV;
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV;
|
||||||
break;
|
break;
|
||||||
case ALPHA_PLANE_ONLY:
|
case ALPHA_PLANE_ONLY:
|
||||||
output_buffer->colorspace = MODE_YUVA;
|
output_buffer->colorspace = MODE_YUVA;
|
||||||
break;
|
break;
|
||||||
default:
|
// forced modes:
|
||||||
free((void*)data);
|
case RGB: output_buffer->colorspace = MODE_RGB; break;
|
||||||
return -1;
|
case RGBA: output_buffer->colorspace = MODE_RGBA; break;
|
||||||
|
case BGR: output_buffer->colorspace = MODE_BGR; break;
|
||||||
|
case BGRA: output_buffer->colorspace = MODE_BGRA; break;
|
||||||
|
case ARGB: output_buffer->colorspace = MODE_ARGB; break;
|
||||||
|
case RGBA_4444: output_buffer->colorspace = MODE_RGBA_4444; break;
|
||||||
|
case RGB_565: output_buffer->colorspace = MODE_RGB_565; break;
|
||||||
|
case rgbA: output_buffer->colorspace = MODE_rgbA; break;
|
||||||
|
case bgrA: output_buffer->colorspace = MODE_bgrA; break;
|
||||||
|
case Argb: output_buffer->colorspace = MODE_Argb; break;
|
||||||
|
case rgbA_4444: output_buffer->colorspace = MODE_rgbA_4444; break;
|
||||||
|
case YUV: output_buffer->colorspace = MODE_YUV; break;
|
||||||
|
case YUVA: output_buffer->colorspace = MODE_YUVA; break;
|
||||||
|
default: goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incremental) {
|
if (use_external_memory > 0 && format >= RGB) {
|
||||||
status = ExUtilDecodeWebPIncremental(data, data_size, verbose, &config);
|
external_buffer = AllocateExternalBuffer(&config, format,
|
||||||
} else {
|
use_external_memory);
|
||||||
status = ExUtilDecodeWebP(data, data_size, verbose, &config);
|
if (external_buffer == NULL) goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Stopwatch stop_watch;
|
||||||
|
if (verbose) StopwatchReset(&stop_watch);
|
||||||
|
|
||||||
|
if (incremental) {
|
||||||
|
status = DecodeWebPIncremental(data, data_size, &config);
|
||||||
|
} else {
|
||||||
|
status = DecodeWebP(data, data_size, &config);
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
const double decode_time = StopwatchReadAndReset(&stop_watch);
|
||||||
|
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free((void*)data);
|
|
||||||
ok = (status == VP8_STATUS_OK);
|
ok = (status == VP8_STATUS_OK);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
ExUtilPrintWebPError(in_file, status);
|
PrintWebPError(in_file, status);
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_file != NULL) {
|
if (out_file != NULL) {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
fprintf(stderr, "Decoded %s. Dimensions: %d x %d %s. Format: %s. "
|
WFPRINTF(stderr, "Decoded %s.", (const W_CHAR*)in_file);
|
||||||
"Now saving...\n",
|
fprintf(stderr, " Dimensions: %d x %d %s. Format: %s. Now saving...\n",
|
||||||
in_file, output_buffer->width, output_buffer->height,
|
output_buffer->width, output_buffer->height,
|
||||||
bitstream->has_alpha ? " (with alpha)" : "",
|
bitstream->has_alpha ? " (with alpha)" : "",
|
||||||
kFormatType[bitstream->format]);
|
kFormatType[bitstream->format]);
|
||||||
}
|
}
|
||||||
ok = SaveOutput(output_buffer, format, out_file);
|
ok = SaveOutput(output_buffer, format, out_file);
|
||||||
} else {
|
} else {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
fprintf(stderr, "File %s can be decoded "
|
WFPRINTF(stderr, "File %s can be decoded ", (const W_CHAR*)in_file);
|
||||||
"(dimensions: %d x %d %s. Format: %s).\n",
|
fprintf(stderr, "(dimensions: %d x %d %s. Format: %s).\n",
|
||||||
in_file, output_buffer->width, output_buffer->height,
|
output_buffer->width, output_buffer->height,
|
||||||
bitstream->has_alpha ? " (with alpha)" : "",
|
bitstream->has_alpha ? " (with alpha)" : "",
|
||||||
kFormatType[bitstream->format]);
|
kFormatType[bitstream->format]);
|
||||||
fprintf(stderr, "Nothing written; "
|
fprintf(stderr, "Nothing written; "
|
||||||
@@ -750,7 +413,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
Exit:
|
Exit:
|
||||||
WebPFreeDecBuffer(output_buffer);
|
WebPFreeDecBuffer(output_buffer);
|
||||||
return ok ? 0 : -1;
|
WebPFree((void*)external_buffer);
|
||||||
|
WebPFree((void*)data);
|
||||||
|
FREE_WARGV_AND_RETURN(ok ? 0 : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -12,16 +12,13 @@
|
|||||||
|
|
||||||
#include "./example_util.h"
|
#include "./example_util.h"
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#include <assert.h>
|
||||||
#include <fcntl.h> // for _O_BINARY
|
|
||||||
#include <io.h> // for _setmode()
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/decode.h"
|
#include "webp/mux_types.h"
|
||||||
#include "./stopwatch.h"
|
#include "../imageio/imageio_util.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// String parsing
|
// String parsing
|
||||||
@@ -41,6 +38,18 @@ int ExUtilGetInt(const char* const v, int base, int* const error) {
|
|||||||
return (int)ExUtilGetUInt(v, base, error);
|
return (int)ExUtilGetUInt(v, base, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ExUtilGetInts(const char* v, int base, int max_output, int output[]) {
|
||||||
|
int n, error = 0;
|
||||||
|
for (n = 0; v != NULL && n < max_output; ++n) {
|
||||||
|
const int value = ExUtilGetInt(v, base, &error);
|
||||||
|
if (error) return -1;
|
||||||
|
output[n] = value;
|
||||||
|
v = strchr(v, ',');
|
||||||
|
if (v != NULL) ++v; // skip over the trailing ','
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
float ExUtilGetFloat(const char* const v, int* const error) {
|
float ExUtilGetFloat(const char* const v, int* const error) {
|
||||||
char* end = NULL;
|
char* end = NULL;
|
||||||
const float f = (v != NULL) ? (float)strtod(v, &end) : 0.f;
|
const float f = (v != NULL) ? (float)strtod(v, &end) : 0.f;
|
||||||
@@ -52,219 +61,75 @@ float ExUtilGetFloat(const char* const v, int* const error) {
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// File I/O
|
|
||||||
|
|
||||||
FILE* ExUtilSetBinaryMode(FILE* file) {
|
|
||||||
#if defined(_WIN32)
|
|
||||||
if (_setmode(_fileno(file), _O_BINARY) == -1) {
|
|
||||||
fprintf(stderr, "Failed to reopen file in O_BINARY mode.\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
|
|
||||||
static const size_t kBlockSize = 16384; // default initial size
|
|
||||||
size_t max_size = 0;
|
|
||||||
size_t size = 0;
|
|
||||||
uint8_t* input = NULL;
|
|
||||||
|
|
||||||
if (data == NULL || data_size == NULL) return 0;
|
|
||||||
*data = NULL;
|
|
||||||
*data_size = 0;
|
|
||||||
|
|
||||||
if (!ExUtilSetBinaryMode(stdin)) return 0;
|
|
||||||
|
|
||||||
while (!feof(stdin)) {
|
|
||||||
// We double the buffer size each time and read as much as possible.
|
|
||||||
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;
|
|
||||||
void* const new_data = realloc(input, max_size + extra_size);
|
|
||||||
if (new_data == NULL) goto Error;
|
|
||||||
input = (uint8_t*)new_data;
|
|
||||||
max_size += extra_size;
|
|
||||||
size += fread(input + size, 1, extra_size, stdin);
|
|
||||||
if (size < max_size) break;
|
|
||||||
}
|
|
||||||
if (ferror(stdin)) goto Error;
|
|
||||||
*data = input;
|
|
||||||
*data_size = size;
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
Error:
|
|
||||||
free(input);
|
|
||||||
fprintf(stderr, "Could not read from stdin\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExUtilReadFile(const char* const file_name,
|
|
||||||
const uint8_t** data, size_t* data_size) {
|
|
||||||
int ok;
|
|
||||||
void* file_data;
|
|
||||||
size_t file_size;
|
|
||||||
FILE* in;
|
|
||||||
const int from_stdin = (file_name == NULL) || !strcmp(file_name, "-");
|
|
||||||
|
|
||||||
if (from_stdin) return ExUtilReadFromStdin(data, data_size);
|
|
||||||
|
|
||||||
if (data == NULL || data_size == NULL) return 0;
|
|
||||||
*data = NULL;
|
|
||||||
*data_size = 0;
|
|
||||||
|
|
||||||
in = fopen(file_name, "rb");
|
|
||||||
if (in == NULL) {
|
|
||||||
fprintf(stderr, "cannot open input file '%s'\n", file_name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
fseek(in, 0, SEEK_END);
|
|
||||||
file_size = ftell(in);
|
|
||||||
fseek(in, 0, SEEK_SET);
|
|
||||||
file_data = malloc(file_size);
|
|
||||||
if (file_data == NULL) return 0;
|
|
||||||
ok = (fread(file_data, file_size, 1, in) == 1);
|
|
||||||
fclose(in);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
fprintf(stderr, "Could not read %d bytes of data from file %s\n",
|
|
||||||
(int)file_size, file_name);
|
|
||||||
free(file_data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*data = (uint8_t*)file_data;
|
|
||||||
*data_size = file_size;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExUtilWriteFile(const char* const file_name,
|
|
||||||
const uint8_t* data, size_t data_size) {
|
|
||||||
int ok;
|
|
||||||
FILE* out;
|
|
||||||
const int to_stdout = (file_name == NULL) || !strcmp(file_name, "-");
|
|
||||||
|
|
||||||
if (data == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
out = to_stdout ? stdout : fopen(file_name, "wb");
|
|
||||||
if (out == NULL) {
|
|
||||||
fprintf(stderr, "Error! Cannot open output file '%s'\n", file_name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ok = (fwrite(data, data_size, 1, out) == 1);
|
|
||||||
if (out != stdout) fclose(out);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// WebP decoding
|
|
||||||
|
|
||||||
static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = {
|
|
||||||
"OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
|
|
||||||
"UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
|
|
||||||
};
|
|
||||||
|
|
||||||
static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
|
|
||||||
if (config->input.has_animation) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Error! Decoding of an animated WebP file is not supported.\n"
|
|
||||||
" Use webpmux to extract the individual frames or\n"
|
|
||||||
" vwebp to view this image.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExUtilPrintWebPError(const char* const in_file, int status) {
|
|
||||||
fprintf(stderr, "Decoding of %s failed.\n", in_file);
|
|
||||||
fprintf(stderr, "Status: %d", status);
|
|
||||||
if (status >= VP8_STATUS_OK && status <= VP8_STATUS_NOT_ENOUGH_DATA) {
|
|
||||||
fprintf(stderr, "(%s)", kStatusMessages[status]);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExUtilLoadWebP(const char* const in_file,
|
|
||||||
const uint8_t** data, size_t* data_size,
|
|
||||||
WebPBitstreamFeatures* bitstream) {
|
|
||||||
VP8StatusCode status;
|
|
||||||
WebPBitstreamFeatures local_features;
|
|
||||||
if (!ExUtilReadFile(in_file, data, data_size)) return 0;
|
|
||||||
|
|
||||||
if (bitstream == NULL) {
|
|
||||||
bitstream = &local_features;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = WebPGetFeatures(*data, *data_size, bitstream);
|
|
||||||
if (status != VP8_STATUS_OK) {
|
|
||||||
free((void*)*data);
|
|
||||||
*data = NULL;
|
|
||||||
*data_size = 0;
|
|
||||||
ExUtilPrintWebPError(in_file, status);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
VP8StatusCode ExUtilDecodeWebP(const uint8_t* const data, size_t data_size,
|
static void ResetCommandLineArguments(int argc, const char* argv[],
|
||||||
int verbose, WebPDecoderConfig* const config) {
|
CommandLineArguments* const args) {
|
||||||
Stopwatch stop_watch;
|
assert(args != NULL);
|
||||||
VP8StatusCode status = VP8_STATUS_OK;
|
args->argc_ = argc;
|
||||||
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
args->argv_ = argv;
|
||||||
|
args->own_argv_ = 0;
|
||||||
PrintAnimationWarning(config);
|
WebPDataInit(&args->argv_data_);
|
||||||
|
|
||||||
StopwatchReset(&stop_watch);
|
|
||||||
|
|
||||||
// Decoding call.
|
|
||||||
status = WebPDecode(data, data_size, config);
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
const double decode_time = StopwatchReadAndReset(&stop_watch);
|
|
||||||
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VP8StatusCode ExUtilDecodeWebPIncremental(
|
void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args) {
|
||||||
const uint8_t* const data, size_t data_size,
|
if (args != NULL) {
|
||||||
int verbose, WebPDecoderConfig* const config) {
|
if (args->own_argv_) {
|
||||||
Stopwatch stop_watch;
|
WebPFree((void*)args->argv_);
|
||||||
VP8StatusCode status = VP8_STATUS_OK;
|
WebPDataClear(&args->argv_data_);
|
||||||
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
|
||||||
|
|
||||||
PrintAnimationWarning(config);
|
|
||||||
|
|
||||||
StopwatchReset(&stop_watch);
|
|
||||||
|
|
||||||
// Decoding call.
|
|
||||||
{
|
|
||||||
WebPIDecoder* const idec = WebPIDecode(data, data_size, config);
|
|
||||||
if (idec == NULL) {
|
|
||||||
fprintf(stderr, "Failed during WebPINewDecoder().\n");
|
|
||||||
return VP8_STATUS_OUT_OF_MEMORY;
|
|
||||||
} else {
|
|
||||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
|
||||||
size_t size = 0;
|
|
||||||
const size_t incr = 2 + (data_size / 20);
|
|
||||||
while (size < data_size) {
|
|
||||||
size_t next_size = size + (rand() % incr);
|
|
||||||
if (next_size > data_size) next_size = data_size;
|
|
||||||
status = WebPIUpdate(idec, data, next_size);
|
|
||||||
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) break;
|
|
||||||
size = next_size;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
status = WebPIUpdate(idec, data, data_size);
|
|
||||||
#endif
|
|
||||||
WebPIDelete(idec);
|
|
||||||
}
|
}
|
||||||
|
ResetCommandLineArguments(0, NULL, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
const double decode_time = StopwatchReadAndReset(&stop_watch);
|
|
||||||
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
#define MAX_ARGC 16384
|
||||||
|
int ExUtilInitCommandLineArguments(int argc, const char* argv[],
|
||||||
|
CommandLineArguments* const args) {
|
||||||
|
if (args == NULL || argv == NULL) return 0;
|
||||||
|
ResetCommandLineArguments(argc, argv, args);
|
||||||
|
if (argc == 1 && argv[0][0] != '-') {
|
||||||
|
char* cur;
|
||||||
|
const char sep[] = " \t\r\n\f\v";
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_UNICODE)
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: Reading arguments from a file is a feature unavailable "
|
||||||
|
"with Unicode binaries.\n");
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ExUtilReadFileToWebPData(argv[0], &args->argv_data_)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
args->own_argv_ = 1;
|
||||||
|
args->argv_ = (const char**)WebPMalloc(MAX_ARGC * sizeof(*args->argv_));
|
||||||
|
if (args->argv_ == NULL) return 0;
|
||||||
|
|
||||||
|
argc = 0;
|
||||||
|
for (cur = strtok((char*)args->argv_data_.bytes, sep);
|
||||||
|
cur != NULL;
|
||||||
|
cur = strtok(NULL, sep)) {
|
||||||
|
if (argc == MAX_ARGC) {
|
||||||
|
fprintf(stderr, "ERROR: Arguments limit %d reached\n", MAX_ARGC);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert(strlen(cur) != 0);
|
||||||
|
args->argv_[argc++] = cur;
|
||||||
|
}
|
||||||
|
args->argc_ = argc;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int ExUtilReadFileToWebPData(const char* const filename,
|
||||||
|
WebPData* const webp_data) {
|
||||||
|
const uint8_t* data;
|
||||||
|
size_t size;
|
||||||
|
if (webp_data == NULL) return 0;
|
||||||
|
if (!ImgIoUtilReadFile(filename, &data, &size)) return 0;
|
||||||
|
webp_data->bytes = data;
|
||||||
|
webp_data->size = size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
#ifndef WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
||||||
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
#define WEBP_EXAMPLES_EXAMPLE_UTIL_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "webp/types.h"
|
||||||
#include "webp/decode.h"
|
#include "webp/mux_types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -30,57 +30,38 @@ uint32_t ExUtilGetUInt(const char* const v, int base, int* const error);
|
|||||||
int ExUtilGetInt(const char* const v, int base, int* const error);
|
int ExUtilGetInt(const char* const v, int base, int* const error);
|
||||||
float ExUtilGetFloat(const char* const v, int* const error);
|
float ExUtilGetFloat(const char* const v, int* const error);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
// This variant of ExUtilGetInt() will parse multiple integers from a
|
||||||
// File I/O
|
// comma-separated list. Up to 'max_output' integers are parsed.
|
||||||
|
// The result is placed in the output[] array, and the number of integers
|
||||||
|
// actually parsed is returned, or -1 if an error occurred.
|
||||||
|
int ExUtilGetInts(const char* v, int base, int max_output, int output[]);
|
||||||
|
|
||||||
// Reopen file in binary (O_BINARY) mode.
|
// Reads a file named 'filename' into a WebPData structure. The content of
|
||||||
// Returns 'file' on success, NULL otherwise.
|
// webp_data is overwritten. Returns false in case of error.
|
||||||
FILE* ExUtilSetBinaryMode(FILE* file);
|
int ExUtilReadFileToWebPData(const char* const filename,
|
||||||
|
WebPData* const webp_data);
|
||||||
// Allocates storage for entire file 'file_name' and returns contents and size
|
|
||||||
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
|
|
||||||
// be deleted using free().
|
|
||||||
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
|
|
||||||
// the function ExUtilReadFromStdin().
|
|
||||||
int ExUtilReadFile(const char* const file_name,
|
|
||||||
const uint8_t** data, size_t* data_size);
|
|
||||||
|
|
||||||
// Same as ExUtilReadFile(), but reads until EOF from stdin instead.
|
|
||||||
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size);
|
|
||||||
|
|
||||||
// Write a data segment into a file named 'file_name'. Returns true if ok.
|
|
||||||
// If 'file_name' is NULL or equal to "-", output is written to stdout.
|
|
||||||
int ExUtilWriteFile(const char* const file_name,
|
|
||||||
const uint8_t* data, size_t data_size);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// WebP decoding
|
// Command-line arguments
|
||||||
|
|
||||||
// Prints an informative error message regarding decode failure of 'in_file'.
|
typedef struct {
|
||||||
// 'status' is treated as a VP8StatusCode and if valid will be printed as a
|
int argc_;
|
||||||
// text string.
|
const char** argv_;
|
||||||
void ExUtilPrintWebPError(const char* const in_file, int status);
|
WebPData argv_data_;
|
||||||
|
int own_argv_;
|
||||||
|
} CommandLineArguments;
|
||||||
|
|
||||||
// Reads a WebP from 'in_file', returning the contents and size in 'data' and
|
// Initializes the structure from the command-line parameters. If there is
|
||||||
// 'data_size'. If not NULL, 'bitstream' is populated using WebPGetFeatures().
|
// only one parameter and it does not start with a '-', then it is assumed to
|
||||||
// Returns true on success.
|
// be a file name. This file will be read and tokenized into command-line
|
||||||
int ExUtilLoadWebP(const char* const in_file,
|
// arguments. The content of 'args' is overwritten.
|
||||||
const uint8_t** data, size_t* data_size,
|
// Returns false in case of error (memory allocation failure, non
|
||||||
WebPBitstreamFeatures* bitstream);
|
// existing file, too many arguments, ...).
|
||||||
|
int ExUtilInitCommandLineArguments(int argc, const char* argv[],
|
||||||
|
CommandLineArguments* const args);
|
||||||
|
|
||||||
// Decodes the WebP contained in 'data'.
|
// Deallocate all memory and reset 'args'.
|
||||||
// 'config' is a structure previously initialized by WebPInitDecoderConfig().
|
void ExUtilDeleteCommandLineArguments(CommandLineArguments* const args);
|
||||||
// 'config->output' should have the desired colorspace selected. 'verbose' will
|
|
||||||
// cause decode timing to be reported.
|
|
||||||
// Returns the decoder status. On success 'config->output' will contain the
|
|
||||||
// decoded picture.
|
|
||||||
VP8StatusCode ExUtilDecodeWebP(const uint8_t* const data, size_t data_size,
|
|
||||||
int verbose, WebPDecoderConfig* const config);
|
|
||||||
|
|
||||||
// Same as ExUtilDecodeWebP(), but using the incremental decoder.
|
|
||||||
VP8StatusCode ExUtilDecodeWebPIncremental(
|
|
||||||
const uint8_t* const data, size_t data_size,
|
|
||||||
int verbose, WebPDecoderConfig* const config);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|||||||
@@ -23,11 +23,22 @@
|
|||||||
|
|
||||||
#ifdef WEBP_HAVE_GIF
|
#ifdef WEBP_HAVE_GIF
|
||||||
|
|
||||||
|
#if defined(HAVE_UNISTD_H) && HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <gif_lib.h>
|
#include <gif_lib.h>
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
#include "webp/mux.h"
|
#include "webp/mux.h"
|
||||||
#include "./example_util.h"
|
#include "../examples/example_util.h"
|
||||||
|
#include "../imageio/imageio_util.h"
|
||||||
#include "./gifdec.h"
|
#include "./gifdec.h"
|
||||||
|
#include "./unicode.h"
|
||||||
|
#include "./unicode_gif.h"
|
||||||
|
|
||||||
|
#if !defined(STDIN_FILENO)
|
||||||
|
#define STDIN_FILENO 0
|
||||||
|
#endif
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -55,7 +66,7 @@ static void Help(void) {
|
|||||||
printf("Usage:\n");
|
printf("Usage:\n");
|
||||||
printf(" gif2webp [options] gif_file -o webp_file\n");
|
printf(" gif2webp [options] gif_file -o webp_file\n");
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" -h / -help ............ this help\n");
|
printf(" -h / -help ............. this help\n");
|
||||||
printf(" -lossy ................. encode image using lossy compression\n");
|
printf(" -lossy ................. encode image using lossy compression\n");
|
||||||
printf(" -mixed ................. for each frame in the image, pick lossy\n"
|
printf(" -mixed ................. for each frame in the image, pick lossy\n"
|
||||||
" or lossless compression heuristically\n");
|
" or lossless compression heuristically\n");
|
||||||
@@ -71,8 +82,10 @@ static void Help(void) {
|
|||||||
printf(" -metadata <string> ..... comma separated list of metadata to\n");
|
printf(" -metadata <string> ..... comma separated list of metadata to\n");
|
||||||
printf(" ");
|
printf(" ");
|
||||||
printf("copy from the input to the output if present\n");
|
printf("copy from the input to the output if present\n");
|
||||||
printf(" "
|
printf(" ");
|
||||||
"Valid values: all, none, icc, xmp (default)\n");
|
printf("Valid values: all, none, icc, xmp (default)\n");
|
||||||
|
printf(" -loop_compatibility .... use compatibility mode for Chrome\n");
|
||||||
|
printf(" version prior to M62 (inclusive)\n");
|
||||||
printf(" -mt .................... use multi-threading if available\n");
|
printf(" -mt .................... use multi-threading if available\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" -version ............... print version number and exit\n");
|
printf(" -version ............... print version number and exit\n");
|
||||||
@@ -83,13 +96,12 @@ static void Help(void) {
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
int gif_error = GIF_ERROR;
|
int gif_error = GIF_ERROR;
|
||||||
WebPMuxError err = WEBP_MUX_OK;
|
WebPMuxError err = WEBP_MUX_OK;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
const char *in_file = NULL, *out_file = NULL;
|
const W_CHAR* in_file = NULL, *out_file = NULL;
|
||||||
FILE* out = NULL;
|
|
||||||
GifFileType* gif = NULL;
|
GifFileType* gif = NULL;
|
||||||
int frame_duration = 0;
|
int frame_duration = 0;
|
||||||
int frame_timestamp = 0;
|
int frame_timestamp = 0;
|
||||||
@@ -98,13 +110,12 @@ int main(int argc, const char *argv[]) {
|
|||||||
WebPPicture frame; // Frame rectangle only (not disposed).
|
WebPPicture frame; // Frame rectangle only (not disposed).
|
||||||
WebPPicture curr_canvas; // Not disposed.
|
WebPPicture curr_canvas; // Not disposed.
|
||||||
WebPPicture prev_canvas; // Disposed.
|
WebPPicture prev_canvas; // Disposed.
|
||||||
WebPPicture prev_to_prev_canvas; // Disposed.
|
|
||||||
|
|
||||||
WebPAnimEncoder* enc = NULL;
|
WebPAnimEncoder* enc = NULL;
|
||||||
WebPAnimEncoderOptions enc_options;
|
WebPAnimEncoderOptions enc_options;
|
||||||
WebPConfig config;
|
WebPConfig config;
|
||||||
|
|
||||||
int is_first_frame = 1; // Whether we are processing the first frame.
|
int frame_number = 0; // Whether we are processing the first frame.
|
||||||
int done;
|
int done;
|
||||||
int c;
|
int c;
|
||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
@@ -115,19 +126,21 @@ int main(int argc, const char *argv[]) {
|
|||||||
int stored_icc = 0; // Whether we have already stored an ICC profile.
|
int stored_icc = 0; // Whether we have already stored an ICC profile.
|
||||||
WebPData xmp_data;
|
WebPData xmp_data;
|
||||||
int stored_xmp = 0; // Whether we have already stored an XMP profile.
|
int stored_xmp = 0; // Whether we have already stored an XMP profile.
|
||||||
int loop_count = 0;
|
int loop_count = 0; // default: infinite
|
||||||
int stored_loop_count = 0; // Whether we have found an explicit loop count.
|
int stored_loop_count = 0; // Whether we have found an explicit loop count.
|
||||||
|
int loop_compatibility = 0;
|
||||||
WebPMux* mux = NULL;
|
WebPMux* mux = NULL;
|
||||||
|
|
||||||
int default_kmin = 1; // Whether to use default kmin value.
|
int default_kmin = 1; // Whether to use default kmin value.
|
||||||
int default_kmax = 1;
|
int default_kmax = 1;
|
||||||
|
|
||||||
|
INIT_WARGV(argc, argv);
|
||||||
|
|
||||||
if (!WebPConfigInit(&config) || !WebPAnimEncoderOptionsInit(&enc_options) ||
|
if (!WebPConfigInit(&config) || !WebPAnimEncoderOptionsInit(&enc_options) ||
|
||||||
!WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) ||
|
!WebPPictureInit(&frame) || !WebPPictureInit(&curr_canvas) ||
|
||||||
!WebPPictureInit(&prev_canvas) ||
|
!WebPPictureInit(&prev_canvas)) {
|
||||||
!WebPPictureInit(&prev_to_prev_canvas)) {
|
|
||||||
fprintf(stderr, "Error! Version mismatch!\n");
|
fprintf(stderr, "Error! Version mismatch!\n");
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
config.lossless = 1; // Use lossless compression by default.
|
config.lossless = 1; // Use lossless compression by default.
|
||||||
|
|
||||||
@@ -137,21 +150,23 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
Help();
|
Help();
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
Help();
|
Help();
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
|
||||||
out_file = argv[++c];
|
out_file = GET_WARGV(argv, ++c);
|
||||||
} else if (!strcmp(argv[c], "-lossy")) {
|
} else if (!strcmp(argv[c], "-lossy")) {
|
||||||
config.lossless = 0;
|
config.lossless = 0;
|
||||||
} else if (!strcmp(argv[c], "-mixed")) {
|
} else if (!strcmp(argv[c], "-mixed")) {
|
||||||
enc_options.allow_mixed = 1;
|
enc_options.allow_mixed = 1;
|
||||||
config.lossless = 0;
|
config.lossless = 0;
|
||||||
|
} else if (!strcmp(argv[c], "-loop_compatibility")) {
|
||||||
|
loop_compatibility = 1;
|
||||||
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
|
||||||
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
|
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-m") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-m") && c < argc - 1) {
|
||||||
@@ -201,7 +216,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
|
fprintf(stderr, "Error! Unknown metadata type '%.*s'\n",
|
||||||
(int)(token - start), start);
|
(int)(token - start), start);
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
start = token + 1;
|
start = token + 1;
|
||||||
}
|
}
|
||||||
@@ -214,26 +229,27 @@ int main(int argc, const char *argv[]) {
|
|||||||
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
|
(enc_version >> 16) & 0xff, (enc_version >> 8) & 0xff,
|
||||||
enc_version & 0xff, (mux_version >> 16) & 0xff,
|
enc_version & 0xff, (mux_version >> 16) & 0xff,
|
||||||
(mux_version >> 8) & 0xff, mux_version & 0xff);
|
(mux_version >> 8) & 0xff, mux_version & 0xff);
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-quiet")) {
|
} else if (!strcmp(argv[c], "-quiet")) {
|
||||||
quiet = 1;
|
quiet = 1;
|
||||||
|
enc_options.verbose = 0;
|
||||||
} else if (!strcmp(argv[c], "-v")) {
|
} else if (!strcmp(argv[c], "-v")) {
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
enc_options.verbose = 1;
|
enc_options.verbose = 1;
|
||||||
} else if (!strcmp(argv[c], "--")) {
|
} else if (!strcmp(argv[c], "--")) {
|
||||||
if (c < argc - 1) in_file = argv[++c];
|
if (c < argc - 1) in_file = GET_WARGV(argv, ++c);
|
||||||
break;
|
break;
|
||||||
} else if (argv[c][0] == '-') {
|
} else if (argv[c][0] == '-') {
|
||||||
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
|
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
} else {
|
} else {
|
||||||
in_file = argv[c];
|
in_file = GET_WARGV(argv, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parse_error) {
|
if (parse_error) {
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,11 +273,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start the decoder object
|
// Start the decoder object
|
||||||
#if LOCAL_GIF_PREREQ(5,0)
|
gif = DGifOpenFileUnicode(in_file, &gif_error);
|
||||||
gif = DGifOpenFileName(in_file, &gif_error);
|
|
||||||
#else
|
|
||||||
gif = DGifOpenFileName(in_file);
|
|
||||||
#endif
|
|
||||||
if (gif == NULL) goto End;
|
if (gif == NULL) goto End;
|
||||||
|
|
||||||
// Loop over GIF images
|
// Loop over GIF images
|
||||||
@@ -277,7 +289,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
if (!DGifGetImageDesc(gif)) goto End;
|
if (!DGifGetImageDesc(gif)) goto End;
|
||||||
|
|
||||||
if (is_first_frame) {
|
if (frame_number == 0) {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
printf("Canvas screen: %d x %d\n", gif->SWidth, gif->SHeight);
|
printf("Canvas screen: %d x %d\n", gif->SWidth, gif->SHeight);
|
||||||
}
|
}
|
||||||
@@ -304,7 +316,6 @@ int main(int argc, const char *argv[]) {
|
|||||||
GIFClearPic(&frame, NULL);
|
GIFClearPic(&frame, NULL);
|
||||||
WebPPictureCopy(&frame, &curr_canvas);
|
WebPPictureCopy(&frame, &curr_canvas);
|
||||||
WebPPictureCopy(&frame, &prev_canvas);
|
WebPPictureCopy(&frame, &prev_canvas);
|
||||||
WebPPictureCopy(&frame, &prev_to_prev_canvas);
|
|
||||||
|
|
||||||
// Background color.
|
// Background color.
|
||||||
GIFGetBackgroundColor(gif->SColorMap, gif->SBackGroundColor,
|
GIFGetBackgroundColor(gif->SColorMap, gif->SBackGroundColor,
|
||||||
@@ -320,7 +331,6 @@ int main(int argc, const char *argv[]) {
|
|||||||
"a memory error.\n");
|
"a memory error.\n");
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
is_first_frame = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some even more broken GIF can have sub-rect with zero width/height.
|
// Some even more broken GIF can have sub-rect with zero width/height.
|
||||||
@@ -337,14 +347,25 @@ int main(int argc, const char *argv[]) {
|
|||||||
GIFBlendFrames(&frame, &gif_rect, &curr_canvas);
|
GIFBlendFrames(&frame, &gif_rect, &curr_canvas);
|
||||||
|
|
||||||
if (!WebPAnimEncoderAdd(enc, &curr_canvas, frame_timestamp, &config)) {
|
if (!WebPAnimEncoderAdd(enc, &curr_canvas, frame_timestamp, &config)) {
|
||||||
fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc));
|
fprintf(stderr, "Error while adding frame #%d: %s\n", frame_number,
|
||||||
|
WebPAnimEncoderGetError(enc));
|
||||||
|
goto End;
|
||||||
|
} else {
|
||||||
|
++frame_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update canvases.
|
// Update canvases.
|
||||||
GIFCopyPixels(&prev_canvas, &prev_to_prev_canvas);
|
|
||||||
GIFDisposeFrame(orig_dispose, &gif_rect, &prev_canvas, &curr_canvas);
|
GIFDisposeFrame(orig_dispose, &gif_rect, &prev_canvas, &curr_canvas);
|
||||||
GIFCopyPixels(&curr_canvas, &prev_canvas);
|
GIFCopyPixels(&curr_canvas, &prev_canvas);
|
||||||
|
|
||||||
|
// Force frames with a small or no duration to 100ms to be consistent
|
||||||
|
// with web browsers and other transcoding tools. This also avoids
|
||||||
|
// incorrect durations between frames when padding frames are
|
||||||
|
// discarded.
|
||||||
|
if (frame_duration <= 10) {
|
||||||
|
frame_duration = 100;
|
||||||
|
}
|
||||||
|
|
||||||
// Update timestamp (for next frame).
|
// Update timestamp (for next frame).
|
||||||
frame_timestamp += frame_duration;
|
frame_timestamp += frame_duration;
|
||||||
|
|
||||||
@@ -358,10 +379,12 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
case EXTENSION_RECORD_TYPE: {
|
case EXTENSION_RECORD_TYPE: {
|
||||||
int extension;
|
int extension;
|
||||||
GifByteType *data = NULL;
|
GifByteType* data = NULL;
|
||||||
if (DGifGetExtension(gif, &extension, &data) == GIF_ERROR) {
|
if (DGifGetExtension(gif, &extension, &data) == GIF_ERROR) {
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
if (data == NULL) continue;
|
||||||
|
|
||||||
switch (extension) {
|
switch (extension) {
|
||||||
case COMMENT_EXT_FUNC_CODE: {
|
case COMMENT_EXT_FUNC_CODE: {
|
||||||
break; // Do nothing for now.
|
break; // Do nothing for now.
|
||||||
@@ -386,7 +409,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (verbose) {
|
if (verbose) {
|
||||||
fprintf(stderr, "Loop count: %d\n", loop_count);
|
fprintf(stderr, "Loop count: %d\n", loop_count);
|
||||||
}
|
}
|
||||||
stored_loop_count = (loop_count != 0);
|
stored_loop_count = loop_compatibility ? (loop_count != 0) : 1;
|
||||||
} else { // An extension containing metadata.
|
} else { // An extension containing metadata.
|
||||||
// We only store the first encountered chunk of each type, and
|
// We only store the first encountered chunk of each type, and
|
||||||
// only if requested by the user.
|
// only if requested by the user.
|
||||||
@@ -442,6 +465,25 @@ int main(int argc, const char *argv[]) {
|
|||||||
fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc));
|
fprintf(stderr, "%s\n", WebPAnimEncoderGetError(enc));
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
// If there's only one frame, we don't need to handle loop count.
|
||||||
|
if (frame_number == 1) {
|
||||||
|
loop_count = 0;
|
||||||
|
} else if (!loop_compatibility) {
|
||||||
|
if (!stored_loop_count) {
|
||||||
|
// if no loop-count element is seen, the default is '1' (loop-once)
|
||||||
|
// and we need to signal it explicitly in WebP. Note however that
|
||||||
|
// in case there's a single frame, we still don't need to store it.
|
||||||
|
if (frame_number > 1) {
|
||||||
|
stored_loop_count = 1;
|
||||||
|
loop_count = 1;
|
||||||
|
}
|
||||||
|
} else if (loop_count > 0 && loop_count < 65535) {
|
||||||
|
// adapt GIF's semantic to WebP's (except in the infinite-loop case)
|
||||||
|
loop_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// loop_count of 0 is the default (infinite), so no need to signal it
|
||||||
|
if (loop_count == 0) stored_loop_count = 0;
|
||||||
|
|
||||||
if (stored_loop_count || stored_icc || stored_xmp) {
|
if (stored_loop_count || stored_icc || stored_xmp) {
|
||||||
// Re-mux to add loop count and/or metadata as needed.
|
// Re-mux to add loop count and/or metadata as needed.
|
||||||
@@ -502,13 +544,19 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (out_file != NULL) {
|
if (out_file != NULL) {
|
||||||
if (!ExUtilWriteFile(out_file, webp_data.bytes, webp_data.size)) {
|
if (!ImgIoUtilWriteFile((const char*)out_file, webp_data.bytes,
|
||||||
fprintf(stderr, "Error writing output file: %s\n", out_file);
|
webp_data.size)) {
|
||||||
|
WFPRINTF(stderr, "Error writing output file: %s\n", out_file);
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
fprintf(stderr, "Saved output file (%d bytes): %s\n",
|
if (!WSTRCMP(out_file, "-")) {
|
||||||
(int)webp_data.size, out_file);
|
fprintf(stderr, "Saved %d bytes to STDIO\n",
|
||||||
|
(int)webp_data.size);
|
||||||
|
} else {
|
||||||
|
WFPRINTF(stderr, "Saved output file (%d bytes): %s\n",
|
||||||
|
(int)webp_data.size, out_file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
@@ -529,9 +577,7 @@ int main(int argc, const char *argv[]) {
|
|||||||
WebPPictureFree(&frame);
|
WebPPictureFree(&frame);
|
||||||
WebPPictureFree(&curr_canvas);
|
WebPPictureFree(&curr_canvas);
|
||||||
WebPPictureFree(&prev_canvas);
|
WebPPictureFree(&prev_canvas);
|
||||||
WebPPictureFree(&prev_to_prev_canvas);
|
|
||||||
WebPAnimEncoderDelete(enc);
|
WebPAnimEncoderDelete(enc);
|
||||||
if (out != NULL && out_file != NULL) fclose(out);
|
|
||||||
|
|
||||||
if (gif_error != GIF_OK) {
|
if (gif_error != GIF_OK) {
|
||||||
GIFDisplayError(gif, gif_error);
|
GIFDisplayError(gif, gif_error);
|
||||||
@@ -544,12 +590,12 @@ int main(int argc, const char *argv[]) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return !ok;
|
FREE_WARGV_AND_RETURN(!ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !WEBP_HAVE_GIF
|
#else // !WEBP_HAVE_GIF
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]);
|
fprintf(stderr, "GIF support not enabled in %s.\n", argv[0]);
|
||||||
(void)argc;
|
(void)argc;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -21,18 +21,24 @@
|
|||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
#include "webp/mux_types.h"
|
#include "webp/mux_types.h"
|
||||||
|
|
||||||
#define GIF_TRANSPARENT_COLOR 0x00ffffff
|
#define GIF_TRANSPARENT_COLOR 0x00000000u
|
||||||
#define GIF_WHITE_COLOR 0xffffffff
|
#define GIF_WHITE_COLOR 0xffffffffu
|
||||||
#define GIF_TRANSPARENT_MASK 0x01
|
#define GIF_TRANSPARENT_MASK 0x01
|
||||||
#define GIF_DISPOSE_MASK 0x07
|
#define GIF_DISPOSE_MASK 0x07
|
||||||
#define GIF_DISPOSE_SHIFT 2
|
#define GIF_DISPOSE_SHIFT 2
|
||||||
|
|
||||||
// from utils/utils.h
|
// from utils/utils.h
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
extern void WebPCopyPlane(const uint8_t* src, int src_stride,
|
extern void WebPCopyPlane(const uint8_t* src, int src_stride,
|
||||||
uint8_t* dst, int dst_stride,
|
uint8_t* dst, int dst_stride,
|
||||||
int width, int height);
|
int width, int height);
|
||||||
extern void WebPCopyPixels(const WebPPicture* const src,
|
extern void WebPCopyPixels(const WebPPicture* const src,
|
||||||
WebPPicture* const dst);
|
WebPPicture* const dst);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void GIFGetBackgroundColor(const ColorMapObject* const color_map,
|
void GIFGetBackgroundColor(const ColorMapObject* const color_map,
|
||||||
int bgcolor_index, int transparent_index,
|
int bgcolor_index, int transparent_index,
|
||||||
@@ -48,7 +54,7 @@ void GIFGetBackgroundColor(const ColorMapObject* const color_map,
|
|||||||
"white background.\n");
|
"white background.\n");
|
||||||
} else {
|
} else {
|
||||||
const GifColorType color = color_map->Colors[bgcolor_index];
|
const GifColorType color = color_map->Colors[bgcolor_index];
|
||||||
*bgcolor = (0xff << 24)
|
*bgcolor = (0xffu << 24)
|
||||||
| (color.Red << 16)
|
| (color.Red << 16)
|
||||||
| (color.Green << 8)
|
| (color.Green << 8)
|
||||||
| (color.Blue << 0);
|
| (color.Blue << 0);
|
||||||
@@ -81,20 +87,27 @@ int GIFReadGraphicsExtension(const GifByteType* const buf, int* const duration,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Remap(const GifFileType* const gif, const uint8_t* const src,
|
static int Remap(const GifFileType* const gif, const uint8_t* const src,
|
||||||
int len, int transparent_index, uint32_t* dst) {
|
int len, int transparent_index, uint32_t* dst) {
|
||||||
int i;
|
int i;
|
||||||
const GifColorType* colors;
|
const GifColorType* colors;
|
||||||
const ColorMapObject* const cmap =
|
const ColorMapObject* const cmap =
|
||||||
gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap;
|
gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap;
|
||||||
if (cmap == NULL) return;
|
if (cmap == NULL) return 1;
|
||||||
|
if (cmap->Colors == NULL || cmap->ColorCount <= 0) return 0;
|
||||||
colors = cmap->Colors;
|
colors = cmap->Colors;
|
||||||
|
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
const GifColorType c = colors[src[i]];
|
if (src[i] == transparent_index) {
|
||||||
dst[i] = (src[i] == transparent_index) ? GIF_TRANSPARENT_COLOR
|
dst[i] = GIF_TRANSPARENT_COLOR;
|
||||||
: c.Blue | (c.Green << 8) | (c.Red << 16) | (0xff << 24);
|
} else if (src[i] < cmap->ColorCount) {
|
||||||
|
const GifColorType c = colors[src[i]];
|
||||||
|
dst[i] = c.Blue | (c.Green << 8) | (c.Red << 16) | (0xffu << 24);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
||||||
@@ -103,12 +116,18 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
const GifImageDesc* const image_desc = &gif->Image;
|
const GifImageDesc* const image_desc = &gif->Image;
|
||||||
uint32_t* dst = NULL;
|
uint32_t* dst = NULL;
|
||||||
uint8_t* tmp = NULL;
|
uint8_t* tmp = NULL;
|
||||||
int ok = 0;
|
const GIFFrameRect rect = {
|
||||||
GIFFrameRect rect = {
|
|
||||||
image_desc->Left, image_desc->Top, image_desc->Width, image_desc->Height
|
image_desc->Left, image_desc->Top, image_desc->Width, image_desc->Height
|
||||||
};
|
};
|
||||||
|
const uint64_t memory_needed = 4 * rect.width * (uint64_t)rect.height;
|
||||||
|
int ok = 0;
|
||||||
*gif_rect = rect;
|
*gif_rect = rect;
|
||||||
|
|
||||||
|
if (memory_needed != (size_t)memory_needed || memory_needed > (4ULL << 32)) {
|
||||||
|
fprintf(stderr, "Image is too large (%d x %d).", rect.width, rect.height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Use a view for the sub-picture:
|
// Use a view for the sub-picture:
|
||||||
if (!WebPPictureView(picture, rect.x_offset, rect.y_offset,
|
if (!WebPPictureView(picture, rect.x_offset, rect.y_offset,
|
||||||
rect.width, rect.height, &sub_image)) {
|
rect.width, rect.height, &sub_image)) {
|
||||||
@@ -118,7 +137,7 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
}
|
}
|
||||||
dst = sub_image.argb;
|
dst = sub_image.argb;
|
||||||
|
|
||||||
tmp = (uint8_t*)malloc(rect.width * sizeof(*tmp));
|
tmp = (uint8_t*)WebPMalloc(rect.width * sizeof(*tmp));
|
||||||
if (tmp == NULL) goto End;
|
if (tmp == NULL) goto End;
|
||||||
|
|
||||||
if (image_desc->Interlace) { // Interlaced image.
|
if (image_desc->Interlace) { // Interlaced image.
|
||||||
@@ -127,20 +146,21 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
const int interlace_jumps[] = { 8, 8, 4, 2 };
|
const int interlace_jumps[] = { 8, 8, 4, 2 };
|
||||||
int pass;
|
int pass;
|
||||||
for (pass = 0; pass < 4; ++pass) {
|
for (pass = 0; pass < 4; ++pass) {
|
||||||
int y;
|
const size_t stride = (size_t)sub_image.argb_stride;
|
||||||
for (y = interlace_offsets[pass]; y < rect.height;
|
int y = interlace_offsets[pass];
|
||||||
y += interlace_jumps[pass]) {
|
uint32_t* row = dst + y * stride;
|
||||||
|
const size_t jump = interlace_jumps[pass] * stride;
|
||||||
|
for (; y < rect.height; y += interlace_jumps[pass], row += jump) {
|
||||||
if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
|
if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
|
||||||
Remap(gif, tmp, rect.width, transparent_index,
|
if (!Remap(gif, tmp, rect.width, transparent_index, row)) goto End;
|
||||||
dst + y * sub_image.argb_stride);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // Non-interlaced image.
|
} else { // Non-interlaced image.
|
||||||
int y;
|
int y;
|
||||||
for (y = 0; y < rect.height; ++y) {
|
uint32_t* ptr = dst;
|
||||||
|
for (y = 0; y < rect.height; ++y, ptr += sub_image.argb_stride) {
|
||||||
if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
|
if (DGifGetLine(gif, tmp, rect.width) == GIF_ERROR) goto End;
|
||||||
Remap(gif, tmp, rect.width, transparent_index,
|
if (!Remap(gif, tmp, rect.width, transparent_index, ptr)) goto End;
|
||||||
dst + y * sub_image.argb_stride);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
@@ -148,7 +168,7 @@ int GIFReadFrame(GifFileType* const gif, int transparent_index,
|
|||||||
End:
|
End:
|
||||||
if (!ok) picture->error_code = sub_image.error_code;
|
if (!ok) picture->error_code = sub_image.error_code;
|
||||||
WebPPictureFree(&sub_image);
|
WebPPictureFree(&sub_image);
|
||||||
free(tmp);
|
WebPFree(tmp);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,13 +236,11 @@ int GIFReadMetadata(GifFileType* const gif, GifByteType** const buf,
|
|||||||
|
|
||||||
static void ClearRectangle(WebPPicture* const picture,
|
static void ClearRectangle(WebPPicture* const picture,
|
||||||
int left, int top, int width, int height) {
|
int left, int top, int width, int height) {
|
||||||
int j;
|
int i, j;
|
||||||
for (j = top; j < top + height; ++j) {
|
const size_t stride = picture->argb_stride;
|
||||||
uint32_t* const dst = picture->argb + j * picture->argb_stride;
|
uint32_t* dst = picture->argb + top * stride + left;
|
||||||
int i;
|
for (j = 0; j < height; ++j, dst += stride) {
|
||||||
for (i = left; i < left + width; ++i) {
|
for (i = 0; i < width; ++i) dst[i] = GIF_TRANSPARENT_COLOR;
|
||||||
dst[i] = GIF_TRANSPARENT_COLOR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,29 +264,31 @@ void GIFDisposeFrame(GIFDisposeMethod dispose, const GIFFrameRect* const rect,
|
|||||||
if (dispose == GIF_DISPOSE_BACKGROUND) {
|
if (dispose == GIF_DISPOSE_BACKGROUND) {
|
||||||
GIFClearPic(curr_canvas, rect);
|
GIFClearPic(curr_canvas, rect);
|
||||||
} else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) {
|
} else if (dispose == GIF_DISPOSE_RESTORE_PREVIOUS) {
|
||||||
const int src_stride = prev_canvas->argb_stride;
|
const size_t src_stride = prev_canvas->argb_stride;
|
||||||
const uint32_t* const src =
|
const uint32_t* const src = prev_canvas->argb + rect->x_offset
|
||||||
prev_canvas->argb + rect->x_offset + rect->y_offset * src_stride;
|
+ rect->y_offset * src_stride;
|
||||||
const int dst_stride = curr_canvas->argb_stride;
|
const size_t dst_stride = curr_canvas->argb_stride;
|
||||||
uint32_t* const dst =
|
uint32_t* const dst = curr_canvas->argb + rect->x_offset
|
||||||
curr_canvas->argb + rect->x_offset + rect->y_offset * dst_stride;
|
+ rect->y_offset * dst_stride;
|
||||||
assert(prev_canvas != NULL);
|
assert(prev_canvas != NULL);
|
||||||
WebPCopyPlane((uint8_t*)src, 4 * src_stride, (uint8_t*)dst, 4 * dst_stride,
|
WebPCopyPlane((uint8_t*)src, (int)(4 * src_stride),
|
||||||
|
(uint8_t*)dst, (int)(4 * dst_stride),
|
||||||
4 * rect->width, rect->height);
|
4 * rect->width, rect->height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIFBlendFrames(const WebPPicture* const src,
|
void GIFBlendFrames(const WebPPicture* const src,
|
||||||
const GIFFrameRect* const rect, WebPPicture* const dst) {
|
const GIFFrameRect* const rect, WebPPicture* const dst) {
|
||||||
int j;
|
int i, j;
|
||||||
|
const size_t src_stride = src->argb_stride;
|
||||||
|
const size_t dst_stride = dst->argb_stride;
|
||||||
assert(src->width == dst->width && src->height == dst->height);
|
assert(src->width == dst->width && src->height == dst->height);
|
||||||
for (j = rect->y_offset; j < rect->y_offset + rect->height; ++j) {
|
for (j = rect->y_offset; j < rect->y_offset + rect->height; ++j) {
|
||||||
int i;
|
|
||||||
for (i = rect->x_offset; i < rect->x_offset + rect->width; ++i) {
|
for (i = rect->x_offset; i < rect->x_offset + rect->width; ++i) {
|
||||||
const uint32_t src_pixel = src->argb[j * src->argb_stride + i];
|
const uint32_t src_pixel = src->argb[j * src_stride + i];
|
||||||
const int src_alpha = src_pixel >> 24;
|
const int src_alpha = src_pixel >> 24;
|
||||||
if (src_alpha != 0) {
|
if (src_alpha != 0) {
|
||||||
dst->argb[j * dst->argb_stride + i] = src_pixel;
|
dst->argb[j * dst_stride + i] = src_pixel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
324
examples/img2webp.c
Normal file
324
examples/img2webp.c
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// generate an animated WebP out of a sequence of images
|
||||||
|
// (PNG, JPEG, ...)
|
||||||
|
//
|
||||||
|
// Example usage:
|
||||||
|
// img2webp -o out.webp -q 40 -mixed -duration 40 input??.png
|
||||||
|
//
|
||||||
|
// Author: skal@google.com (Pascal Massimino)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "webp/config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../examples/example_util.h"
|
||||||
|
#include "../imageio/image_dec.h"
|
||||||
|
#include "../imageio/imageio_util.h"
|
||||||
|
#include "./stopwatch.h"
|
||||||
|
#include "./unicode.h"
|
||||||
|
#include "webp/encode.h"
|
||||||
|
#include "webp/mux.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static void Help(void) {
|
||||||
|
printf("Usage:\n\n");
|
||||||
|
printf(" img2webp [file-level options] [image files...] "
|
||||||
|
"[per-frame options...]\n");
|
||||||
|
printf("\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(" -v ................... verbose mode\n");
|
||||||
|
printf(" -h ................... this help\n");
|
||||||
|
printf(" -version ............. print version number and exit\n");
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
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(" -q <float> ........... quality\n");
|
||||||
|
printf(" -m <int> ............. method to use\n");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf("example: img2webp -loop 2 in0.png -lossy in1.jpg\n"
|
||||||
|
" -d 80 in2.tiff -o out.webp\n");
|
||||||
|
printf("\nNote: if a single file name is passed as the argument, the "
|
||||||
|
"arguments will be\n");
|
||||||
|
printf("tokenized from this file. The file name must not start with "
|
||||||
|
"the character '-'.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static int ReadImage(const char filename[], WebPPicture* const pic) {
|
||||||
|
const uint8_t* data = NULL;
|
||||||
|
size_t data_size = 0;
|
||||||
|
WebPImageReader reader;
|
||||||
|
int ok;
|
||||||
|
#ifdef HAVE_WINCODEC_H
|
||||||
|
// Try to decode the file using WIC falling back to the other readers for
|
||||||
|
// e.g., WebP.
|
||||||
|
ok = ReadPictureWithWIC(filename, pic, 1, NULL);
|
||||||
|
if (ok) return 1;
|
||||||
|
#endif
|
||||||
|
if (!ImgIoUtilReadFile(filename, &data, &data_size)) return 0;
|
||||||
|
reader = WebPGuessImageReader(data, data_size);
|
||||||
|
ok = reader(data, data_size, pic, 1, NULL);
|
||||||
|
WebPFree((void*)data);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SetLoopCount(int loop_count, WebPData* const webp_data) {
|
||||||
|
int ok = 1;
|
||||||
|
WebPMuxError err;
|
||||||
|
uint32_t features;
|
||||||
|
WebPMuxAnimParams new_params;
|
||||||
|
WebPMux* const mux = WebPMuxCreate(webp_data, 1);
|
||||||
|
if (mux == NULL) return 0;
|
||||||
|
|
||||||
|
err = WebPMuxGetFeatures(mux, &features);
|
||||||
|
ok = (err == WEBP_MUX_OK);
|
||||||
|
if (!ok || !(features & ANIMATION_FLAG)) goto End;
|
||||||
|
|
||||||
|
err = WebPMuxGetAnimationParams(mux, &new_params);
|
||||||
|
ok = (err == WEBP_MUX_OK);
|
||||||
|
if (ok) {
|
||||||
|
new_params.loop_count = loop_count;
|
||||||
|
err = WebPMuxSetAnimationParams(mux, &new_params);
|
||||||
|
ok = (err == WEBP_MUX_OK);
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
WebPDataClear(webp_data);
|
||||||
|
err = WebPMuxAssemble(mux, webp_data);
|
||||||
|
ok = (err == WEBP_MUX_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
End:
|
||||||
|
WebPMuxDelete(mux);
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "Error during loop-count setting\n");
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
const char* output = NULL;
|
||||||
|
WebPAnimEncoder* enc = NULL;
|
||||||
|
int verbose = 0;
|
||||||
|
int pic_num = 0;
|
||||||
|
int duration = 100;
|
||||||
|
int timestamp_ms = 0;
|
||||||
|
int loop_count = 0;
|
||||||
|
int width = 0, height = 0;
|
||||||
|
WebPAnimEncoderOptions anim_config;
|
||||||
|
WebPConfig config;
|
||||||
|
WebPPicture pic;
|
||||||
|
WebPData webp_data;
|
||||||
|
int c;
|
||||||
|
int have_input = 0;
|
||||||
|
CommandLineArguments cmd_args;
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
INIT_WARGV(argc, argv);
|
||||||
|
|
||||||
|
ok = ExUtilInitCommandLineArguments(argc - 1, argv + 1, &cmd_args);
|
||||||
|
if (!ok) FREE_WARGV_AND_RETURN(1);
|
||||||
|
|
||||||
|
argc = cmd_args.argc_;
|
||||||
|
argv = cmd_args.argv_;
|
||||||
|
|
||||||
|
WebPDataInit(&webp_data);
|
||||||
|
if (!WebPAnimEncoderOptionsInit(&anim_config) ||
|
||||||
|
!WebPConfigInit(&config) ||
|
||||||
|
!WebPPictureInit(&pic)) {
|
||||||
|
fprintf(stderr, "Library version mismatch!\n");
|
||||||
|
ok = 0;
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1st pass of option parsing
|
||||||
|
for (c = 0; ok && c < argc; ++c) {
|
||||||
|
if (argv[c][0] == '-') {
|
||||||
|
int parse_error = 0;
|
||||||
|
if (!strcmp(argv[c], "-o") && c + 1 < argc) {
|
||||||
|
argv[c] = NULL;
|
||||||
|
output = (const char*)GET_WARGV_SHIFTED(argv, ++c);
|
||||||
|
} else if (!strcmp(argv[c], "-kmin") && c + 1 < argc) {
|
||||||
|
argv[c] = NULL;
|
||||||
|
anim_config.kmin = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
} else if (!strcmp(argv[c], "-kmax") && c + 1 < argc) {
|
||||||
|
argv[c] = NULL;
|
||||||
|
anim_config.kmax = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
} else if (!strcmp(argv[c], "-loop") && c + 1 < argc) {
|
||||||
|
argv[c] = NULL;
|
||||||
|
loop_count = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
if (loop_count < 0) {
|
||||||
|
fprintf(stderr, "Invalid non-positive loop-count (%d)\n", loop_count);
|
||||||
|
parse_error = 1;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(argv[c], "-min_size")) {
|
||||||
|
anim_config.minimize_size = 1;
|
||||||
|
} else if (!strcmp(argv[c], "-mixed")) {
|
||||||
|
anim_config.allow_mixed = 1;
|
||||||
|
config.lossless = 0;
|
||||||
|
} else if (!strcmp(argv[c], "-v")) {
|
||||||
|
verbose = 1;
|
||||||
|
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
|
Help();
|
||||||
|
goto End;
|
||||||
|
} else if (!strcmp(argv[c], "-version")) {
|
||||||
|
const int enc_version = WebPGetEncoderVersion();
|
||||||
|
const int mux_version = WebPGetMuxVersion();
|
||||||
|
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);
|
||||||
|
goto End;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ok = !parse_error;
|
||||||
|
if (!ok) goto End;
|
||||||
|
argv[c] = NULL; // mark option as 'parsed' during 1st pass
|
||||||
|
} else {
|
||||||
|
have_input |= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!have_input) {
|
||||||
|
fprintf(stderr, "No input file(s) for generating animation!\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
// image-reading pass
|
||||||
|
pic_num = 0;
|
||||||
|
config.lossless = 1;
|
||||||
|
for (c = 0; ok && c < argc; ++c) {
|
||||||
|
if (argv[c] == NULL) continue;
|
||||||
|
if (argv[c][0] == '-') { // parse local options
|
||||||
|
int parse_error = 0;
|
||||||
|
if (!strcmp(argv[c], "-lossy")) {
|
||||||
|
if (!anim_config.allow_mixed) config.lossless = 0;
|
||||||
|
} else if (!strcmp(argv[c], "-lossless")) {
|
||||||
|
if (!anim_config.allow_mixed) config.lossless = 1;
|
||||||
|
} else if (!strcmp(argv[c], "-q") && c + 1 < argc) {
|
||||||
|
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
|
} else if (!strcmp(argv[c], "-m") && c + 1 < argc) {
|
||||||
|
config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
} else if (!strcmp(argv[c], "-d") && c + 1 < argc) {
|
||||||
|
duration = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
if (duration <= 0) {
|
||||||
|
fprintf(stderr, "Invalid negative duration (%d)\n", duration);
|
||||||
|
parse_error = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parse_error = 1; // shouldn't be here.
|
||||||
|
fprintf(stderr, "Unknown option [%s]\n", argv[c]);
|
||||||
|
}
|
||||||
|
ok = !parse_error;
|
||||||
|
if (!ok) goto End;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
ok = WebPValidateConfig(&config);
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "Invalid configuration.\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read next input image
|
||||||
|
pic.use_argb = 1;
|
||||||
|
ok = ReadImage((const char*)GET_WARGV_SHIFTED(argv, c), &pic);
|
||||||
|
if (!ok) goto End;
|
||||||
|
|
||||||
|
if (enc == NULL) {
|
||||||
|
width = pic.width;
|
||||||
|
height = pic.height;
|
||||||
|
enc = WebPAnimEncoderNew(width, height, &anim_config);
|
||||||
|
ok = (enc != NULL);
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "Could not create WebPAnimEncoder object.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
ok = (width == pic.width && height == pic.height);
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "Frame #%d dimension mismatched! "
|
||||||
|
"Got %d x %d. Was expecting %d x %d.\n",
|
||||||
|
pic_num, pic.width, pic.height, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
ok = WebPAnimEncoderAdd(enc, &pic, timestamp_ms, &config);
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "Error while adding frame #%d\n", pic_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WebPPictureFree(&pic);
|
||||||
|
if (!ok) goto End;
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
WFPRINTF(stderr, "Added frame #%3d at time %4d (file: %s)\n",
|
||||||
|
pic_num, timestamp_ms, GET_WARGV_SHIFTED(argv, c));
|
||||||
|
}
|
||||||
|
timestamp_ms += duration;
|
||||||
|
++pic_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a last fake frame to signal the last duration
|
||||||
|
ok = ok && WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL);
|
||||||
|
ok = ok && WebPAnimEncoderAssemble(enc, &webp_data);
|
||||||
|
if (!ok) {
|
||||||
|
fprintf(stderr, "Error during final animation assembly.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
End:
|
||||||
|
// free resources
|
||||||
|
WebPAnimEncoderDelete(enc);
|
||||||
|
|
||||||
|
if (ok && loop_count > 0) { // Re-mux to add loop count.
|
||||||
|
ok = SetLoopCount(loop_count, &webp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
if (output != NULL) {
|
||||||
|
ok = ImgIoUtilWriteFile(output, webp_data.bytes, webp_data.size);
|
||||||
|
if (ok) WFPRINTF(stderr, "output file: %s ", (const W_CHAR*)output);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "[no output file specified] ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
fprintf(stderr, "[%d frames, %u bytes].\n",
|
||||||
|
pic_num, (unsigned int)webp_data.size);
|
||||||
|
}
|
||||||
|
WebPDataClear(&webp_data);
|
||||||
|
ExUtilDeleteCommandLineArguments(&cmd_args);
|
||||||
|
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
|
||||||
|
}
|
||||||
@@ -60,4 +60,4 @@ static WEBP_INLINE double StopwatchReadAndReset(Stopwatch* watch) {
|
|||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
#endif /* WEBP_EXAMPLES_STOPWATCH_H_ */
|
#endif // WEBP_EXAMPLES_STOPWATCH_H_
|
||||||
|
|||||||
102
examples/unicode.h
Normal file
102
examples/unicode.h
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
// Copyright 2018 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the COPYING file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Unicode support for Windows. The main idea is to maintain an array of Unicode
|
||||||
|
// arguments (wargv) and use it only for file paths. The regular argv is used
|
||||||
|
// for everything else.
|
||||||
|
//
|
||||||
|
// Author: Yannis Guyon (yguyon@google.com)
|
||||||
|
|
||||||
|
#ifndef WEBP_EXAMPLES_UNICODE_H_
|
||||||
|
#define WEBP_EXAMPLES_UNICODE_H_
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_UNICODE)
|
||||||
|
|
||||||
|
// wchar_t is used instead of TCHAR because we only perform additional work when
|
||||||
|
// Unicode is enabled and because the output of CommandLineToArgvW() is wchar_t.
|
||||||
|
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
|
||||||
|
// Create a wchar_t array containing Unicode parameters.
|
||||||
|
#define INIT_WARGV(ARGC, ARGV) \
|
||||||
|
int wargc; \
|
||||||
|
const W_CHAR** const wargv = \
|
||||||
|
(const W_CHAR**)CommandLineToArgvW(GetCommandLineW(), &wargc); \
|
||||||
|
do { \
|
||||||
|
if (wargv == NULL || wargc != (ARGC)) { \
|
||||||
|
fprintf(stderr, "Error: Unable to get Unicode arguments.\n"); \
|
||||||
|
FREE_WARGV_AND_RETURN(-1); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
// Use this to get a Unicode argument (e.g. file path).
|
||||||
|
#define GET_WARGV(UNUSED, C) wargv[C]
|
||||||
|
// For cases where argv is shifted by one compared to wargv.
|
||||||
|
#define GET_WARGV_SHIFTED(UNUSED, C) wargv[(C) + 1]
|
||||||
|
#define GET_WARGV_OR_NULL() wargv
|
||||||
|
|
||||||
|
// Release resources. LocalFree() is needed after CommandLineToArgvW().
|
||||||
|
#define FREE_WARGV() LOCAL_FREE((W_CHAR** const)wargv)
|
||||||
|
#define LOCAL_FREE(WARGV) \
|
||||||
|
do { \
|
||||||
|
if ((WARGV) != NULL) LocalFree(WARGV); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define W_CHAR wchar_t // WCHAR without underscore might already be defined.
|
||||||
|
#define TO_W_CHAR(STR) (L##STR)
|
||||||
|
|
||||||
|
#define WFOPEN(ARG, OPT) _wfopen((const W_CHAR*)ARG, TO_W_CHAR(OPT))
|
||||||
|
|
||||||
|
#define WPRINTF(STR, ...) wprintf(TO_W_CHAR(STR), __VA_ARGS__)
|
||||||
|
#define WFPRINTF(STDERR, STR, ...) fwprintf(STDERR, TO_W_CHAR(STR), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define WSTRLEN(FILENAME) wcslen((const W_CHAR*)FILENAME)
|
||||||
|
#define WSTRCMP(FILENAME, STR) wcscmp((const W_CHAR*)FILENAME, TO_W_CHAR(STR))
|
||||||
|
#define WSTRRCHR(FILENAME, STR) wcsrchr((const W_CHAR*)FILENAME, TO_W_CHAR(STR))
|
||||||
|
#define WSNPRINTF(A, B, STR, ...) _snwprintf(A, B, TO_W_CHAR(STR), __VA_ARGS__)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Unicode file paths work as is on Unix platforms, and no extra work is done on
|
||||||
|
// Windows either if Unicode is disabled.
|
||||||
|
|
||||||
|
#define INIT_WARGV(ARGC, ARGV)
|
||||||
|
|
||||||
|
#define GET_WARGV(ARGV, C) (ARGV)[C]
|
||||||
|
#define GET_WARGV_SHIFTED(ARGV, C) (ARGV)[C]
|
||||||
|
#define GET_WARGV_OR_NULL() NULL
|
||||||
|
|
||||||
|
#define FREE_WARGV()
|
||||||
|
#define LOCAL_FREE(WARGV)
|
||||||
|
|
||||||
|
#define W_CHAR char
|
||||||
|
#define TO_W_CHAR(STR) (STR)
|
||||||
|
|
||||||
|
#define WFOPEN(ARG, OPT) fopen(ARG, OPT)
|
||||||
|
|
||||||
|
#define WPRINTF(STR, ...) printf(STR, __VA_ARGS__)
|
||||||
|
#define WFPRINTF(STDERR, STR, ...) fprintf(STDERR, STR, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define WSTRLEN(FILENAME) strlen(FILENAME)
|
||||||
|
#define WSTRCMP(FILENAME, STR) strcmp(FILENAME, STR)
|
||||||
|
#define WSTRRCHR(FILENAME, STR) strrchr(FILENAME, STR)
|
||||||
|
#define WSNPRINTF(A, B, STR, ...) snprintf(A, B, STR, __VA_ARGS__)
|
||||||
|
|
||||||
|
#endif // defined(_WIN32) && defined(_UNICODE)
|
||||||
|
|
||||||
|
// Don't forget to free wargv before returning (e.g. from main).
|
||||||
|
#define FREE_WARGV_AND_RETURN(VALUE) \
|
||||||
|
do { \
|
||||||
|
FREE_WARGV(); \
|
||||||
|
return (VALUE); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif // WEBP_EXAMPLES_UNICODE_H_
|
||||||
75
examples/unicode_gif.h
Normal file
75
examples/unicode_gif.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright 2018 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license
|
||||||
|
// that can be found in the COPYING file in the root of the source
|
||||||
|
// tree. An additional intellectual property rights grant can be found
|
||||||
|
// in the file PATENTS. All contributing project authors may
|
||||||
|
// be found in the AUTHORS file in the root of the source tree.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// giflib doesn't have a Unicode DGifOpenFileName(). Let's make one.
|
||||||
|
//
|
||||||
|
// Author: Yannis Guyon (yguyon@google.com)
|
||||||
|
|
||||||
|
#ifndef WEBP_EXAMPLES_UNICODE_GIF_H_
|
||||||
|
#define WEBP_EXAMPLES_UNICODE_GIF_H_
|
||||||
|
|
||||||
|
#include "./unicode.h"
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "webp/config.h" // For WEBP_HAVE_GIF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WEBP_HAVE_GIF)
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <fcntl.h> // Not standard, needed for _topen and flags.
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gif_lib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "./gifdec.h"
|
||||||
|
|
||||||
|
#if !defined(STDIN_FILENO)
|
||||||
|
#define STDIN_FILENO 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static GifFileType* DGifOpenFileUnicode(const W_CHAR* file_name, int* error) {
|
||||||
|
if (!WSTRCMP(file_name, "-")) {
|
||||||
|
#if LOCAL_GIF_PREREQ(5, 0)
|
||||||
|
return DGifOpenFileHandle(STDIN_FILENO, error);
|
||||||
|
#else
|
||||||
|
(void)error;
|
||||||
|
return DGifOpenFileHandle(STDIN_FILENO);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_UNICODE)
|
||||||
|
|
||||||
|
int file_handle = _wopen(file_name, _O_RDONLY | _O_BINARY);
|
||||||
|
if (file_handle == -1) {
|
||||||
|
if (error != NULL) *error = D_GIF_ERR_OPEN_FAILED;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LOCAL_GIF_PREREQ(5, 0)
|
||||||
|
return DGifOpenFileHandle(file_handle, error);
|
||||||
|
#else
|
||||||
|
return DGifOpenFileHandle(file_handle);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if LOCAL_GIF_PREREQ(5, 0)
|
||||||
|
return DGifOpenFileName(file_name, error);
|
||||||
|
#else
|
||||||
|
return DGifOpenFileName(file_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // defined(_WIN32) && defined(_UNICODE)
|
||||||
|
// DGifCloseFile() is called later.
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined(WEBP_HAVE_GIF)
|
||||||
|
|
||||||
|
#endif // WEBP_EXAMPLES_UNICODE_GIF_H_
|
||||||
229
examples/vwebp.c
229
examples/vwebp.c
@@ -14,6 +14,10 @@
|
|||||||
#include "webp/config.h"
|
#include "webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__unix__) || defined(__CYGWIN__)
|
||||||
|
#define _POSIX_C_SOURCE 200112L // for setenv
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -36,7 +40,9 @@
|
|||||||
#include "webp/decode.h"
|
#include "webp/decode.h"
|
||||||
#include "webp/demux.h"
|
#include "webp/demux.h"
|
||||||
|
|
||||||
#include "./example_util.h"
|
#include "../examples/example_util.h"
|
||||||
|
#include "../imageio/imageio_util.h"
|
||||||
|
#include "./unicode.h"
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
@@ -49,7 +55,9 @@ static struct {
|
|||||||
int done;
|
int done;
|
||||||
int decoding_error;
|
int decoding_error;
|
||||||
int print_info;
|
int print_info;
|
||||||
|
int only_deltas;
|
||||||
int use_color_profile;
|
int use_color_profile;
|
||||||
|
int draw_anim_background_color;
|
||||||
|
|
||||||
int canvas_width, canvas_height;
|
int canvas_width, canvas_height;
|
||||||
int loop_count;
|
int loop_count;
|
||||||
@@ -63,6 +71,7 @@ static struct {
|
|||||||
WebPIterator curr_frame;
|
WebPIterator curr_frame;
|
||||||
WebPIterator prev_frame;
|
WebPIterator prev_frame;
|
||||||
WebPChunkIterator iccp;
|
WebPChunkIterator iccp;
|
||||||
|
int viewport_width, viewport_height;
|
||||||
} kParams;
|
} kParams;
|
||||||
|
|
||||||
static void ClearPreviousPic(void) {
|
static void ClearPreviousPic(void) {
|
||||||
@@ -198,6 +207,11 @@ static void decode_callback(int what) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
duration = curr->duration;
|
duration = curr->duration;
|
||||||
|
// Behavior copied from Chrome, cf:
|
||||||
|
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/
|
||||||
|
// platform/graphics/DeferredImageDecoder.cpp?
|
||||||
|
// rcl=b4c33049f096cd283f32be9a58b9a9e768227c26&l=246
|
||||||
|
if (duration <= 10) duration = 100;
|
||||||
}
|
}
|
||||||
if (!Decode()) {
|
if (!Decode()) {
|
||||||
kParams.decoding_error = 1;
|
kParams.decoding_error = 1;
|
||||||
@@ -213,6 +227,9 @@ static void decode_callback(int what) {
|
|||||||
// Callbacks
|
// Callbacks
|
||||||
|
|
||||||
static void HandleKey(unsigned char key, int pos_x, int pos_y) {
|
static void HandleKey(unsigned char key, int pos_x, int pos_y) {
|
||||||
|
// Note: rescaling the window or toggling some features during an animation
|
||||||
|
// generates visual artifacts. This is not fixed because refreshing the frame
|
||||||
|
// may require rendering the whole animation from start till current frame.
|
||||||
(void)pos_x;
|
(void)pos_x;
|
||||||
(void)pos_y;
|
(void)pos_y;
|
||||||
if (key == 'q' || key == 'Q' || key == 27 /* Esc */) {
|
if (key == 'q' || key == 'Q' || key == 27 /* Esc */) {
|
||||||
@@ -240,20 +257,31 @@ static void HandleKey(unsigned char key, int pos_x, int pos_y) {
|
|||||||
glutPostRedisplay();
|
glutPostRedisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (key == 'b') {
|
||||||
|
kParams.draw_anim_background_color = 1 - kParams.draw_anim_background_color;
|
||||||
|
if (!kParams.has_animation) ClearPreviousFrame();
|
||||||
|
glutPostRedisplay();
|
||||||
} else if (key == 'i') {
|
} else if (key == 'i') {
|
||||||
kParams.print_info = 1 - kParams.print_info;
|
kParams.print_info = 1 - kParams.print_info;
|
||||||
|
if (!kParams.has_animation) ClearPreviousFrame();
|
||||||
|
glutPostRedisplay();
|
||||||
|
} else if (key == 'd') {
|
||||||
|
kParams.only_deltas = 1 - kParams.only_deltas;
|
||||||
glutPostRedisplay();
|
glutPostRedisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleReshape(int width, int height) {
|
static void HandleReshape(int width, int height) {
|
||||||
// TODO(skal): proper handling of resize, esp. for large pictures.
|
// Note: reshape doesn't preserve aspect ratio, and might
|
||||||
// + key control of the zoom.
|
// be handling larger-than-screen pictures incorrectly.
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
kParams.viewport_width = width;
|
||||||
|
kParams.viewport_height = height;
|
||||||
|
if (!kParams.has_animation) ClearPreviousFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintString(const char* const text) {
|
static void PrintString(const char* const text) {
|
||||||
@@ -265,7 +293,7 @@ static void PrintString(const char* const text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static float GetColorf(uint32_t color, int shift) {
|
static float GetColorf(uint32_t color, int shift) {
|
||||||
return (color >> shift) / 255.f;
|
return ((color >> shift) & 0xff) / 255.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawCheckerBoard(void) {
|
static void DrawCheckerBoard(void) {
|
||||||
@@ -288,6 +316,43 @@ static void DrawCheckerBoard(void) {
|
|||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DrawBackground(void) {
|
||||||
|
// Whole window cleared with clear color, checkerboard rendered on top of it.
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
DrawCheckerBoard();
|
||||||
|
|
||||||
|
// ANIM background color rendered (blend) on top. Default is white for still
|
||||||
|
// images (without ANIM chunk). glClear() can't be used for that (no blend).
|
||||||
|
if (kParams.draw_anim_background_color) {
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glColor4f(GetColorf(kParams.bg_color, 16), // BGRA from spec
|
||||||
|
GetColorf(kParams.bg_color, 8),
|
||||||
|
GetColorf(kParams.bg_color, 0),
|
||||||
|
GetColorf(kParams.bg_color, 24));
|
||||||
|
glRecti(-1, -1, +1, +1);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw background in a scissored rectangle.
|
||||||
|
static void DrawBackgroundScissored(int window_x, int window_y, int frame_w,
|
||||||
|
int frame_h) {
|
||||||
|
// Only update the requested area, not the whole canvas.
|
||||||
|
window_x = window_x * kParams.viewport_width / kParams.canvas_width;
|
||||||
|
window_y = window_y * kParams.viewport_height / kParams.canvas_height;
|
||||||
|
frame_w = frame_w * kParams.viewport_width / kParams.canvas_width;
|
||||||
|
frame_h = frame_h * kParams.viewport_height / kParams.canvas_height;
|
||||||
|
|
||||||
|
// glScissor() takes window coordinates (0,0 at bottom left).
|
||||||
|
window_y = kParams.viewport_height - window_y - frame_h;
|
||||||
|
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glScissor(window_x, window_y, frame_w, frame_h);
|
||||||
|
DrawBackground();
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
static void HandleDisplay(void) {
|
static void HandleDisplay(void) {
|
||||||
const WebPDecBuffer* const pic = kParams.pic;
|
const WebPDecBuffer* const pic = kParams.pic;
|
||||||
const WebPIterator* const curr = &kParams.curr_frame;
|
const WebPIterator* const curr = &kParams.curr_frame;
|
||||||
@@ -295,42 +360,30 @@ static void HandleDisplay(void) {
|
|||||||
GLfloat xoff, yoff;
|
GLfloat xoff, yoff;
|
||||||
if (pic == NULL) return;
|
if (pic == NULL) return;
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glPixelZoom(1, -1);
|
glPixelZoom((GLfloat)(+1. / kParams.canvas_width * kParams.viewport_width),
|
||||||
|
(GLfloat)(-1. / kParams.canvas_height * kParams.viewport_height));
|
||||||
xoff = (GLfloat)(2. * curr->x_offset / kParams.canvas_width);
|
xoff = (GLfloat)(2. * curr->x_offset / kParams.canvas_width);
|
||||||
yoff = (GLfloat)(2. * curr->y_offset / kParams.canvas_height);
|
yoff = (GLfloat)(2. * curr->y_offset / kParams.canvas_height);
|
||||||
glRasterPos2f(-1.f + xoff, 1.f - yoff);
|
glRasterPos2f(-1.f + xoff, 1.f - yoff);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4);
|
||||||
|
|
||||||
if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ||
|
if (kParams.only_deltas) {
|
||||||
curr->blend_method == WEBP_MUX_NO_BLEND) {
|
DrawBackground();
|
||||||
// TODO(later): these offsets and those above should factor in window size.
|
} else {
|
||||||
// they will be incorrect if the window is resized.
|
// The rectangle of the previous frame might be different than the current
|
||||||
// glScissor() takes window coordinates (0,0 at bottom left).
|
// frame, so we may need to DrawBackgroundScissored for both.
|
||||||
int window_x, window_y;
|
|
||||||
int frame_w, frame_h;
|
|
||||||
if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
|
if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
|
||||||
// Clear the previous frame rectangle.
|
// Clear the previous frame rectangle.
|
||||||
window_x = prev->x_offset;
|
DrawBackgroundScissored(prev->x_offset, prev->y_offset, prev->width,
|
||||||
window_y = kParams.canvas_height - prev->y_offset - prev->height;
|
prev->height);
|
||||||
frame_w = prev->width;
|
}
|
||||||
frame_h = prev->height;
|
if (curr->blend_method == WEBP_MUX_NO_BLEND) {
|
||||||
} else { // curr->blend_method == WEBP_MUX_NO_BLEND.
|
// We simulate no-blending behavior by first clearing the current frame
|
||||||
// We simulate no-blending behavior by first clearing the current frame
|
// rectangle and then alpha-blending against it.
|
||||||
// rectangle (to a checker-board) and then alpha-blending against it.
|
DrawBackgroundScissored(curr->x_offset, curr->y_offset, curr->width,
|
||||||
window_x = curr->x_offset;
|
curr->height);
|
||||||
window_y = kParams.canvas_height - curr->y_offset - curr->height;
|
|
||||||
frame_w = curr->width;
|
|
||||||
frame_h = curr->height;
|
|
||||||
}
|
}
|
||||||
glEnable(GL_SCISSOR_TEST);
|
|
||||||
// Only update the requested area, not the whole canvas.
|
|
||||||
glScissor(window_x, window_y, frame_w, frame_h);
|
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT); // use clear color
|
|
||||||
DrawCheckerBoard();
|
|
||||||
|
|
||||||
glDisable(GL_SCISSOR_TEST);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*prev = *curr;
|
*prev = *curr;
|
||||||
@@ -357,71 +410,97 @@ static void HandleDisplay(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
#if defined(__APPLE__) || defined(_WIN32)
|
||||||
glFlush();
|
glFlush();
|
||||||
|
#else
|
||||||
|
glutSwapBuffers();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void StartDisplay(void) {
|
static void StartDisplay(void) {
|
||||||
const int width = kParams.canvas_width;
|
int width = kParams.canvas_width;
|
||||||
const int height = kParams.canvas_height;
|
int height = kParams.canvas_height;
|
||||||
|
int screen_width, screen_height;
|
||||||
|
// TODO(webp:365) GLUT_DOUBLE results in flickering / old frames to be
|
||||||
|
// partially displayed with animated webp + alpha.
|
||||||
|
#if defined(__APPLE__) || defined(_WIN32)
|
||||||
glutInitDisplayMode(GLUT_RGBA);
|
glutInitDisplayMode(GLUT_RGBA);
|
||||||
|
#else
|
||||||
|
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
|
||||||
|
#endif
|
||||||
|
screen_width = glutGet(GLUT_SCREEN_WIDTH);
|
||||||
|
screen_height = glutGet(GLUT_SCREEN_HEIGHT);
|
||||||
|
if (width > screen_width || height > screen_height) {
|
||||||
|
if (width > screen_width) {
|
||||||
|
height = (height * screen_width + width - 1) / width;
|
||||||
|
width = screen_width;
|
||||||
|
}
|
||||||
|
if (height > screen_height) {
|
||||||
|
width = (width * screen_height + height - 1) / height;
|
||||||
|
height = screen_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
glutInitWindowSize(width, height);
|
glutInitWindowSize(width, height);
|
||||||
glutCreateWindow("WebP viewer");
|
glutCreateWindow("WebP viewer");
|
||||||
glutDisplayFunc(HandleDisplay);
|
glutDisplayFunc(HandleDisplay);
|
||||||
|
glutReshapeFunc(HandleReshape);
|
||||||
glutIdleFunc(NULL);
|
glutIdleFunc(NULL);
|
||||||
glutKeyboardFunc(HandleKey);
|
glutKeyboardFunc(HandleKey);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glClearColor(GetColorf(kParams.bg_color, 0),
|
glClearColor(0, 0, 0, 0); // window will be cleared to black (no blend)
|
||||||
GetColorf(kParams.bg_color, 8),
|
DrawBackground();
|
||||||
GetColorf(kParams.bg_color, 16),
|
|
||||||
GetColorf(kParams.bg_color, 24));
|
|
||||||
HandleReshape(width, height);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
DrawCheckerBoard();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Main
|
// Main
|
||||||
|
|
||||||
static void Help(void) {
|
static void Help(void) {
|
||||||
printf("Usage: vwebp in_file [options]\n\n"
|
printf(
|
||||||
"Decodes the WebP image file and visualize it using OpenGL\n"
|
"Usage: vwebp in_file [options]\n\n"
|
||||||
"Options are:\n"
|
"Decodes the WebP image file and visualize it using OpenGL\n"
|
||||||
" -version .... print version number and exit\n"
|
"Options are:\n"
|
||||||
" -noicc ....... don't use the icc profile if present\n"
|
" -version ..... print version number and exit\n"
|
||||||
" -nofancy ..... don't use the fancy YUV420 upscaler\n"
|
" -noicc ....... don't use the icc profile if present\n"
|
||||||
" -nofilter .... disable in-loop filtering\n"
|
" -nofancy ..... don't use the fancy YUV420 upscaler\n"
|
||||||
" -dither <int> dithering strength (0..100), default=50\n"
|
" -nofilter .... disable in-loop filtering\n"
|
||||||
" -noalphadither disable alpha plane dithering\n"
|
" -dither <int> dithering strength (0..100), default=50\n"
|
||||||
" -mt .......... use multi-threading\n"
|
" -noalphadither disable alpha plane dithering\n"
|
||||||
" -info ........ print info\n"
|
" -usebgcolor .. display background color\n"
|
||||||
" -h ....... this help message\n"
|
" -mt .......... use multi-threading\n"
|
||||||
"\n"
|
" -info ........ print info\n"
|
||||||
"Keyboard shortcuts:\n"
|
" -h ........... this help message\n"
|
||||||
" 'c' ................ toggle use of color profile\n"
|
"\n"
|
||||||
" 'i' ................ overlay file information\n"
|
"Keyboard shortcuts:\n"
|
||||||
" 'q' / 'Q' / ESC .... quit\n"
|
" 'c' ................ toggle use of color profile\n"
|
||||||
);
|
" 'b' ................ toggle background color display\n"
|
||||||
|
" 'i' ................ overlay file information\n"
|
||||||
|
" 'd' ................ disable blending & disposal (debug)\n"
|
||||||
|
" 'q' / 'Q' / ESC .... quit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
int c;
|
int c;
|
||||||
WebPDecoderConfig* const config = &kParams.config;
|
WebPDecoderConfig* const config = &kParams.config;
|
||||||
WebPIterator* const curr = &kParams.curr_frame;
|
WebPIterator* const curr = &kParams.curr_frame;
|
||||||
|
|
||||||
|
INIT_WARGV(argc, argv);
|
||||||
|
|
||||||
if (!WebPInitDecoderConfig(config)) {
|
if (!WebPInitDecoderConfig(config)) {
|
||||||
fprintf(stderr, "Library version mismatch!\n");
|
fprintf(stderr, "Library version mismatch!\n");
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
config->options.dithering_strength = 50;
|
config->options.dithering_strength = 50;
|
||||||
config->options.alpha_dithering_strength = 100;
|
config->options.alpha_dithering_strength = 100;
|
||||||
kParams.use_color_profile = 1;
|
kParams.use_color_profile = 1;
|
||||||
|
// Background color hidden by default to see transparent areas.
|
||||||
|
kParams.draw_anim_background_color = 0;
|
||||||
|
|
||||||
for (c = 1; c < argc; ++c) {
|
for (c = 1; c < argc; ++c) {
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||||
Help();
|
Help();
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-noicc")) {
|
} else if (!strcmp(argv[c], "-noicc")) {
|
||||||
kParams.use_color_profile = 0;
|
kParams.use_color_profile = 0;
|
||||||
} else if (!strcmp(argv[c], "-nofancy")) {
|
} else if (!strcmp(argv[c], "-nofancy")) {
|
||||||
@@ -430,6 +509,8 @@ int main(int argc, char *argv[]) {
|
|||||||
config->options.bypass_filtering = 1;
|
config->options.bypass_filtering = 1;
|
||||||
} else if (!strcmp(argv[c], "-noalphadither")) {
|
} else if (!strcmp(argv[c], "-noalphadither")) {
|
||||||
config->options.alpha_dithering_strength = 0;
|
config->options.alpha_dithering_strength = 0;
|
||||||
|
} else if (!strcmp(argv[c], "-usebgcolor")) {
|
||||||
|
kParams.draw_anim_background_color = 1;
|
||||||
} else if (!strcmp(argv[c], "-dither") && c + 1 < argc) {
|
} else if (!strcmp(argv[c], "-dither") && c + 1 < argc) {
|
||||||
config->options.dithering_strength =
|
config->options.dithering_strength =
|
||||||
ExUtilGetInt(argv[++c], 0, &parse_error);
|
ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
@@ -442,34 +523,34 @@ int main(int argc, char *argv[]) {
|
|||||||
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
(dec_version >> 16) & 0xff, (dec_version >> 8) & 0xff,
|
||||||
dec_version & 0xff, (dmux_version >> 16) & 0xff,
|
dec_version & 0xff, (dmux_version >> 16) & 0xff,
|
||||||
(dmux_version >> 8) & 0xff, dmux_version & 0xff);
|
(dmux_version >> 8) & 0xff, dmux_version & 0xff);
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-mt")) {
|
} else if (!strcmp(argv[c], "-mt")) {
|
||||||
config->options.use_threads = 1;
|
config->options.use_threads = 1;
|
||||||
} else if (!strcmp(argv[c], "--")) {
|
} else if (!strcmp(argv[c], "--")) {
|
||||||
if (c < argc - 1) kParams.file_name = argv[++c];
|
if (c < argc - 1) kParams.file_name = (const char*)GET_WARGV(argv, ++c);
|
||||||
break;
|
break;
|
||||||
} else if (argv[c][0] == '-') {
|
} else if (argv[c][0] == '-') {
|
||||||
printf("Unknown option '%s'\n", argv[c]);
|
printf("Unknown option '%s'\n", argv[c]);
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
} else {
|
} else {
|
||||||
kParams.file_name = argv[c];
|
kParams.file_name = (const char*)GET_WARGV(argv, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parse_error) {
|
if (parse_error) {
|
||||||
Help();
|
Help();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kParams.file_name == NULL) {
|
if (kParams.file_name == NULL) {
|
||||||
printf("missing input file!!\n");
|
printf("missing input file!!\n");
|
||||||
Help();
|
Help();
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExUtilReadFile(kParams.file_name,
|
if (!ImgIoUtilReadFile(kParams.file_name,
|
||||||
&kParams.data.bytes, &kParams.data.size)) {
|
&kParams.data.bytes, &kParams.data.size)) {
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,10 +565,6 @@ int main(int argc, char *argv[]) {
|
|||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WebPDemuxGetI(kParams.dmux, WEBP_FF_FORMAT_FLAGS) & FRAGMENTS_FLAG) {
|
|
||||||
fprintf(stderr, "Image fragments are not supported for now!\n");
|
|
||||||
goto Error;
|
|
||||||
}
|
|
||||||
kParams.canvas_width = WebPDemuxGetI(kParams.dmux, WEBP_FF_CANVAS_WIDTH);
|
kParams.canvas_width = WebPDemuxGetI(kParams.dmux, WEBP_FF_CANVAS_WIDTH);
|
||||||
kParams.canvas_height = WebPDemuxGetI(kParams.dmux, WEBP_FF_CANVAS_HEIGHT);
|
kParams.canvas_height = WebPDemuxGetI(kParams.dmux, WEBP_FF_CANVAS_HEIGHT);
|
||||||
if (kParams.print_info) {
|
if (kParams.print_info) {
|
||||||
@@ -544,16 +621,16 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// Should only be reached when using FREEGLUT:
|
// Should only be reached when using FREEGLUT:
|
||||||
ClearParams();
|
ClearParams();
|
||||||
return 0;
|
FREE_WARGV_AND_RETURN(0);
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
ClearParams();
|
ClearParams();
|
||||||
return -1;
|
FREE_WARGV_AND_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // !WEBP_HAVE_GL
|
#else // !WEBP_HAVE_GL
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]);
|
fprintf(stderr, "OpenGL support not enabled in %s.\n", argv[0]);
|
||||||
(void)argc;
|
(void)argc;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
// Copyright 2014 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.
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// WebP decode.
|
|
||||||
|
|
||||||
#include "./webpdec.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "webp/decode.h"
|
|
||||||
#include "webp/encode.h"
|
|
||||||
#include "./example_util.h"
|
|
||||||
#include "./metadata.h"
|
|
||||||
|
|
||||||
int ReadWebP(const uint8_t* const data, size_t data_size,
|
|
||||||
WebPPicture* const pic,
|
|
||||||
int keep_alpha, Metadata* const metadata) {
|
|
||||||
int ok = 0;
|
|
||||||
VP8StatusCode status = VP8_STATUS_OK;
|
|
||||||
WebPDecoderConfig config;
|
|
||||||
WebPDecBuffer* const output_buffer = &config.output;
|
|
||||||
WebPBitstreamFeatures* const bitstream = &config.input;
|
|
||||||
|
|
||||||
// TODO(jzern): add Exif/XMP/ICC extraction.
|
|
||||||
if (metadata != NULL) {
|
|
||||||
fprintf(stderr, "Warning: metadata extraction from WebP is unsupported.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!WebPInitDecoderConfig(&config)) {
|
|
||||||
fprintf(stderr, "Library version mismatch!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = WebPGetFeatures(data, data_size, bitstream);
|
|
||||||
if (status != VP8_STATUS_OK) {
|
|
||||||
ExUtilPrintWebPError("input data", status);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const int has_alpha = keep_alpha && bitstream->has_alpha;
|
|
||||||
// TODO(skal): use MODE_YUV(A), depending on the expected
|
|
||||||
// input pic->use_argb. This would save some conversion steps.
|
|
||||||
output_buffer->colorspace = has_alpha ? MODE_RGBA : MODE_RGB;
|
|
||||||
|
|
||||||
status = ExUtilDecodeWebP(data, data_size, 0, &config);
|
|
||||||
if (status == VP8_STATUS_OK) {
|
|
||||||
const uint8_t* const rgba = output_buffer->u.RGBA.rgba;
|
|
||||||
const int stride = output_buffer->u.RGBA.stride;
|
|
||||||
pic->width = output_buffer->width;
|
|
||||||
pic->height = output_buffer->height;
|
|
||||||
ok = has_alpha ? WebPPictureImportRGBA(pic, rgba, stride)
|
|
||||||
: WebPPictureImportRGB(pic, rgba, stride);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != VP8_STATUS_OK) {
|
|
||||||
ExUtilPrintWebPError("input data", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
WebPFreeDecBuffer(output_buffer);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// Copyright 2014 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.
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// WebP decode.
|
|
||||||
|
|
||||||
#ifndef WEBP_EXAMPLES_WEBPDEC_H_
|
|
||||||
#define WEBP_EXAMPLES_WEBPDEC_H_
|
|
||||||
|
|
||||||
#include "webp/types.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Metadata;
|
|
||||||
struct WebPPicture;
|
|
||||||
|
|
||||||
// Reads a WebP from 'in_file', returning the decoded output in 'pic'.
|
|
||||||
// Output is RGBA or YUVA, depending on pic->use_argb value.
|
|
||||||
// If 'keep_alpha' is true and the WebP has an alpha channel, the output is RGBA
|
|
||||||
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
|
||||||
// Returns true on success.
|
|
||||||
int ReadWebP(const uint8_t* const data, size_t data_size,
|
|
||||||
struct WebPPicture* const pic,
|
|
||||||
int keep_alpha, struct Metadata* const metadata);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // WEBP_EXAMPLES_WEBPDEC_H_
|
|
||||||
1180
examples/webpinfo.c
Normal file
1180
examples/webpinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
44
extras/Makefile.am
Normal file
44
extras/Makefile.am
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir)
|
||||||
|
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
|
||||||
|
noinst_LTLIBRARIES = libwebpextras.la
|
||||||
|
|
||||||
|
noinst_HEADERS =
|
||||||
|
noinst_HEADERS += ../src/webp/types.h
|
||||||
|
|
||||||
|
libwebpextras_la_SOURCES =
|
||||||
|
libwebpextras_la_SOURCES += extras.c extras.h quality_estimate.c
|
||||||
|
|
||||||
|
libwebpextras_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
libwebpextras_la_LDFLAGS = -lm
|
||||||
|
libwebpextras_la_LIBADD = ../src/libwebp.la
|
||||||
|
|
||||||
|
noinst_PROGRAMS =
|
||||||
|
noinst_PROGRAMS += webp_quality
|
||||||
|
if BUILD_DEMUX
|
||||||
|
noinst_PROGRAMS += get_disto
|
||||||
|
endif
|
||||||
|
if BUILD_VWEBP_SDL
|
||||||
|
noinst_PROGRAMS += vwebp_sdl
|
||||||
|
endif
|
||||||
|
|
||||||
|
get_disto_SOURCES = get_disto.c
|
||||||
|
get_disto_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
get_disto_LDADD =
|
||||||
|
get_disto_LDADD += ../imageio/libimageio_util.la
|
||||||
|
get_disto_LDADD += ../imageio/libimagedec.la
|
||||||
|
get_disto_LDADD += ../src/libwebp.la
|
||||||
|
get_disto_LDADD += $(PNG_LIBS) $(JPEG_LIBS) $(TIFF_LIBS)
|
||||||
|
|
||||||
|
webp_quality_SOURCES = webp_quality.c
|
||||||
|
webp_quality_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
webp_quality_LDADD =
|
||||||
|
webp_quality_LDADD += ../imageio/libimageio_util.la
|
||||||
|
webp_quality_LDADD += libwebpextras.la
|
||||||
|
webp_quality_LDADD += ../src/libwebp.la
|
||||||
|
|
||||||
|
vwebp_sdl_SOURCES = vwebp_sdl.c webp_to_sdl.c webp_to_sdl.h
|
||||||
|
vwebp_sdl_CPPFLAGS = $(AM_CPPFLAGS) $(SDL_INCLUDES)
|
||||||
|
vwebp_sdl_LDADD =
|
||||||
|
vwebp_sdl_LDADD += ../imageio/libimageio_util.la
|
||||||
|
vwebp_sdl_LDADD += ../src/libwebp.la
|
||||||
|
vwebp_sdl_LDADD += $(SDL_LIBS)
|
||||||
@@ -10,13 +10,16 @@
|
|||||||
// Additional WebP utilities.
|
// Additional WebP utilities.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "../webp/extras.h"
|
#include "extras/extras.h"
|
||||||
|
#include "webp/format_constants.h"
|
||||||
|
#include "src/dsp/dsp.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define XTRA_MAJ_VERSION 0
|
#define XTRA_MAJ_VERSION 1
|
||||||
#define XTRA_MIN_VERSION 0
|
#define XTRA_MIN_VERSION 2
|
||||||
#define XTRA_REV_VERSION 0
|
#define XTRA_REV_VERSION 1
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -46,15 +49,16 @@ int WebPImportGray(const uint8_t* gray_data, WebPPicture* pic) {
|
|||||||
|
|
||||||
int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) {
|
int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) {
|
||||||
int x, y;
|
int x, y;
|
||||||
|
uint32_t* dst;
|
||||||
if (pic == NULL || rgb565 == NULL) return 0;
|
if (pic == NULL || rgb565 == NULL) return 0;
|
||||||
pic->colorspace = WEBP_YUV420;
|
pic->colorspace = WEBP_YUV420;
|
||||||
pic->use_argb = 1;
|
pic->use_argb = 1;
|
||||||
if (!WebPPictureAlloc(pic)) return 0;
|
if (!WebPPictureAlloc(pic)) return 0;
|
||||||
|
dst = pic->argb;
|
||||||
for (y = 0; y < pic->height; ++y) {
|
for (y = 0; y < pic->height; ++y) {
|
||||||
const int width = pic->width;
|
const int width = pic->width;
|
||||||
uint32_t* dst = pic->argb + y * pic->argb_stride;
|
|
||||||
for (x = 0; x < width; ++x) {
|
for (x = 0; x < width; ++x) {
|
||||||
#ifdef WEBP_SWAP_16BIT_CSP
|
#if defined(WEBP_SWAP_16BIT_CSP) && (WEBP_SWAP_16BIT_CSP == 1)
|
||||||
const uint32_t rg = rgb565[2 * x + 1];
|
const uint32_t rg = rgb565[2 * x + 1];
|
||||||
const uint32_t gb = rgb565[2 * x + 0];
|
const uint32_t gb = rgb565[2 * x + 0];
|
||||||
#else
|
#else
|
||||||
@@ -68,24 +72,26 @@ int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic) {
|
|||||||
r = r | (r >> 5);
|
r = r | (r >> 5);
|
||||||
g = g | (g >> 6);
|
g = g | (g >> 6);
|
||||||
b = b | (b >> 5);
|
b = b | (b >> 5);
|
||||||
dst[x] = (r << 16) | (g << 8) | b;
|
dst[x] = (0xffu << 24) | (r << 16) | (g << 8) | b;
|
||||||
}
|
}
|
||||||
rgb565 += 2 * width;
|
rgb565 += 2 * width;
|
||||||
|
dst += pic->argb_stride;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) {
|
int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) {
|
||||||
int x, y;
|
int x, y;
|
||||||
|
uint32_t* dst;
|
||||||
if (pic == NULL || rgb4444 == NULL) return 0;
|
if (pic == NULL || rgb4444 == NULL) return 0;
|
||||||
pic->colorspace = WEBP_YUV420;
|
pic->colorspace = WEBP_YUV420;
|
||||||
pic->use_argb = 1;
|
pic->use_argb = 1;
|
||||||
if (!WebPPictureAlloc(pic)) return 0;
|
if (!WebPPictureAlloc(pic)) return 0;
|
||||||
|
dst = pic->argb;
|
||||||
for (y = 0; y < pic->height; ++y) {
|
for (y = 0; y < pic->height; ++y) {
|
||||||
const int width = pic->width;
|
const int width = pic->width;
|
||||||
uint32_t* dst = pic->argb + y * pic->argb_stride;
|
|
||||||
for (x = 0; x < width; ++x) {
|
for (x = 0; x < width; ++x) {
|
||||||
#ifdef WEBP_SWAP_16BIT_CSP
|
#if defined(WEBP_SWAP_16BIT_CSP) && (WEBP_SWAP_16BIT_CSP == 1)
|
||||||
const uint32_t rg = rgb4444[2 * x + 1];
|
const uint32_t rg = rgb4444[2 * x + 1];
|
||||||
const uint32_t ba = rgb4444[2 * x + 0];
|
const uint32_t ba = rgb4444[2 * x + 0];
|
||||||
#else
|
#else
|
||||||
@@ -104,6 +110,51 @@ int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic) {
|
|||||||
dst[x] = (a << 24) | (r << 16) | (g << 8) | b;
|
dst[x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||||
}
|
}
|
||||||
rgb4444 += 2 * width;
|
rgb4444 += 2 * width;
|
||||||
|
dst += pic->argb_stride;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride,
|
||||||
|
const uint32_t palette[], int palette_size,
|
||||||
|
WebPPicture* pic) {
|
||||||
|
int x, y;
|
||||||
|
uint32_t* dst;
|
||||||
|
// 256 as the input buffer is uint8_t.
|
||||||
|
assert(MAX_PALETTE_SIZE <= 256);
|
||||||
|
if (pic == NULL || indexed == NULL || indexed_stride < pic->width ||
|
||||||
|
palette == NULL || palette_size > MAX_PALETTE_SIZE || palette_size <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pic->use_argb = 1;
|
||||||
|
if (!WebPPictureAlloc(pic)) return 0;
|
||||||
|
dst = pic->argb;
|
||||||
|
for (y = 0; y < pic->height; ++y) {
|
||||||
|
for (x = 0; x < pic->width; ++x) {
|
||||||
|
// Make sure we are within the palette.
|
||||||
|
if (indexed[x] >= palette_size) {
|
||||||
|
WebPPictureFree(pic);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dst[x] = palette[indexed[x]];
|
||||||
|
}
|
||||||
|
indexed += indexed_stride;
|
||||||
|
dst += pic->argb_stride;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int WebPUnmultiplyARGB(WebPPicture* pic) {
|
||||||
|
int y;
|
||||||
|
uint32_t* dst;
|
||||||
|
if (pic == NULL || pic->use_argb != 1 || pic->argb == NULL) return 0;
|
||||||
|
WebPInitAlphaProcessing();
|
||||||
|
dst = pic->argb;
|
||||||
|
for (y = 0; y < pic->height; ++y) {
|
||||||
|
WebPMultARGBRow(dst, pic->width, /*inverse=*/1);
|
||||||
|
dst += pic->argb_stride;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
77
extras/extras.h
Normal file
77
extras/extras.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2015 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_EXTRAS_EXTRAS_H_
|
||||||
|
#define WEBP_EXTRAS_EXTRAS_H_
|
||||||
|
|
||||||
|
#include "webp/types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "webp/encode.h"
|
||||||
|
|
||||||
|
#define WEBP_EXTRAS_ABI_VERSION 0x0002 // MAJOR(8b) + MINOR(8b)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Returns the version number of the extras library, packed in hexadecimal using
|
||||||
|
// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.
|
||||||
|
WEBP_EXTERN int WebPGetExtrasVersion(void);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Ad-hoc colorspace importers.
|
||||||
|
|
||||||
|
// Import luma sample (gray scale image) into 'picture'. The 'picture'
|
||||||
|
// width and height must be set prior to calling this function.
|
||||||
|
WEBP_EXTERN int WebPImportGray(const uint8_t* gray, WebPPicture* picture);
|
||||||
|
|
||||||
|
// Import rgb sample in RGB565 packed format into 'picture'. The 'picture'
|
||||||
|
// width and height must be set prior to calling this function.
|
||||||
|
WEBP_EXTERN int WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic);
|
||||||
|
|
||||||
|
// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture'
|
||||||
|
// width and height must be set prior to calling this function.
|
||||||
|
WEBP_EXTERN int WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic);
|
||||||
|
|
||||||
|
// Import a color mapped image. The number of colors is less or equal to
|
||||||
|
// MAX_PALETTE_SIZE. 'pic' must have been initialized. Its content, if any,
|
||||||
|
// will be discarded. Returns 'false' in case of error, or if indexed[] contains
|
||||||
|
// invalid indices.
|
||||||
|
WEBP_EXTERN int
|
||||||
|
WebPImportColorMappedARGB(const uint8_t* indexed, int indexed_stride,
|
||||||
|
const uint32_t palette[], int palette_size,
|
||||||
|
WebPPicture* pic);
|
||||||
|
|
||||||
|
// Convert the ARGB content of 'pic' from associated to unassociated.
|
||||||
|
// 'pic' can be for instance the result of calling of some WebPPictureImportXXX
|
||||||
|
// functions, with pic->use_argb set to 'true'. It is assumed (and not checked)
|
||||||
|
// that the pre-multiplied r/g/b values as less or equal than the alpha value.
|
||||||
|
// Return false in case of error (invalid parameter, ...).
|
||||||
|
WEBP_EXTERN int WebPUnmultiplyARGB(WebPPicture* pic);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Parse a bitstream, search for VP8 (lossy) header and report a
|
||||||
|
// rough estimation of the quality factor used for compressing the bitstream.
|
||||||
|
// If the bitstream is in lossless format, the special value '101' is returned.
|
||||||
|
// Otherwise (lossy bitstream), the returned value is in the range [0..100].
|
||||||
|
// Any error (invalid bitstream, animated WebP, incomplete header, etc.)
|
||||||
|
// will return a value of -1.
|
||||||
|
WEBP_EXTERN int VP8EstimateQuality(const uint8_t* const data, size_t size);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WEBP_EXTRAS_EXTRAS_H_
|
||||||
355
extras/get_disto.c
Normal file
355
extras/get_disto.c
Normal file
@@ -0,0 +1,355 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Simple tool to load two webp/png/jpg/tiff files and compute PSNR/SSIM.
|
||||||
|
// This is mostly a wrapper around WebPPictureDistortion().
|
||||||
|
//
|
||||||
|
/*
|
||||||
|
gcc -o get_disto get_disto.c -O3 -I../ -L../examples -L../imageio \
|
||||||
|
-lexample_util -limageio_util -limagedec -lwebp -L/opt/local/lib \
|
||||||
|
-lpng -lz -ljpeg -ltiff -lm -lpthread
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "webp/encode.h"
|
||||||
|
#include "imageio/image_dec.h"
|
||||||
|
#include "imageio/imageio_util.h"
|
||||||
|
#include "../examples/unicode.h"
|
||||||
|
|
||||||
|
static size_t ReadPicture(const char* const filename, WebPPicture* const pic,
|
||||||
|
int keep_alpha) {
|
||||||
|
const uint8_t* data = NULL;
|
||||||
|
size_t data_size = 0;
|
||||||
|
WebPImageReader reader = NULL;
|
||||||
|
int ok = ImgIoUtilReadFile(filename, &data, &data_size);
|
||||||
|
if (!ok) goto End;
|
||||||
|
|
||||||
|
pic->use_argb = 1; // force ARGB
|
||||||
|
|
||||||
|
#ifdef HAVE_WINCODEC_H
|
||||||
|
// Try to decode the file using WIC falling back to the other readers for
|
||||||
|
// e.g., WebP.
|
||||||
|
ok = ReadPictureWithWIC(filename, pic, keep_alpha, NULL);
|
||||||
|
if (ok) goto End;
|
||||||
|
#endif
|
||||||
|
reader = WebPGuessImageReader(data, data_size);
|
||||||
|
ok = reader(data, data_size, pic, keep_alpha, NULL);
|
||||||
|
|
||||||
|
End:
|
||||||
|
if (!ok) {
|
||||||
|
WFPRINTF(stderr, "Error! Could not process file %s\n",
|
||||||
|
(const W_CHAR*)filename);
|
||||||
|
}
|
||||||
|
free((void*)data);
|
||||||
|
return ok ? data_size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RescalePlane(uint8_t* plane, int width, int height,
|
||||||
|
int x_stride, int y_stride, int max) {
|
||||||
|
const uint32_t factor = (max > 0) ? (255u << 16) / max : 0;
|
||||||
|
int x, y;
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
uint8_t* const ptr = plane + y * y_stride;
|
||||||
|
for (x = 0; x < width * x_stride; x += x_stride) {
|
||||||
|
const uint32_t diff = (ptr[x] * factor + (1 << 15)) >> 16;
|
||||||
|
ptr[x] = diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the max absolute difference.
|
||||||
|
static int DiffScaleChannel(uint8_t* src1, int stride1,
|
||||||
|
const uint8_t* src2, int stride2,
|
||||||
|
int x_stride, int w, int h, int do_scaling) {
|
||||||
|
int x, y;
|
||||||
|
int max = 0;
|
||||||
|
for (y = 0; y < h; ++y) {
|
||||||
|
uint8_t* const ptr1 = src1 + y * stride1;
|
||||||
|
const uint8_t* const ptr2 = src2 + y * stride2;
|
||||||
|
for (x = 0; x < w * x_stride; x += x_stride) {
|
||||||
|
const int diff = abs(ptr1[x] - ptr2[x]);
|
||||||
|
if (diff > max) max = diff;
|
||||||
|
ptr1[x] = diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_scaling) RescalePlane(src1, w, h, x_stride, stride1, max);
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// SSIM calculation. We re-implement these functions here, out of dsp/, to avoid
|
||||||
|
// breaking the library's hidden visibility. This code duplication avoids the
|
||||||
|
// bigger annoyance of having to open up internal details of libdsp...
|
||||||
|
|
||||||
|
#define SSIM_KERNEL 3 // total size of the kernel: 2 * SSIM_KERNEL + 1
|
||||||
|
|
||||||
|
// struct for accumulating statistical moments
|
||||||
|
typedef struct {
|
||||||
|
uint32_t w; // sum(w_i) : sum of weights
|
||||||
|
uint32_t xm, ym; // sum(w_i * x_i), sum(w_i * y_i)
|
||||||
|
uint32_t xxm, xym, yym; // sum(w_i * x_i * x_i), etc.
|
||||||
|
} DistoStats;
|
||||||
|
|
||||||
|
// hat-shaped filter. Sum of coefficients is equal to 16.
|
||||||
|
static const uint32_t kWeight[2 * SSIM_KERNEL + 1] = { 1, 2, 3, 4, 3, 2, 1 };
|
||||||
|
|
||||||
|
static WEBP_INLINE double SSIMCalculation(const DistoStats* const stats) {
|
||||||
|
const uint32_t N = stats->w;
|
||||||
|
const uint32_t w2 = N * N;
|
||||||
|
const uint32_t C1 = 20 * w2;
|
||||||
|
const uint32_t C2 = 60 * w2;
|
||||||
|
const uint32_t C3 = 8 * 8 * w2; // 'dark' limit ~= 6
|
||||||
|
const uint64_t xmxm = (uint64_t)stats->xm * stats->xm;
|
||||||
|
const uint64_t ymym = (uint64_t)stats->ym * stats->ym;
|
||||||
|
if (xmxm + ymym >= C3) {
|
||||||
|
const int64_t xmym = (int64_t)stats->xm * stats->ym;
|
||||||
|
const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative
|
||||||
|
const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm;
|
||||||
|
const uint64_t syy = (uint64_t)stats->yym * N - ymym;
|
||||||
|
// we descale by 8 to prevent overflow during the fnum/fden multiply.
|
||||||
|
const uint64_t num_S = (2 * (uint64_t)(sxy < 0 ? 0 : sxy) + C2) >> 8;
|
||||||
|
const uint64_t den_S = (sxx + syy + C2) >> 8;
|
||||||
|
const uint64_t fnum = (2 * xmym + C1) * num_S;
|
||||||
|
const uint64_t fden = (xmxm + ymym + C1) * den_S;
|
||||||
|
const double r = (double)fnum / fden;
|
||||||
|
assert(r >= 0. && r <= 1.0);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return 1.; // area is too dark to contribute meaningfully
|
||||||
|
}
|
||||||
|
|
||||||
|
static double SSIMGetClipped(const uint8_t* src1, int stride1,
|
||||||
|
const uint8_t* src2, int stride2,
|
||||||
|
int xo, int yo, int W, int H) {
|
||||||
|
DistoStats stats = { 0, 0, 0, 0, 0, 0 };
|
||||||
|
const int ymin = (yo - SSIM_KERNEL < 0) ? 0 : yo - SSIM_KERNEL;
|
||||||
|
const int ymax = (yo + SSIM_KERNEL > H - 1) ? H - 1 : yo + SSIM_KERNEL;
|
||||||
|
const int xmin = (xo - SSIM_KERNEL < 0) ? 0 : xo - SSIM_KERNEL;
|
||||||
|
const int xmax = (xo + SSIM_KERNEL > W - 1) ? W - 1 : xo + SSIM_KERNEL;
|
||||||
|
int x, y;
|
||||||
|
src1 += ymin * stride1;
|
||||||
|
src2 += ymin * stride2;
|
||||||
|
for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) {
|
||||||
|
for (x = xmin; x <= xmax; ++x) {
|
||||||
|
const uint32_t w = kWeight[SSIM_KERNEL + x - xo]
|
||||||
|
* kWeight[SSIM_KERNEL + y - yo];
|
||||||
|
const uint32_t s1 = src1[x];
|
||||||
|
const uint32_t s2 = src2[x];
|
||||||
|
stats.w += w;
|
||||||
|
stats.xm += w * s1;
|
||||||
|
stats.ym += w * s2;
|
||||||
|
stats.xxm += w * s1 * s1;
|
||||||
|
stats.xym += w * s1 * s2;
|
||||||
|
stats.yym += w * s2 * s2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SSIMCalculation(&stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute SSIM-score map. Return -1 in case of error, max diff otherwise.
|
||||||
|
static int SSIMScaleChannel(uint8_t* src1, int stride1,
|
||||||
|
const uint8_t* src2, int stride2,
|
||||||
|
int x_stride, int w, int h, int do_scaling) {
|
||||||
|
int x, y;
|
||||||
|
int max = 0;
|
||||||
|
uint8_t* const plane1 = (uint8_t*)malloc(2 * w * h * sizeof(*plane1));
|
||||||
|
uint8_t* const plane2 = plane1 + w * h;
|
||||||
|
if (plane1 == NULL) return -1;
|
||||||
|
|
||||||
|
// extract plane
|
||||||
|
for (y = 0; y < h; ++y) {
|
||||||
|
for (x = 0; x < w; ++x) {
|
||||||
|
plane1[x + y * w] = src1[x * x_stride + y * stride1];
|
||||||
|
plane2[x + y * w] = src2[x * x_stride + y * stride2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (y = 0; y < h; ++y) {
|
||||||
|
for (x = 0; x < w; ++x) {
|
||||||
|
const double ssim = SSIMGetClipped(plane1, w, plane2, w, x, y, w, h);
|
||||||
|
int diff = (int)(255 * (1. - ssim));
|
||||||
|
if (diff < 0) {
|
||||||
|
diff = 0;
|
||||||
|
} else if (diff > max) {
|
||||||
|
max = diff;
|
||||||
|
}
|
||||||
|
src1[x * x_stride + y * stride1] = (diff > 255) ? 255u : (uint8_t)diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(plane1);
|
||||||
|
|
||||||
|
if (do_scaling) RescalePlane(src1, w, h, x_stride, stride1, max);
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert an argb picture to luminance.
|
||||||
|
static void ConvertToGray(WebPPicture* const pic) {
|
||||||
|
int x, y;
|
||||||
|
assert(pic != NULL);
|
||||||
|
assert(pic->use_argb);
|
||||||
|
for (y = 0; y < pic->height; ++y) {
|
||||||
|
uint32_t* const row = &pic->argb[y * pic->argb_stride];
|
||||||
|
for (x = 0; x < pic->width; ++x) {
|
||||||
|
const uint32_t argb = row[x];
|
||||||
|
const uint32_t r = (argb >> 16) & 0xff;
|
||||||
|
const uint32_t g = (argb >> 8) & 0xff;
|
||||||
|
const uint32_t b = (argb >> 0) & 0xff;
|
||||||
|
// We use BT.709 for converting to luminance.
|
||||||
|
const uint32_t Y = (uint32_t)(0.2126 * r + 0.7152 * g + 0.0722 * b + .5);
|
||||||
|
row[x] = (argb & 0xff000000u) | (Y * 0x010101u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Help(void) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Usage: get_disto [-ssim][-psnr][-alpha] compressed.webp orig.webp\n"
|
||||||
|
" -ssim ..... print SSIM distortion\n"
|
||||||
|
" -psnr ..... print PSNR distortion (default)\n"
|
||||||
|
" -alpha .... preserve alpha plane\n"
|
||||||
|
" -h ........ this message\n"
|
||||||
|
" -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
WebPPicture pic1, pic2;
|
||||||
|
size_t size1 = 0, size2 = 0;
|
||||||
|
int ret = 1;
|
||||||
|
float disto[5];
|
||||||
|
int type = 0;
|
||||||
|
int c;
|
||||||
|
int help = 0;
|
||||||
|
int keep_alpha = 0;
|
||||||
|
int scale = 0;
|
||||||
|
int use_gray = 0;
|
||||||
|
const char* name1 = NULL;
|
||||||
|
const char* name2 = NULL;
|
||||||
|
const char* output = NULL;
|
||||||
|
|
||||||
|
INIT_WARGV(argc, argv);
|
||||||
|
|
||||||
|
if (!WebPPictureInit(&pic1) || !WebPPictureInit(&pic2)) {
|
||||||
|
fprintf(stderr, "Can't init pictures\n");
|
||||||
|
FREE_WARGV_AND_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (c = 1; c < argc; ++c) {
|
||||||
|
if (!strcmp(argv[c], "-ssim")) {
|
||||||
|
type = 1;
|
||||||
|
} else if (!strcmp(argv[c], "-psnr")) {
|
||||||
|
type = 0;
|
||||||
|
} else if (!strcmp(argv[c], "-alpha")) {
|
||||||
|
keep_alpha = 1;
|
||||||
|
} else if (!strcmp(argv[c], "-scale")) {
|
||||||
|
scale = 1;
|
||||||
|
} else if (!strcmp(argv[c], "-gray")) {
|
||||||
|
use_gray = 1;
|
||||||
|
} else if (!strcmp(argv[c], "-h")) {
|
||||||
|
help = 1;
|
||||||
|
ret = 0;
|
||||||
|
} else if (!strcmp(argv[c], "-o")) {
|
||||||
|
if (++c == argc) {
|
||||||
|
fprintf(stderr, "missing file name after %s option.\n", argv[c - 1]);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
output = (const char*)GET_WARGV(argv, c);
|
||||||
|
} else if (name1 == NULL) {
|
||||||
|
name1 = (const char*)GET_WARGV(argv, c);
|
||||||
|
} else {
|
||||||
|
name2 = (const char*)GET_WARGV(argv, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (help || name1 == NULL || name2 == NULL) {
|
||||||
|
if (!help) {
|
||||||
|
fprintf(stderr, "Error: missing arguments.\n");
|
||||||
|
}
|
||||||
|
Help();
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
size1 = ReadPicture(name1, &pic1, 1);
|
||||||
|
size2 = ReadPicture(name2, &pic2, 1);
|
||||||
|
if (size1 == 0 || size2 == 0) goto End;
|
||||||
|
|
||||||
|
if (!keep_alpha) {
|
||||||
|
WebPBlendAlpha(&pic1, 0x00000000);
|
||||||
|
WebPBlendAlpha(&pic2, 0x00000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WebPPictureDistortion(&pic1, &pic2, type, disto)) {
|
||||||
|
fprintf(stderr, "Error while computing the distortion.\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
printf("%u %.2f %.2f %.2f %.2f %.2f [ %.2f bpp ]\n",
|
||||||
|
(unsigned int)size1,
|
||||||
|
disto[4], disto[0], disto[1], disto[2], disto[3],
|
||||||
|
8.f * size1 / pic1.width / pic1.height);
|
||||||
|
|
||||||
|
if (output != NULL) {
|
||||||
|
uint8_t* data = NULL;
|
||||||
|
size_t data_size = 0;
|
||||||
|
if (pic1.use_argb != pic2.use_argb) {
|
||||||
|
fprintf(stderr, "Pictures are not in the same argb format. "
|
||||||
|
"Can't save the difference map.\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
if (pic1.use_argb) {
|
||||||
|
int n;
|
||||||
|
fprintf(stderr, "max differences per channel: ");
|
||||||
|
for (n = 0; n < 3; ++n) { // skip the alpha channel
|
||||||
|
const int range = (type == 1) ?
|
||||||
|
SSIMScaleChannel((uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
||||||
|
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4,
|
||||||
|
4, pic1.width, pic1.height, scale) :
|
||||||
|
DiffScaleChannel((uint8_t*)pic1.argb + n, pic1.argb_stride * 4,
|
||||||
|
(const uint8_t*)pic2.argb + n, pic2.argb_stride * 4,
|
||||||
|
4, pic1.width, pic1.height, scale);
|
||||||
|
if (range < 0) fprintf(stderr, "\nError computing diff map\n");
|
||||||
|
fprintf(stderr, "[%d]", range);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
if (use_gray) ConvertToGray(&pic1);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Can only compute the difference map in ARGB format.\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
#if !defined(WEBP_REDUCE_CSP)
|
||||||
|
data_size = WebPEncodeLosslessBGRA((const uint8_t*)pic1.argb,
|
||||||
|
pic1.width, pic1.height,
|
||||||
|
pic1.argb_stride * 4,
|
||||||
|
&data);
|
||||||
|
if (data_size == 0) {
|
||||||
|
fprintf(stderr, "Error during lossless encoding.\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
ret = ImgIoUtilWriteFile(output, data, data_size) ? 0 : 1;
|
||||||
|
WebPFree(data);
|
||||||
|
if (ret) goto End;
|
||||||
|
#else
|
||||||
|
(void)data;
|
||||||
|
(void)data_size;
|
||||||
|
fprintf(stderr, "Cannot save the difference map. Please recompile "
|
||||||
|
"without the WEBP_REDUCE_CSP flag.\n");
|
||||||
|
#endif // WEBP_REDUCE_CSP
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
End:
|
||||||
|
WebPPictureFree(&pic1);
|
||||||
|
WebPPictureFree(&pic2);
|
||||||
|
FREE_WARGV_AND_RETURN(ret);
|
||||||
|
}
|
||||||
129
extras/quality_estimate.c
Normal file
129
extras/quality_estimate.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// VP8EstimateQuality(): rough encoding quality estimate
|
||||||
|
//
|
||||||
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
|
#include "extras/extras.h"
|
||||||
|
#include "webp/decode.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define INVALID_BIT_POS (1ull << 63)
|
||||||
|
|
||||||
|
// In most cases, we don't need to use a full arithmetic decoder, since
|
||||||
|
// all the header's bits are written using a uniform probability of 128.
|
||||||
|
// We can just parse the header as if it was bits (works in 99.999% cases).
|
||||||
|
static WEBP_INLINE uint32_t GetBit(const uint8_t* const data, size_t nb,
|
||||||
|
uint64_t max_size, uint64_t* const bit_pos) {
|
||||||
|
uint32_t val = 0;
|
||||||
|
if (*bit_pos + nb <= 8 * max_size) {
|
||||||
|
while (nb-- > 0) {
|
||||||
|
const uint64_t p = (*bit_pos)++;
|
||||||
|
const int bit = !!(data[p >> 3] & (128 >> ((p & 7))));
|
||||||
|
val = (val << 1) | bit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*bit_pos = INVALID_BIT_POS;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_BIT(n) GetBit(data, (n), size, &bit_pos)
|
||||||
|
#define CONDITIONAL_SKIP(n) (GET_BIT(1) ? GET_BIT((n)) : 0)
|
||||||
|
|
||||||
|
int VP8EstimateQuality(const uint8_t* const data, size_t size) {
|
||||||
|
size_t pos = 0;
|
||||||
|
uint64_t bit_pos;
|
||||||
|
uint64_t sig = 0x00;
|
||||||
|
int ok = 0;
|
||||||
|
int Q = -1;
|
||||||
|
WebPBitstreamFeatures features;
|
||||||
|
|
||||||
|
if (data == NULL) return -1;
|
||||||
|
|
||||||
|
if (WebPGetFeatures(data, size, &features) != VP8_STATUS_OK) {
|
||||||
|
return -1; // invalid file
|
||||||
|
}
|
||||||
|
if (features.format == 2) return 101; // lossless
|
||||||
|
if (features.format == 0 || features.has_animation) return -1; // mixed
|
||||||
|
|
||||||
|
while (pos < size) {
|
||||||
|
sig = (sig >> 8) | ((uint64_t)data[pos++] << 40);
|
||||||
|
if ((sig >> 24) == 0x2a019dull) {
|
||||||
|
ok = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) return -1;
|
||||||
|
if (pos + 4 > size) return -1;
|
||||||
|
|
||||||
|
// Skip main Header
|
||||||
|
// width = (data[pos + 0] | (data[pos + 1] << 8)) & 0x3fff;
|
||||||
|
// height = (data[pos + 2] | (data[pos + 3] << 8)) & 0x3fff;
|
||||||
|
pos += 4;
|
||||||
|
bit_pos = pos * 8;
|
||||||
|
|
||||||
|
GET_BIT(2); // colorspace + clamp type
|
||||||
|
|
||||||
|
// Segment header
|
||||||
|
if (GET_BIT(1)) { // use_segment_
|
||||||
|
int s;
|
||||||
|
const int update_map = GET_BIT(1);
|
||||||
|
if (GET_BIT(1)) { // update data
|
||||||
|
const int absolute_delta = GET_BIT(1);
|
||||||
|
int q[4] = { 0, 0, 0, 0 };
|
||||||
|
for (s = 0; s < 4; ++s) {
|
||||||
|
if (GET_BIT(1)) {
|
||||||
|
q[s] = GET_BIT(7);
|
||||||
|
if (GET_BIT(1)) q[s] = -q[s]; // sign
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (absolute_delta) Q = q[0]; // just use the first segment's quantizer
|
||||||
|
for (s = 0; s < 4; ++s) CONDITIONAL_SKIP(7); // filter strength
|
||||||
|
}
|
||||||
|
if (update_map) {
|
||||||
|
for (s = 0; s < 3; ++s) CONDITIONAL_SKIP(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Filter header
|
||||||
|
GET_BIT(1 + 6 + 3); // simple + level + sharpness
|
||||||
|
if (GET_BIT(1)) { // use_lf_delta
|
||||||
|
if (GET_BIT(1)) { // update lf_delta?
|
||||||
|
int n;
|
||||||
|
for (n = 0; n < 4 + 4; ++n) CONDITIONAL_SKIP(6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// num partitions
|
||||||
|
GET_BIT(2);
|
||||||
|
|
||||||
|
// ParseQuant
|
||||||
|
{
|
||||||
|
const int base_q = GET_BIT(7);
|
||||||
|
/* dqy1_dc = */ CONDITIONAL_SKIP(5);
|
||||||
|
/* dqy2_dc = */ CONDITIONAL_SKIP(5);
|
||||||
|
/* dqy2_ac = */ CONDITIONAL_SKIP(5);
|
||||||
|
/* dquv_dc = */ CONDITIONAL_SKIP(5);
|
||||||
|
/* dquv_ac = */ CONDITIONAL_SKIP(5);
|
||||||
|
|
||||||
|
if (Q < 0) Q = base_q;
|
||||||
|
}
|
||||||
|
if (bit_pos == INVALID_BIT_POS) return -1;
|
||||||
|
|
||||||
|
// base mapping
|
||||||
|
Q = (127 - Q) * 100 / 127;
|
||||||
|
// correction for power-law behavior in low range
|
||||||
|
if (Q < 80) {
|
||||||
|
Q = (int)(pow(Q / 80., 1. / 0.38) * 80);
|
||||||
|
}
|
||||||
|
return Q;
|
||||||
|
}
|
||||||
101
extras/vwebp_sdl.c
Normal file
101
extras/vwebp_sdl.c
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2017 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Simple SDL-based WebP file viewer.
|
||||||
|
// Does not support animation, just static images.
|
||||||
|
//
|
||||||
|
// Press 'q' to exit.
|
||||||
|
//
|
||||||
|
// Author: James Zern (jzern@google.com)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "webp/config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WEBP_HAVE_SDL)
|
||||||
|
|
||||||
|
#include "webp_to_sdl.h"
|
||||||
|
#include "webp/decode.h"
|
||||||
|
#include "imageio/imageio_util.h"
|
||||||
|
#include "../examples/unicode.h"
|
||||||
|
|
||||||
|
#if defined(WEBP_HAVE_JUST_SDL_H)
|
||||||
|
#include <SDL.h>
|
||||||
|
#else
|
||||||
|
#include <SDL/SDL.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void ProcessEvents(void) {
|
||||||
|
int done = 0;
|
||||||
|
SDL_Event event;
|
||||||
|
while (!done && SDL_WaitEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_KEYUP:
|
||||||
|
switch (event.key.keysym.sym) {
|
||||||
|
case SDLK_q: done = 1; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
int c;
|
||||||
|
int ok = 0;
|
||||||
|
|
||||||
|
INIT_WARGV(argc, argv);
|
||||||
|
|
||||||
|
for (c = 1; c < argc; ++c) {
|
||||||
|
const char* file = NULL;
|
||||||
|
const uint8_t* webp = NULL;
|
||||||
|
size_t webp_size = 0;
|
||||||
|
if (!strcmp(argv[c], "-h")) {
|
||||||
|
printf("Usage: %s [-h] image.webp [more_files.webp...]\n", argv[0]);
|
||||||
|
FREE_WARGV_AND_RETURN(0);
|
||||||
|
} else {
|
||||||
|
file = (const char*)GET_WARGV(argv, c);
|
||||||
|
}
|
||||||
|
if (file == NULL) continue;
|
||||||
|
if (!ImgIoUtilReadFile(file, &webp, &webp_size)) {
|
||||||
|
WFPRINTF(stderr, "Error opening file: %s\n", (const W_CHAR*)file);
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
if (webp_size != (size_t)(int)webp_size) {
|
||||||
|
free((void*)webp);
|
||||||
|
fprintf(stderr, "File too large.\n");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
ok = WebpToSDL((const char*)webp, (int)webp_size);
|
||||||
|
free((void*)webp);
|
||||||
|
if (!ok) {
|
||||||
|
WFPRINTF(stderr, "Error decoding file %s\n", (const W_CHAR*)file);
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
ProcessEvents();
|
||||||
|
}
|
||||||
|
ok = 1;
|
||||||
|
|
||||||
|
Error:
|
||||||
|
SDL_Quit();
|
||||||
|
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // !WEBP_HAVE_SDL
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
fprintf(stderr, "SDL support not enabled in %s.\n", argv[0]);
|
||||||
|
(void)argc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
54
extras/webp_quality.c
Normal file
54
extras/webp_quality.c
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// Simple tool to roughly evaluate the quality encoding of a webp bitstream
|
||||||
|
//
|
||||||
|
// Result is a *rough* estimation of the quality. You should just consider
|
||||||
|
// the bucket it's in (q > 80? > 50? > 20?) and not take it for face value.
|
||||||
|
/*
|
||||||
|
gcc -o webp_quality webp_quality.c -O3 -I../ -L. -L../imageio \
|
||||||
|
-limageio_util -lwebpextras -lwebp -lm -lpthread
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "extras/extras.h"
|
||||||
|
#include "imageio/imageio_util.h"
|
||||||
|
#include "../examples/unicode.h"
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
int c;
|
||||||
|
int quiet = 0;
|
||||||
|
int ok = 1;
|
||||||
|
|
||||||
|
INIT_WARGV(argc, argv);
|
||||||
|
|
||||||
|
for (c = 1; ok && c < argc; ++c) {
|
||||||
|
if (!strcmp(argv[c], "-quiet")) {
|
||||||
|
quiet = 1;
|
||||||
|
} else if (!strcmp(argv[c], "-help") || !strcmp(argv[c], "-h")) {
|
||||||
|
printf("webp_quality [-h][-quiet] webp_files...\n");
|
||||||
|
FREE_WARGV_AND_RETURN(0);
|
||||||
|
} else {
|
||||||
|
const char* const filename = (const char*)GET_WARGV(argv, c);
|
||||||
|
const uint8_t* data = NULL;
|
||||||
|
size_t data_size = 0;
|
||||||
|
int q;
|
||||||
|
ok = ImgIoUtilReadFile(filename, &data, &data_size);
|
||||||
|
if (!ok) break;
|
||||||
|
q = VP8EstimateQuality(data, data_size);
|
||||||
|
if (!quiet) WPRINTF("[%s] ", (const W_CHAR*)filename);
|
||||||
|
if (q < 0) {
|
||||||
|
fprintf(stderr, "Not a WebP file, or not a lossy WebP file.\n");
|
||||||
|
ok = 0;
|
||||||
|
} else {
|
||||||
|
if (!quiet) {
|
||||||
|
printf("Estimated quality factor: %d\n", q);
|
||||||
|
} else {
|
||||||
|
printf("%d\n", q); // just print the number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free((void*)data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FREE_WARGV_AND_RETURN(ok ? 0 : 1);
|
||||||
|
}
|
||||||
110
extras/webp_to_sdl.c
Normal file
110
extras/webp_to_sdl.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// Copyright 2017 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Simple WebP-to-SDL wrapper. Useful for emscripten.
|
||||||
|
//
|
||||||
|
// Author: James Zern (jzern@google.com)
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "src/webp/config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WEBP_HAVE_SDL)
|
||||||
|
|
||||||
|
#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>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int init_ok = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!init_ok) {
|
||||||
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
init_ok = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &config.input);
|
||||||
|
if (status != VP8_STATUS_OK) goto Error;
|
||||||
|
|
||||||
|
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);
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
|
||||||
|
|
||||||
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||||
|
output->colorspace = MODE_BGRA;
|
||||||
|
#else
|
||||||
|
output->colorspace = MODE_RGBA;
|
||||||
|
#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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = 1;
|
||||||
|
|
||||||
|
Error:
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
SDL_FreeSurface(screen);
|
||||||
|
WebPFreeDecBuffer(output);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif // WEBP_HAVE_SDL
|
||||||
22
extras/webp_to_sdl.h
Normal file
22
extras/webp_to_sdl.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2017 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Simple WebP-to-SDL wrapper. Useful for emscripten.
|
||||||
|
//
|
||||||
|
// Author: James Zern (jzern@google.com)
|
||||||
|
|
||||||
|
#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
|
||||||
|
// a WebP bitstream into an RGBA SDL surface.
|
||||||
|
// Return false on failure.
|
||||||
|
extern int WebpToSDL(const char* data, unsigned int data_size);
|
||||||
|
|
||||||
|
#endif // WEBP_EXTRAS_WEBP_TO_SDL_H_
|
||||||
14
gradle.properties
Normal file
14
gradle.properties
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
|
||||||
|
# Versions for gradle
|
||||||
|
BUILD_TOOLS_VERSION=23.0.3
|
||||||
|
COMPILE_SDK_VERSION=23
|
||||||
|
ANDROID_GRADLE_PLUGIN_VERSION=1.5.0
|
||||||
|
GRADLE_DOWNLOAD_TASK_VERSION=2.1.0
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
183
gradlew
vendored
Executable file
183
gradlew
vendored
Executable file
@@ -0,0 +1,183 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
0) set -- ;;
|
||||||
|
1) set -- "$args0" ;;
|
||||||
|
2) set -- "$args0" "$args1" ;;
|
||||||
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
100
gradlew.bat
vendored
Normal file
100
gradlew.bat
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
54
imageio/Android.mk
Normal file
54
imageio/Android.mk
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# libimageio_util
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
imageio_util.c \
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
|
||||||
|
|
||||||
|
LOCAL_MODULE := imageio_util
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# libimagedec
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
image_dec.c \
|
||||||
|
jpegdec.c \
|
||||||
|
metadata.c \
|
||||||
|
pngdec.c \
|
||||||
|
pnmdec.c \
|
||||||
|
tiffdec.c \
|
||||||
|
webpdec.c \
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
|
||||||
|
LOCAL_STATIC_LIBRARIES := imageio_util
|
||||||
|
|
||||||
|
LOCAL_MODULE := imagedec
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# libimageenc
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
image_enc.c \
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
|
||||||
|
LOCAL_STATIC_LIBRARIES := imageio_util
|
||||||
|
|
||||||
|
LOCAL_MODULE := imageenc
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
32
imageio/Makefile.am
Normal file
32
imageio/Makefile.am
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
|
||||||
|
noinst_LTLIBRARIES =
|
||||||
|
noinst_LTLIBRARIES += libimageio_util.la
|
||||||
|
if BUILD_DEMUX
|
||||||
|
noinst_LTLIBRARIES += libimagedec.la
|
||||||
|
endif
|
||||||
|
noinst_LTLIBRARIES += libimageenc.la
|
||||||
|
|
||||||
|
noinst_HEADERS =
|
||||||
|
noinst_HEADERS += ../src/webp/decode.h
|
||||||
|
noinst_HEADERS += ../src/webp/types.h
|
||||||
|
|
||||||
|
libimageio_util_la_SOURCES =
|
||||||
|
libimageio_util_la_SOURCES += imageio_util.c imageio_util.h
|
||||||
|
|
||||||
|
libimagedec_la_SOURCES =
|
||||||
|
libimagedec_la_SOURCES += image_dec.c image_dec.h
|
||||||
|
libimagedec_la_SOURCES += jpegdec.c jpegdec.h
|
||||||
|
libimagedec_la_SOURCES += metadata.c metadata.h
|
||||||
|
libimagedec_la_SOURCES += pngdec.c pngdec.h
|
||||||
|
libimagedec_la_SOURCES += pnmdec.c pnmdec.h
|
||||||
|
libimagedec_la_SOURCES += tiffdec.c tiffdec.h
|
||||||
|
libimagedec_la_SOURCES += webpdec.c webpdec.h
|
||||||
|
libimagedec_la_SOURCES += wicdec.c wicdec.h
|
||||||
|
libimagedec_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES)
|
||||||
|
libimagedec_la_CPPFLAGS += $(AM_CPPFLAGS)
|
||||||
|
libimagedec_la_LIBADD = ../src/demux/libwebpdemux.la
|
||||||
|
|
||||||
|
libimageenc_la_SOURCES =
|
||||||
|
libimageenc_la_SOURCES += image_enc.c image_enc.h
|
||||||
|
libimageenc_la_CPPFLAGS = $(JPEG_INCLUDES) $(PNG_INCLUDES) $(TIFF_INCLUDES)
|
||||||
|
libimageenc_la_CPPFLAGS += $(AM_CPPFLAGS)
|
||||||
66
imageio/image_dec.c
Normal file
66
imageio/image_dec.c
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Generic image-type guessing.
|
||||||
|
|
||||||
|
#include "./image_dec.h"
|
||||||
|
|
||||||
|
static WEBP_INLINE uint32_t GetBE32(const uint8_t buf[]) {
|
||||||
|
return ((uint32_t)buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
WebPInputFileFormat WebPGuessImageType(const uint8_t* const data,
|
||||||
|
size_t data_size) {
|
||||||
|
WebPInputFileFormat format = WEBP_UNSUPPORTED_FORMAT;
|
||||||
|
if (data != NULL && data_size >= 12) {
|
||||||
|
const uint32_t magic1 = GetBE32(data + 0);
|
||||||
|
const uint32_t magic2 = GetBE32(data + 8);
|
||||||
|
if (magic1 == 0x89504E47U) {
|
||||||
|
format = WEBP_PNG_FORMAT;
|
||||||
|
} else if (magic1 >= 0xFFD8FF00U && magic1 <= 0xFFD8FFFFU) {
|
||||||
|
format = WEBP_JPEG_FORMAT;
|
||||||
|
} else if (magic1 == 0x49492A00 || magic1 == 0x4D4D002A) {
|
||||||
|
format = WEBP_TIFF_FORMAT;
|
||||||
|
} else if (magic1 == 0x52494646 && magic2 == 0x57454250) {
|
||||||
|
format = WEBP_WEBP_FORMAT;
|
||||||
|
} else if (((magic1 >> 24) & 0xff) == 'P') {
|
||||||
|
const int type = (magic1 >> 16) & 0xff;
|
||||||
|
// we only support 'P5 -> P7' for now.
|
||||||
|
if (type >= '5' && type <= '7') format = WEBP_PNM_FORMAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int FailReader(const uint8_t* const data, size_t data_size,
|
||||||
|
struct WebPPicture* const pic,
|
||||||
|
int keep_alpha, struct Metadata* const metadata) {
|
||||||
|
(void)data;
|
||||||
|
(void)data_size;
|
||||||
|
(void)pic;
|
||||||
|
(void)keep_alpha;
|
||||||
|
(void)metadata;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebPImageReader WebPGetImageReader(WebPInputFileFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case WEBP_PNG_FORMAT: return ReadPNG;
|
||||||
|
case WEBP_JPEG_FORMAT: return ReadJPEG;
|
||||||
|
case WEBP_TIFF_FORMAT: return ReadTIFF;
|
||||||
|
case WEBP_WEBP_FORMAT: return ReadWebP;
|
||||||
|
case WEBP_PNM_FORMAT: return ReadPNM;
|
||||||
|
default: return FailReader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WebPImageReader WebPGuessImageReader(const uint8_t* const data,
|
||||||
|
size_t data_size) {
|
||||||
|
return WebPGetImageReader(WebPGuessImageType(data, data_size));
|
||||||
|
}
|
||||||
67
imageio/image_dec.h
Normal file
67
imageio/image_dec.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// All-in-one library to decode PNG/JPEG/WebP/TIFF/WIC input images.
|
||||||
|
//
|
||||||
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
|
#ifndef WEBP_IMAGEIO_IMAGE_DEC_H_
|
||||||
|
#define WEBP_IMAGEIO_IMAGE_DEC_H_
|
||||||
|
|
||||||
|
#include "webp/types.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "webp/config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "./metadata.h"
|
||||||
|
#include "./jpegdec.h"
|
||||||
|
#include "./pngdec.h"
|
||||||
|
#include "./pnmdec.h"
|
||||||
|
#include "./tiffdec.h"
|
||||||
|
#include "./webpdec.h"
|
||||||
|
#include "./wicdec.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WEBP_PNG_FORMAT = 0,
|
||||||
|
WEBP_JPEG_FORMAT,
|
||||||
|
WEBP_TIFF_FORMAT,
|
||||||
|
WEBP_WEBP_FORMAT,
|
||||||
|
WEBP_PNM_FORMAT,
|
||||||
|
WEBP_UNSUPPORTED_FORMAT
|
||||||
|
} WebPInputFileFormat;
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
size_t data_size);
|
||||||
|
|
||||||
|
// Signature for common image-reading functions (ReadPNG, ReadJPEG, ...)
|
||||||
|
typedef int (*WebPImageReader)(const uint8_t* const data, size_t data_size,
|
||||||
|
struct WebPPicture* const pic,
|
||||||
|
int keep_alpha, struct Metadata* const metadata);
|
||||||
|
|
||||||
|
// Return the reader associated to a given file format.
|
||||||
|
WebPImageReader WebPGetImageReader(WebPInputFileFormat format);
|
||||||
|
|
||||||
|
// This function is similar to WebPGuessImageType(), but returns a
|
||||||
|
// suitable reader function. The returned reader is never NULL, but
|
||||||
|
// unknown formats will return an always-failing valid reader.
|
||||||
|
WebPImageReader WebPGuessImageReader(const uint8_t* const data,
|
||||||
|
size_t data_size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WEBP_IMAGEIO_IMAGE_DEC_H_
|
||||||
604
imageio/image_enc.c
Normal file
604
imageio/image_enc.c
Normal file
@@ -0,0 +1,604 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Save image
|
||||||
|
|
||||||
|
#include "./image_enc.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef WEBP_HAVE_PNG
|
||||||
|
#include <png.h>
|
||||||
|
#include <setjmp.h> // note: this must be included *after* png.h
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_WINCODEC_H
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
#define INITGUID // Without this GUIDs are declared extern and fail to link
|
||||||
|
#endif
|
||||||
|
#define CINTERFACE
|
||||||
|
#define COBJMACROS
|
||||||
|
#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++
|
||||||
|
// code with COBJMACROS.
|
||||||
|
#include <ole2.h> // CreateStreamOnHGlobal()
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wincodec.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "./imageio_util.h"
|
||||||
|
#include "../examples/unicode.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// PNG
|
||||||
|
|
||||||
|
#ifdef HAVE_WINCODEC_H
|
||||||
|
|
||||||
|
#define IFS(fn) \
|
||||||
|
do { \
|
||||||
|
if (SUCCEEDED(hr)) { \
|
||||||
|
hr = (fn); \
|
||||||
|
if (FAILED(hr)) fprintf(stderr, #fn " failed %08lx\n", hr); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define MAKE_REFGUID(x) (x)
|
||||||
|
#else
|
||||||
|
#define MAKE_REFGUID(x) &(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static HRESULT CreateOutputStream(const char* out_file_name,
|
||||||
|
int write_to_mem, IStream** stream) {
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (write_to_mem) {
|
||||||
|
// Output to a memory buffer. This is freed when 'stream' is released.
|
||||||
|
IFS(CreateStreamOnHGlobal(NULL, TRUE, stream));
|
||||||
|
} else {
|
||||||
|
IFS(SHCreateStreamOnFile((const LPTSTR)out_file_name,
|
||||||
|
STGM_WRITE | STGM_CREATE, stream));
|
||||||
|
}
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
_ftprintf(stderr, _T("Error opening output file %s (%08lx)\n"),
|
||||||
|
(const LPTSTR)out_file_name, hr);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WriteUsingWIC(const char* out_file_name, int use_stdout,
|
||||||
|
REFGUID container_guid,
|
||||||
|
uint8_t* rgb, int stride,
|
||||||
|
uint32_t width, uint32_t height, int has_alpha) {
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
IWICImagingFactory* factory = NULL;
|
||||||
|
IWICBitmapFrameEncode* frame = NULL;
|
||||||
|
IWICBitmapEncoder* encoder = NULL;
|
||||||
|
IStream* stream = NULL;
|
||||||
|
WICPixelFormatGUID pixel_format = has_alpha ? GUID_WICPixelFormat32bppBGRA
|
||||||
|
: GUID_WICPixelFormat24bppBGR;
|
||||||
|
|
||||||
|
if (out_file_name == NULL || rgb == NULL) return E_INVALIDARG;
|
||||||
|
|
||||||
|
IFS(CoInitialize(NULL));
|
||||||
|
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
MAKE_REFGUID(IID_IWICImagingFactory),
|
||||||
|
(LPVOID*)&factory));
|
||||||
|
if (hr == REGDB_E_CLASSNOTREG) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Couldn't access Windows Imaging Component (are you running "
|
||||||
|
"Windows XP SP3 or newer?). PNG support not available. "
|
||||||
|
"Use -ppm or -pgm for available PPM and PGM formats.\n");
|
||||||
|
}
|
||||||
|
IFS(CreateOutputStream(out_file_name, use_stdout, &stream));
|
||||||
|
IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL,
|
||||||
|
&encoder));
|
||||||
|
IFS(IWICBitmapEncoder_Initialize(encoder, stream,
|
||||||
|
WICBitmapEncoderNoCache));
|
||||||
|
IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL));
|
||||||
|
IFS(IWICBitmapFrameEncode_Initialize(frame, NULL));
|
||||||
|
IFS(IWICBitmapFrameEncode_SetSize(frame, width, height));
|
||||||
|
IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format));
|
||||||
|
IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride,
|
||||||
|
height * stride, rgb));
|
||||||
|
IFS(IWICBitmapFrameEncode_Commit(frame));
|
||||||
|
IFS(IWICBitmapEncoder_Commit(encoder));
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && use_stdout) {
|
||||||
|
HGLOBAL image;
|
||||||
|
IFS(GetHGlobalFromStream(stream, &image));
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
HANDLE std_output = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
DWORD mode;
|
||||||
|
const BOOL update_mode = GetConsoleMode(std_output, &mode);
|
||||||
|
const void* const image_mem = GlobalLock(image);
|
||||||
|
DWORD bytes_written = 0;
|
||||||
|
|
||||||
|
// Clear output processing if necessary, then output the image.
|
||||||
|
if (update_mode) SetConsoleMode(std_output, 0);
|
||||||
|
if (!WriteFile(std_output, image_mem, (DWORD)GlobalSize(image),
|
||||||
|
&bytes_written, NULL) ||
|
||||||
|
bytes_written != GlobalSize(image)) {
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
if (update_mode) SetConsoleMode(std_output, mode);
|
||||||
|
GlobalUnlock(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame != NULL) IUnknown_Release(frame);
|
||||||
|
if (encoder != NULL) IUnknown_Release(encoder);
|
||||||
|
if (factory != NULL) IUnknown_Release(factory);
|
||||||
|
if (stream != NULL) IUnknown_Release(stream);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPWritePNG(const char* out_file_name, int use_stdout,
|
||||||
|
const WebPDecBuffer* const buffer) {
|
||||||
|
const uint32_t width = buffer->width;
|
||||||
|
const uint32_t height = buffer->height;
|
||||||
|
uint8_t* const rgb = buffer->u.RGBA.rgba;
|
||||||
|
const int stride = buffer->u.RGBA.stride;
|
||||||
|
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
||||||
|
|
||||||
|
return SUCCEEDED(WriteUsingWIC(out_file_name, use_stdout,
|
||||||
|
MAKE_REFGUID(GUID_ContainerFormatPng),
|
||||||
|
rgb, stride, width, height, has_alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
|
||||||
|
static void PNGAPI PNGErrorFunction(png_structp png, png_const_charp unused) {
|
||||||
|
(void)unused; // remove variable-unused warning
|
||||||
|
longjmp(png_jmpbuf(png), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
|
||||||
|
volatile png_structp png;
|
||||||
|
volatile png_infop info;
|
||||||
|
|
||||||
|
if (out_file == NULL || buffer == NULL) return 0;
|
||||||
|
|
||||||
|
png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||||
|
NULL, PNGErrorFunction, NULL);
|
||||||
|
if (png == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
info = png_create_info_struct(png);
|
||||||
|
if (info == NULL) {
|
||||||
|
png_destroy_write_struct((png_structpp)&png, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (setjmp(png_jmpbuf(png))) {
|
||||||
|
png_destroy_write_struct((png_structpp)&png, (png_infopp)&info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
png_init_io(png, out_file);
|
||||||
|
{
|
||||||
|
const uint32_t width = buffer->width;
|
||||||
|
const uint32_t height = buffer->height;
|
||||||
|
png_bytep row = buffer->u.RGBA.rgba;
|
||||||
|
const int stride = buffer->u.RGBA.stride;
|
||||||
|
const int has_alpha = WebPIsAlphaMode(buffer->colorspace);
|
||||||
|
uint32_t y;
|
||||||
|
|
||||||
|
png_set_IHDR(png, info, width, height, 8,
|
||||||
|
has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
|
||||||
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
||||||
|
PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
png_write_info(png, info);
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
png_write_rows(png, &row, 1);
|
||||||
|
row += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
png_write_end(png, info);
|
||||||
|
png_destroy_write_struct((png_structpp)&png, (png_infopp)&info);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#else // !HAVE_WINCODEC_H && !WEBP_HAVE_PNG
|
||||||
|
int WebPWritePNG(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
|
if (fout == NULL || buffer == NULL) return 0;
|
||||||
|
|
||||||
|
fprintf(stderr, "PNG support not compiled. Please install the libpng "
|
||||||
|
"development package before building.\n");
|
||||||
|
fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// PPM / PAM
|
||||||
|
|
||||||
|
static int WritePPMPAM(FILE* fout, const WebPDecBuffer* const buffer,
|
||||||
|
int alpha) {
|
||||||
|
if (fout == NULL || buffer == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
const uint32_t width = buffer->width;
|
||||||
|
const uint32_t height = buffer->height;
|
||||||
|
const uint8_t* row = buffer->u.RGBA.rgba;
|
||||||
|
const int stride = buffer->u.RGBA.stride;
|
||||||
|
const size_t bytes_per_px = alpha ? 4 : 3;
|
||||||
|
uint32_t y;
|
||||||
|
|
||||||
|
if (row == NULL) return 0;
|
||||||
|
|
||||||
|
if (alpha) {
|
||||||
|
fprintf(fout, "P7\nWIDTH %u\nHEIGHT %u\nDEPTH 4\nMAXVAL 255\n"
|
||||||
|
"TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
|
||||||
|
} else {
|
||||||
|
fprintf(fout, "P6\n%u %u\n255\n", width, height);
|
||||||
|
}
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
if (fwrite(row, width, bytes_per_px, fout) != bytes_per_px) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
row += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPWritePPM(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
|
return WritePPMPAM(fout, buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebPWritePAM(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
|
return WritePPMPAM(fout, buffer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Raw PGM
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
const uint32_t bytes_per_px = 2;
|
||||||
|
uint32_t y;
|
||||||
|
|
||||||
|
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
|
||||||
|
|
||||||
|
fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height);
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
if (fwrite(rgba, width, bytes_per_px, fout) != bytes_per_px) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
rgba += stride;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// BMP
|
||||||
|
|
||||||
|
static void PutLE16(uint8_t* const dst, uint32_t value) {
|
||||||
|
dst[0] = (value >> 0) & 0xff;
|
||||||
|
dst[1] = (value >> 8) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PutLE32(uint8_t* const dst, uint32_t value) {
|
||||||
|
PutLE16(dst + 0, (value >> 0) & 0xffff);
|
||||||
|
PutLE16(dst + 2, (value >> 16) & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BMP_HEADER_SIZE 54
|
||||||
|
int WebPWriteBMP(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 uint32_t bytes_per_px = has_alpha ? 4 : 3;
|
||||||
|
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 total_size = bmp_stride * height + BMP_HEADER_SIZE;
|
||||||
|
uint8_t bmp_header[BMP_HEADER_SIZE] = { 0 };
|
||||||
|
|
||||||
|
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
|
||||||
|
|
||||||
|
// bitmap file header
|
||||||
|
PutLE16(bmp_header + 0, 0x4d42); // signature 'BM'
|
||||||
|
PutLE32(bmp_header + 2, total_size); // size including header
|
||||||
|
PutLE32(bmp_header + 6, 0); // reserved
|
||||||
|
PutLE32(bmp_header + 10, BMP_HEADER_SIZE); // offset to pixel array
|
||||||
|
// bitmap info header
|
||||||
|
PutLE32(bmp_header + 14, 40); // DIB header size
|
||||||
|
PutLE32(bmp_header + 18, width); // dimensions
|
||||||
|
PutLE32(bmp_header + 22, -(int)height); // vertical flip!
|
||||||
|
PutLE16(bmp_header + 26, 1); // number of planes
|
||||||
|
PutLE16(bmp_header + 28, bytes_per_px * 8); // bits per pixel
|
||||||
|
PutLE32(bmp_header + 30, 0); // no compression (BI_RGB)
|
||||||
|
PutLE32(bmp_header + 34, 0); // image size (placeholder)
|
||||||
|
PutLE32(bmp_header + 38, 2400); // x pixels/meter
|
||||||
|
PutLE32(bmp_header + 42, 2400); // y pixels/meter
|
||||||
|
PutLE32(bmp_header + 46, 0); // number of palette colors
|
||||||
|
PutLE32(bmp_header + 50, 0); // important color count
|
||||||
|
|
||||||
|
// TODO(skal): color profile
|
||||||
|
|
||||||
|
// write header
|
||||||
|
if (fwrite(bmp_header, sizeof(bmp_header), 1, fout) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write pixel array
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
if (fwrite(rgba, line_size, 1, fout) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// write padding zeroes
|
||||||
|
if (bmp_stride != line_size) {
|
||||||
|
const uint8_t zeroes[3] = { 0 };
|
||||||
|
if (fwrite(zeroes, bmp_stride - line_size, 1, fout) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rgba += stride;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#undef BMP_HEADER_SIZE
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TIFF
|
||||||
|
|
||||||
|
#define NUM_IFD_ENTRIES 15
|
||||||
|
#define EXTRA_DATA_SIZE 16
|
||||||
|
// 10b for signature/header + n * 12b entries + 4b for IFD terminator:
|
||||||
|
#define EXTRA_DATA_OFFSET (10 + 12 * NUM_IFD_ENTRIES + 4)
|
||||||
|
#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;
|
||||||
|
// For non-alpha case, we omit tag 0x152 (ExtraSamples).
|
||||||
|
const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES
|
||||||
|
: NUM_IFD_ENTRIES - 1;
|
||||||
|
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
|
||||||
|
// IFD (offset = 8). Entries must be written in increasing tag order.
|
||||||
|
num_ifd_entries, 0, // Number of entries in the IFD (12 bytes each).
|
||||||
|
0x00, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 10: Width (TBD)
|
||||||
|
0x01, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 22: Height (TBD)
|
||||||
|
0x02, 0x01, 3, 0, bytes_per_px, 0, 0, 0, // 34: BitsPerSample: 8888
|
||||||
|
EXTRA_DATA_OFFSET + 0, 0, 0, 0,
|
||||||
|
0x03, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 46: Compression: none
|
||||||
|
0x06, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 58: Photometric: RGB
|
||||||
|
0x11, 0x01, 4, 0, 1, 0, 0, 0, // 70: Strips offset:
|
||||||
|
TIFF_HEADER_SIZE, 0, 0, 0, // data follows header
|
||||||
|
0x12, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 82: Orientation: topleft
|
||||||
|
0x15, 0x01, 3, 0, 1, 0, 0, 0, // 94: SamplesPerPixels
|
||||||
|
bytes_per_px, 0, 0, 0,
|
||||||
|
0x16, 0x01, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 106: Rows per strip (TBD)
|
||||||
|
0x17, 0x01, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 118: StripByteCount (TBD)
|
||||||
|
0x1a, 0x01, 5, 0, 1, 0, 0, 0, // 130: X-resolution
|
||||||
|
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
||||||
|
0x1b, 0x01, 5, 0, 1, 0, 0, 0, // 142: Y-resolution
|
||||||
|
EXTRA_DATA_OFFSET + 8, 0, 0, 0,
|
||||||
|
0x1c, 0x01, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0, // 154: PlanarConfiguration
|
||||||
|
0x28, 0x01, 3, 0, 1, 0, 0, 0, 2, 0, 0, 0, // 166: ResolutionUnit (inch)
|
||||||
|
0x52, 0x01, 3, 0, 1, 0, 0, 0,
|
||||||
|
assoc_alpha, 0, 0, 0, // 178: ExtraSamples: rgbA/RGBA
|
||||||
|
0, 0, 0, 0, // 190: IFD terminator
|
||||||
|
// EXTRA_DATA_OFFSET:
|
||||||
|
8, 0, 8, 0, 8, 0, 8, 0, // BitsPerSample
|
||||||
|
72, 0, 0, 0, 1, 0, 0, 0 // 72 pixels/inch, for X/Y-resolution
|
||||||
|
};
|
||||||
|
uint32_t y;
|
||||||
|
|
||||||
|
if (fout == NULL || buffer == NULL || rgba == NULL) return 0;
|
||||||
|
|
||||||
|
// Fill placeholders in IFD:
|
||||||
|
PutLE32(tiff_header + 10 + 8, width);
|
||||||
|
PutLE32(tiff_header + 22 + 8, height);
|
||||||
|
PutLE32(tiff_header + 106 + 8, height);
|
||||||
|
PutLE32(tiff_header + 118 + 8, width * bytes_per_px * height);
|
||||||
|
if (!has_alpha) PutLE32(tiff_header + 178, 0); // IFD terminator
|
||||||
|
|
||||||
|
// write header
|
||||||
|
if (fwrite(tiff_header, sizeof(tiff_header), 1, fout) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// write pixel values
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
if (fwrite(rgba, bytes_per_px, width, fout) != width) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
rgba += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef TIFF_HEADER_SIZE
|
||||||
|
#undef EXTRA_DATA_OFFSET
|
||||||
|
#undef EXTRA_DATA_SIZE
|
||||||
|
#undef NUM_IFD_ENTRIES
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Raw Alpha
|
||||||
|
|
||||||
|
int WebPWriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
|
if (fout == NULL || buffer == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
const uint32_t width = buffer->width;
|
||||||
|
const uint32_t height = buffer->height;
|
||||||
|
const uint8_t* a = buffer->u.YUVA.a;
|
||||||
|
const int a_stride = buffer->u.YUVA.a_stride;
|
||||||
|
uint32_t y;
|
||||||
|
|
||||||
|
if (a == NULL) return 0;
|
||||||
|
|
||||||
|
fprintf(fout, "P5\n%u %u\n255\n", width, height);
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
if (fwrite(a, width, 1, fout) != 1) return 0;
|
||||||
|
a += a_stride;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// PGM with IMC4 layout
|
||||||
|
|
||||||
|
int WebPWritePGM(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
|
if (fout == NULL || buffer == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
const int width = buffer->width;
|
||||||
|
const int height = buffer->height;
|
||||||
|
const WebPYUVABuffer* const yuv = &buffer->u.YUVA;
|
||||||
|
const uint8_t* src_y = yuv->y;
|
||||||
|
const uint8_t* src_u = yuv->u;
|
||||||
|
const uint8_t* src_v = yuv->v;
|
||||||
|
const uint8_t* src_a = yuv->a;
|
||||||
|
const int uv_width = (width + 1) / 2;
|
||||||
|
const int uv_height = (height + 1) / 2;
|
||||||
|
const int a_height = (src_a != NULL) ? height : 0;
|
||||||
|
int ok = 1;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
if (src_y == NULL || src_u == NULL || src_v == NULL) return 0;
|
||||||
|
|
||||||
|
fprintf(fout, "P5\n%d %d\n255\n",
|
||||||
|
(width + 1) & ~1, height + uv_height + a_height);
|
||||||
|
for (y = 0; ok && y < height; ++y) {
|
||||||
|
ok &= (fwrite(src_y, width, 1, fout) == 1);
|
||||||
|
if (width & 1) fputc(0, fout); // padding byte
|
||||||
|
src_y += yuv->y_stride;
|
||||||
|
}
|
||||||
|
for (y = 0; ok && y < uv_height; ++y) {
|
||||||
|
ok &= (fwrite(src_u, uv_width, 1, fout) == 1);
|
||||||
|
ok &= (fwrite(src_v, uv_width, 1, fout) == 1);
|
||||||
|
src_u += yuv->u_stride;
|
||||||
|
src_v += yuv->v_stride;
|
||||||
|
}
|
||||||
|
for (y = 0; ok && y < a_height; ++y) {
|
||||||
|
ok &= (fwrite(src_a, width, 1, fout) == 1);
|
||||||
|
if (width & 1) fputc(0, fout); // padding byte
|
||||||
|
src_a += yuv->a_stride;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Raw YUV(A) planes
|
||||||
|
|
||||||
|
int WebPWriteYUV(FILE* fout, const WebPDecBuffer* const buffer) {
|
||||||
|
if (fout == NULL || buffer == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
const int width = buffer->width;
|
||||||
|
const int height = buffer->height;
|
||||||
|
const WebPYUVABuffer* const yuv = &buffer->u.YUVA;
|
||||||
|
const uint8_t* src_y = yuv->y;
|
||||||
|
const uint8_t* src_u = yuv->u;
|
||||||
|
const uint8_t* src_v = yuv->v;
|
||||||
|
const uint8_t* src_a = yuv->a;
|
||||||
|
const int uv_width = (width + 1) / 2;
|
||||||
|
const int uv_height = (height + 1) / 2;
|
||||||
|
const int a_height = (src_a != NULL) ? height : 0;
|
||||||
|
int ok = 1;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
if (src_y == NULL || src_u == NULL || src_v == NULL) return 0;
|
||||||
|
|
||||||
|
for (y = 0; ok && y < height; ++y) {
|
||||||
|
ok &= (fwrite(src_y, width, 1, fout) == 1);
|
||||||
|
src_y += yuv->y_stride;
|
||||||
|
}
|
||||||
|
for (y = 0; ok && y < uv_height; ++y) {
|
||||||
|
ok &= (fwrite(src_u, uv_width, 1, fout) == 1);
|
||||||
|
src_u += yuv->u_stride;
|
||||||
|
}
|
||||||
|
for (y = 0; ok && y < uv_height; ++y) {
|
||||||
|
ok &= (fwrite(src_v, uv_width, 1, fout) == 1);
|
||||||
|
src_v += yuv->v_stride;
|
||||||
|
}
|
||||||
|
for (y = 0; ok && y < a_height; ++y) {
|
||||||
|
ok &= (fwrite(src_a, width, 1, fout) == 1);
|
||||||
|
src_a += yuv->a_stride;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Generic top-level call
|
||||||
|
|
||||||
|
int WebPSaveImage(const WebPDecBuffer* const buffer,
|
||||||
|
WebPOutputFileFormat format,
|
||||||
|
const char* const out_file_name) {
|
||||||
|
FILE* fout = NULL;
|
||||||
|
int needs_open_file = 1;
|
||||||
|
const int use_stdout =
|
||||||
|
(out_file_name != NULL) && !WSTRCMP(out_file_name, "-");
|
||||||
|
int ok = 1;
|
||||||
|
|
||||||
|
if (buffer == NULL || out_file_name == NULL) return 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_WINCODEC_H
|
||||||
|
needs_open_file = (format != PNG);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (needs_open_file) {
|
||||||
|
fout = use_stdout ? ImgIoUtilSetBinaryMode(stdout)
|
||||||
|
: WFOPEN(out_file_name, "wb");
|
||||||
|
if (fout == NULL) {
|
||||||
|
WFPRINTF(stderr, "Error opening output file %s\n",
|
||||||
|
(const W_CHAR*)out_file_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == PNG ||
|
||||||
|
format == RGBA || format == BGRA || format == ARGB ||
|
||||||
|
format == rgbA || format == bgrA || format == Argb) {
|
||||||
|
#ifdef HAVE_WINCODEC_H
|
||||||
|
ok &= WebPWritePNG(out_file_name, use_stdout, buffer);
|
||||||
|
#else
|
||||||
|
ok &= WebPWritePNG(fout, buffer);
|
||||||
|
#endif
|
||||||
|
} else if (format == PAM) {
|
||||||
|
ok &= WebPWritePAM(fout, buffer);
|
||||||
|
} else if (format == PPM || format == RGB || format == BGR) {
|
||||||
|
ok &= WebPWritePPM(fout, buffer);
|
||||||
|
} else if (format == RGBA_4444 || format == RGB_565 || format == rgbA_4444) {
|
||||||
|
ok &= WebPWrite16bAsPGM(fout, buffer);
|
||||||
|
} else if (format == BMP) {
|
||||||
|
ok &= WebPWriteBMP(fout, buffer);
|
||||||
|
} else if (format == TIFF) {
|
||||||
|
ok &= WebPWriteTIFF(fout, buffer);
|
||||||
|
} else if (format == RAW_YUV) {
|
||||||
|
ok &= WebPWriteYUV(fout, buffer);
|
||||||
|
} else if (format == PGM || format == YUV || format == YUVA) {
|
||||||
|
ok &= WebPWritePGM(fout, buffer);
|
||||||
|
} else if (format == ALPHA_PLANE_ONLY) {
|
||||||
|
ok &= WebPWriteAlphaPlane(fout, buffer);
|
||||||
|
}
|
||||||
|
if (fout != NULL && fout != stdout) {
|
||||||
|
fclose(fout);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
96
imageio/image_enc.h
Normal file
96
imageio/image_enc.h
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// All-in-one library to save PNG/JPEG/WebP/TIFF/WIC images.
|
||||||
|
//
|
||||||
|
// Author: Skal (pascal.massimino@gmail.com)
|
||||||
|
|
||||||
|
#ifndef WEBP_IMAGEIO_IMAGE_ENC_H_
|
||||||
|
#define WEBP_IMAGEIO_IMAGE_ENC_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "webp/config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "webp/types.h"
|
||||||
|
#include "webp/decode.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Output types
|
||||||
|
typedef enum {
|
||||||
|
PNG = 0,
|
||||||
|
PAM,
|
||||||
|
PPM,
|
||||||
|
PGM,
|
||||||
|
BMP,
|
||||||
|
TIFF,
|
||||||
|
RAW_YUV,
|
||||||
|
ALPHA_PLANE_ONLY, // this is for experimenting only
|
||||||
|
// forced colorspace output (for testing, mostly)
|
||||||
|
RGB, RGBA, BGR, BGRA, ARGB,
|
||||||
|
RGBA_4444, RGB_565,
|
||||||
|
rgbA, bgrA, Argb, rgbA_4444,
|
||||||
|
YUV, YUVA
|
||||||
|
} WebPOutputFileFormat;
|
||||||
|
|
||||||
|
// General all-purpose call.
|
||||||
|
// Most formats expect a 'buffer' containing RGBA-like samples, except
|
||||||
|
// RAW_YUV, YUV and YUVA formats.
|
||||||
|
// If 'out_file_name' is "-", data is saved to stdout.
|
||||||
|
// Returns false if an error occurred, true otherwise.
|
||||||
|
int WebPSaveImage(const WebPDecBuffer* const buffer,
|
||||||
|
WebPOutputFileFormat format, const char* const out_file_name);
|
||||||
|
|
||||||
|
// Save to PNG.
|
||||||
|
#ifdef HAVE_WINCODEC_H
|
||||||
|
int WebPWritePNG(const char* out_file_name, int use_stdout,
|
||||||
|
const struct WebPDecBuffer* const buffer);
|
||||||
|
#else
|
||||||
|
int WebPWritePNG(FILE* out_file, const WebPDecBuffer* const buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Save to PPM format (RGB, no alpha)
|
||||||
|
int WebPWritePPM(FILE* fout, const struct WebPDecBuffer* const buffer);
|
||||||
|
|
||||||
|
// Save to PAM format (= PPM + alpha)
|
||||||
|
int WebPWritePAM(FILE* fout, const struct WebPDecBuffer* const buffer);
|
||||||
|
|
||||||
|
// Save 16b mode (RGBA4444, RGB565, ...) for debugging purposes.
|
||||||
|
int WebPWrite16bAsPGM(FILE* fout, const struct WebPDecBuffer* const buffer);
|
||||||
|
|
||||||
|
// Save as BMP
|
||||||
|
int WebPWriteBMP(FILE* fout, const struct WebPDecBuffer* const buffer);
|
||||||
|
|
||||||
|
// Save as TIFF
|
||||||
|
int WebPWriteTIFF(FILE* fout, const struct WebPDecBuffer* const buffer);
|
||||||
|
|
||||||
|
// Save the ALPHA plane (only) as a PGM
|
||||||
|
int WebPWriteAlphaPlane(FILE* fout, const struct WebPDecBuffer* const buffer);
|
||||||
|
|
||||||
|
// Save as YUV samples as PGM format (using IMC4 layout).
|
||||||
|
// See: http://www.fourcc.org/yuv.php#IMC4.
|
||||||
|
// (very convenient format for viewing the samples, esp. for odd dimensions).
|
||||||
|
int WebPWritePGM(FILE* fout, const struct WebPDecBuffer* const buffer);
|
||||||
|
|
||||||
|
// Save YUV(A) planes sequentially (raw dump)
|
||||||
|
int WebPWriteYUV(FILE* fout, const struct WebPDecBuffer* const buffer);
|
||||||
|
|
||||||
|
// Save 16b mode (RGBA4444, RGB565, ...) as PGM format, for debugging purposes.
|
||||||
|
int WebPWrite16bAsPGM(FILE* fout, const struct WebPDecBuffer* const buffer);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WEBP_IMAGEIO_IMAGE_ENC_H_
|
||||||
162
imageio/imageio_util.c
Normal file
162
imageio/imageio_util.c
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Utility functions used by the image decoders.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "./imageio_util.h"
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <fcntl.h> // for _O_BINARY
|
||||||
|
#include <io.h> // for _setmode()
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../examples/unicode.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// File I/O
|
||||||
|
|
||||||
|
FILE* ImgIoUtilSetBinaryMode(FILE* file) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (_setmode(_fileno(file), _O_BINARY) == -1) {
|
||||||
|
fprintf(stderr, "Failed to reopen file in O_BINARY mode.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
|
||||||
|
static const size_t kBlockSize = 16384; // default initial size
|
||||||
|
size_t max_size = 0;
|
||||||
|
size_t size = 0;
|
||||||
|
uint8_t* input = NULL;
|
||||||
|
|
||||||
|
if (data == NULL || data_size == NULL) return 0;
|
||||||
|
*data = NULL;
|
||||||
|
*data_size = 0;
|
||||||
|
|
||||||
|
if (!ImgIoUtilSetBinaryMode(stdin)) return 0;
|
||||||
|
|
||||||
|
while (!feof(stdin)) {
|
||||||
|
// We double the buffer size each time and read as much as possible.
|
||||||
|
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;
|
||||||
|
// we allocate one extra byte for the \0 terminator
|
||||||
|
void* const new_data = realloc(input, max_size + extra_size + 1);
|
||||||
|
if (new_data == NULL) goto Error;
|
||||||
|
input = (uint8_t*)new_data;
|
||||||
|
max_size += extra_size;
|
||||||
|
size += fread(input + size, 1, extra_size, stdin);
|
||||||
|
if (size < max_size) break;
|
||||||
|
}
|
||||||
|
if (ferror(stdin)) goto Error;
|
||||||
|
if (input != NULL) input[size] = '\0'; // convenient 0-terminator
|
||||||
|
*data = input;
|
||||||
|
*data_size = size;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
Error:
|
||||||
|
free(input);
|
||||||
|
fprintf(stderr, "Could not read from stdin\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ImgIoUtilReadFile(const char* const file_name,
|
||||||
|
const uint8_t** data, size_t* data_size) {
|
||||||
|
int ok;
|
||||||
|
uint8_t* file_data;
|
||||||
|
size_t file_size;
|
||||||
|
FILE* in;
|
||||||
|
const int from_stdin = (file_name == NULL) || !WSTRCMP(file_name, "-");
|
||||||
|
|
||||||
|
if (from_stdin) return ImgIoUtilReadFromStdin(data, data_size);
|
||||||
|
|
||||||
|
if (data == NULL || data_size == NULL) return 0;
|
||||||
|
*data = NULL;
|
||||||
|
*data_size = 0;
|
||||||
|
|
||||||
|
in = WFOPEN(file_name, "rb");
|
||||||
|
if (in == NULL) {
|
||||||
|
WFPRINTF(stderr, "cannot open input file '%s'\n", (const W_CHAR*)file_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fseek(in, 0, SEEK_END);
|
||||||
|
file_size = ftell(in);
|
||||||
|
fseek(in, 0, SEEK_SET);
|
||||||
|
// we allocate one extra byte for the \0 terminator
|
||||||
|
file_data = (uint8_t*)WebPMalloc(file_size + 1);
|
||||||
|
if (file_data == NULL) {
|
||||||
|
fclose(in);
|
||||||
|
WFPRINTF(stderr, "memory allocation failure when reading file %s\n",
|
||||||
|
(const W_CHAR*)file_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ok = (fread(file_data, file_size, 1, in) == 1);
|
||||||
|
fclose(in);
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
WFPRINTF(stderr, "Could not read %d bytes of data from file %s\n",
|
||||||
|
(int)file_size, (const W_CHAR*)file_name);
|
||||||
|
WebPFree(file_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
file_data[file_size] = '\0'; // convenient 0-terminator
|
||||||
|
*data = file_data;
|
||||||
|
*data_size = file_size;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int ImgIoUtilWriteFile(const char* const file_name,
|
||||||
|
const uint8_t* data, size_t data_size) {
|
||||||
|
int ok;
|
||||||
|
FILE* out;
|
||||||
|
const int to_stdout = (file_name == NULL) || !WSTRCMP(file_name, "-");
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
out = to_stdout ? ImgIoUtilSetBinaryMode(stdout) : WFOPEN(file_name, "wb");
|
||||||
|
if (out == NULL) {
|
||||||
|
WFPRINTF(stderr, "Error! Cannot open output file '%s'\n",
|
||||||
|
(const W_CHAR*)file_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ok = (fwrite(data, data_size, 1, out) == 1);
|
||||||
|
if (out != stdout) fclose(out);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
||||||
|
uint8_t* dst, int dst_stride, int width, int height) {
|
||||||
|
while (height-- > 0) {
|
||||||
|
memcpy(dst, src, width * sizeof(*dst));
|
||||||
|
src += src_stride;
|
||||||
|
dst += dst_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height) {
|
||||||
|
const uint64_t total_size = stride * height;
|
||||||
|
int ok = (total_size == (size_t)total_size);
|
||||||
|
// check that 'stride' is representable as int:
|
||||||
|
ok = ok && ((uint64_t)(int)stride == stride);
|
||||||
|
#if defined(WEBP_MAX_IMAGE_SIZE)
|
||||||
|
ok = ok && (total_size <= (uint64_t)WEBP_MAX_IMAGE_SIZE);
|
||||||
|
#endif
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
64
imageio/imageio_util.h
Normal file
64
imageio/imageio_util.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Utility functions used by the image decoders.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef WEBP_IMAGEIO_IMAGEIO_UTIL_H_
|
||||||
|
#define WEBP_IMAGEIO_IMAGEIO_UTIL_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "webp/types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// File I/O
|
||||||
|
|
||||||
|
// Reopen file in binary (O_BINARY) mode.
|
||||||
|
// Returns 'file' on success, NULL otherwise.
|
||||||
|
FILE* ImgIoUtilSetBinaryMode(FILE* file);
|
||||||
|
|
||||||
|
// Allocates storage for entire file 'file_name' and returns contents and size
|
||||||
|
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
|
||||||
|
// be deleted using WebPFree().
|
||||||
|
// Note: for convenience, the data will be null-terminated with an extra byte
|
||||||
|
// (not accounted for in *data_size), in case the file is text and intended
|
||||||
|
// to be used as a C-string.
|
||||||
|
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
|
||||||
|
// the function ImgIoUtilReadFromStdin().
|
||||||
|
int ImgIoUtilReadFile(const char* const file_name,
|
||||||
|
const uint8_t** data, size_t* data_size);
|
||||||
|
|
||||||
|
// Same as ImgIoUtilReadFile(), but reads until EOF from stdin instead.
|
||||||
|
int ImgIoUtilReadFromStdin(const uint8_t** data, size_t* data_size);
|
||||||
|
|
||||||
|
// Write a data segment into a file named 'file_name'. Returns true if ok.
|
||||||
|
// If 'file_name' is NULL or equal to "-", output is written to stdout.
|
||||||
|
int ImgIoUtilWriteFile(const char* const file_name,
|
||||||
|
const uint8_t* data, size_t data_size);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Copy width x height pixels from 'src' to 'dst' honoring the strides.
|
||||||
|
void ImgIoUtilCopyPlane(const uint8_t* src, int src_stride,
|
||||||
|
uint8_t* dst, int dst_stride, int width, int height);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Returns 0 in case of overflow, memory over-allocation or excessive dimension.
|
||||||
|
int ImgIoUtilCheckSizeArgumentsOverflow(uint64_t stride, size_t height);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WEBP_IMAGEIO_IMAGEIO_UTIL_H_
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
#include "./example_util.h"
|
#include "./imageio_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -206,6 +206,7 @@ struct my_error_mgr {
|
|||||||
|
|
||||||
static void my_error_exit(j_common_ptr dinfo) {
|
static void my_error_exit(j_common_ptr dinfo) {
|
||||||
struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err;
|
struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err;
|
||||||
|
fprintf(stderr, "libjpeg error: ");
|
||||||
dinfo->err->output_message(dinfo);
|
dinfo->err->output_message(dinfo);
|
||||||
longjmp(myerr->setjmp_buffer, 1);
|
longjmp(myerr->setjmp_buffer, 1);
|
||||||
}
|
}
|
||||||
@@ -222,10 +223,10 @@ static void ContextInit(j_decompress_ptr cinfo) {
|
|||||||
ctx->pub.bytes_in_buffer = ctx->data_size;
|
ctx->pub.bytes_in_buffer = ctx->data_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ContextFill(j_decompress_ptr cinfo) {
|
static boolean ContextFill(j_decompress_ptr cinfo) {
|
||||||
// we shouldn't get here.
|
// we shouldn't get here.
|
||||||
ERREXIT(cinfo, JERR_FILE_READ);
|
ERREXIT(cinfo, JERR_FILE_READ);
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ContextSkip(j_decompress_ptr cinfo, long jump_size) {
|
static void ContextSkip(j_decompress_ptr cinfo, long jump_size) {
|
||||||
@@ -255,20 +256,25 @@ static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic, Metadata* const metadata) {
|
WebPPicture* const pic, int keep_alpha,
|
||||||
|
Metadata* const metadata) {
|
||||||
volatile int ok = 0;
|
volatile int ok = 0;
|
||||||
int stride, width, height;
|
int width, height;
|
||||||
|
int64_t stride;
|
||||||
volatile struct jpeg_decompress_struct dinfo;
|
volatile struct jpeg_decompress_struct dinfo;
|
||||||
struct my_error_mgr jerr;
|
struct my_error_mgr jerr;
|
||||||
uint8_t* volatile rgb = NULL;
|
uint8_t* volatile rgb = NULL;
|
||||||
JSAMPROW buffer[1];
|
JSAMPROW buffer[1];
|
||||||
JPEGReadContext ctx;
|
JPEGReadContext ctx;
|
||||||
|
|
||||||
|
if (data == NULL || data_size == 0 || pic == NULL) return 0;
|
||||||
|
|
||||||
|
(void)keep_alpha;
|
||||||
memset(&ctx, 0, sizeof(ctx));
|
memset(&ctx, 0, sizeof(ctx));
|
||||||
ctx.data = data;
|
ctx.data = data;
|
||||||
ctx.data_size = data_size;
|
ctx.data_size = data_size;
|
||||||
|
|
||||||
memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp sanity
|
memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp safety
|
||||||
dinfo.err = jpeg_std_error(&jerr.pub);
|
dinfo.err = jpeg_std_error(&jerr.pub);
|
||||||
jerr.pub.error_exit = my_error_exit;
|
jerr.pub.error_exit = my_error_exit;
|
||||||
|
|
||||||
@@ -295,17 +301,22 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
width = dinfo.output_width;
|
width = dinfo.output_width;
|
||||||
height = dinfo.output_height;
|
height = dinfo.output_height;
|
||||||
stride = dinfo.output_width * dinfo.output_components * sizeof(*rgb);
|
stride = (int64_t)dinfo.output_width * dinfo.output_components * sizeof(*rgb);
|
||||||
|
|
||||||
rgb = (uint8_t*)malloc(stride * height);
|
if (stride != (int)stride ||
|
||||||
|
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgb = (uint8_t*)malloc((size_t)stride * height);
|
||||||
if (rgb == NULL) {
|
if (rgb == NULL) {
|
||||||
goto End;
|
goto Error;
|
||||||
}
|
}
|
||||||
buffer[0] = (JSAMPLE*)rgb;
|
buffer[0] = (JSAMPLE*)rgb;
|
||||||
|
|
||||||
while (dinfo.output_scanline < dinfo.output_height) {
|
while (dinfo.output_scanline < dinfo.output_height) {
|
||||||
if (jpeg_read_scanlines((j_decompress_ptr)&dinfo, buffer, 1) != 1) {
|
if (jpeg_read_scanlines((j_decompress_ptr)&dinfo, buffer, 1) != 1) {
|
||||||
goto End;
|
goto Error;
|
||||||
}
|
}
|
||||||
buffer[0] += stride;
|
buffer[0] += stride;
|
||||||
}
|
}
|
||||||
@@ -324,7 +335,7 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
|
|||||||
// WebP conversion.
|
// WebP conversion.
|
||||||
pic->width = width;
|
pic->width = width;
|
||||||
pic->height = height;
|
pic->height = height;
|
||||||
ok = WebPPictureImportRGB(pic, rgb, stride);
|
ok = WebPPictureImportRGB(pic, rgb, (int)stride);
|
||||||
if (!ok) goto Error;
|
if (!ok) goto Error;
|
||||||
|
|
||||||
End:
|
End:
|
||||||
@@ -333,11 +344,12 @@ int ReadJPEG(const uint8_t* const data, size_t data_size,
|
|||||||
}
|
}
|
||||||
#else // !WEBP_HAVE_JPEG
|
#else // !WEBP_HAVE_JPEG
|
||||||
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic,
|
struct WebPPicture* const pic, int keep_alpha,
|
||||||
struct Metadata* const metadata) {
|
struct Metadata* const metadata) {
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)data_size;
|
(void)data_size;
|
||||||
(void)pic;
|
(void)pic;
|
||||||
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr, "JPEG support not compiled. Please install the libjpeg "
|
fprintf(stderr, "JPEG support not compiled. Please install the libjpeg "
|
||||||
"development package before building.\n");
|
"development package before building.\n");
|
||||||
@@ -9,10 +9,9 @@
|
|||||||
//
|
//
|
||||||
// JPEG decode.
|
// JPEG decode.
|
||||||
|
|
||||||
#ifndef WEBP_EXAMPLES_JPEGDEC_H_
|
#ifndef WEBP_IMAGEIO_JPEGDEC_H_
|
||||||
#define WEBP_EXAMPLES_JPEGDEC_H_
|
#define WEBP_IMAGEIO_JPEGDEC_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "webp/types.h"
|
#include "webp/types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -25,11 +24,14 @@ struct WebPPicture;
|
|||||||
// Reads a JPEG from 'data', returning the decoded output in 'pic'.
|
// Reads a JPEG from 'data', returning the decoded output in 'pic'.
|
||||||
// The output is RGB or YUV depending on pic->use_argb value.
|
// The output is RGB or YUV depending on pic->use_argb value.
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
|
// 'keep_alpha' has no effect, but is kept for coherence with other signatures
|
||||||
|
// for image readers.
|
||||||
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
int ReadJPEG(const uint8_t* const data, size_t data_size,
|
||||||
struct WebPPicture* const pic, struct Metadata* const metadata);
|
struct WebPPicture* const pic, int keep_alpha,
|
||||||
|
struct Metadata* const metadata);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // WEBP_EXAMPLES_JPEGDEC_H_
|
#endif // WEBP_IMAGEIO_JPEGDEC_H_
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
// Metadata types and functions.
|
// Metadata types and functions.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef WEBP_EXAMPLES_METADATA_H_
|
#ifndef WEBP_IMAGEIO_METADATA_H_
|
||||||
#define WEBP_EXAMPLES_METADATA_H_
|
#define WEBP_IMAGEIO_METADATA_H_
|
||||||
|
|
||||||
#include "webp/types.h"
|
#include "webp/types.h"
|
||||||
|
|
||||||
@@ -44,4 +44,4 @@ int MetadataCopy(const char* metadata, size_t metadata_len,
|
|||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // WEBP_EXAMPLES_METADATA_H_
|
#endif // WEBP_IMAGEIO_METADATA_H_
|
||||||
@@ -18,21 +18,45 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef WEBP_HAVE_PNG
|
#ifdef WEBP_HAVE_PNG
|
||||||
#include <assert.h>
|
#ifndef PNG_USER_MEM_SUPPORTED
|
||||||
|
#define PNG_USER_MEM_SUPPORTED // for png_create_read_struct_2
|
||||||
|
#endif
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
#include <setjmp.h> // note: this must be included *after* png.h
|
#include <setjmp.h> // note: this must be included *after* png.h
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
#include "./example_util.h"
|
#include "./imageio_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
|
||||||
|
#define LOCAL_PNG_VERSION ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR)
|
||||||
|
#define LOCAL_PNG_PREREQ(maj, min) \
|
||||||
|
(LOCAL_PNG_VERSION >= (((maj) << 8) | (min)))
|
||||||
|
|
||||||
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
||||||
if (error != NULL) fprintf(stderr, "libpng error: %s\n", error);
|
if (error != NULL) fprintf(stderr, "libpng error: %s\n", error);
|
||||||
longjmp(png_jmpbuf(png), 1);
|
longjmp(png_jmpbuf(png), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LOCAL_PNG_PREREQ(1,4)
|
||||||
|
typedef png_alloc_size_t LocalPngAllocSize;
|
||||||
|
#else
|
||||||
|
typedef png_size_t LocalPngAllocSize;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static png_voidp MallocFunc(png_structp png_ptr, LocalPngAllocSize size) {
|
||||||
|
(void)png_ptr;
|
||||||
|
if (size != (size_t)size) return NULL;
|
||||||
|
if (!ImgIoUtilCheckSizeArgumentsOverflow(size, 1)) return NULL;
|
||||||
|
return (png_voidp)malloc((size_t)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FreeFunc(png_structp png_ptr, png_voidp ptr) {
|
||||||
|
(void)png_ptr;
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
// Converts the NULL terminated 'hexstring' which contains 2-byte character
|
// Converts the NULL terminated 'hexstring' which contains 2-byte character
|
||||||
// representations of hex values to raw data.
|
// representations of hex values to raw data.
|
||||||
// 'hexstring' may contain values consisting of [A-F][a-f][0-9] in pairs,
|
// 'hexstring' may contain values consisting of [A-F][a-f][0-9] in pairs,
|
||||||
@@ -172,11 +196,10 @@ static int ExtractMetadataFromPNG(png_structp png,
|
|||||||
{
|
{
|
||||||
png_charp name;
|
png_charp name;
|
||||||
int comp_type;
|
int comp_type;
|
||||||
#if ((PNG_LIBPNG_VER_MAJOR << 8) | PNG_LIBPNG_VER_MINOR << 0) < \
|
#if LOCAL_PNG_PREREQ(1,5)
|
||||||
((1 << 8) | (5 << 0))
|
|
||||||
png_charp profile;
|
|
||||||
#else // >= libpng 1.5.0
|
|
||||||
png_bytep profile;
|
png_bytep profile;
|
||||||
|
#else
|
||||||
|
png_charp profile;
|
||||||
#endif
|
#endif
|
||||||
png_uint_32 len;
|
png_uint_32 len;
|
||||||
|
|
||||||
@@ -186,7 +209,6 @@ static int ExtractMetadataFromPNG(png_structp png,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +220,9 @@ typedef struct {
|
|||||||
|
|
||||||
static void ReadFunc(png_structp png_ptr, png_bytep data, png_size_t length) {
|
static void ReadFunc(png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||||
PNGReadContext* const ctx = (PNGReadContext*)png_get_io_ptr(png_ptr);
|
PNGReadContext* const ctx = (PNGReadContext*)png_get_io_ptr(png_ptr);
|
||||||
assert(ctx->offset + length <= ctx->data_size);
|
if (ctx->data_size - ctx->offset < length) {
|
||||||
|
png_error(png_ptr, "ReadFunc: invalid read length (overflow)!");
|
||||||
|
}
|
||||||
memcpy(data, ctx->data + ctx->offset, length);
|
memcpy(data, ctx->data + ctx->offset, length);
|
||||||
ctx->offset += length;
|
ctx->offset += length;
|
||||||
}
|
}
|
||||||
@@ -216,13 +240,16 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
int p;
|
int p;
|
||||||
volatile int ok = 0;
|
volatile int ok = 0;
|
||||||
png_uint_32 width, height, y;
|
png_uint_32 width, height, y;
|
||||||
png_uint_32 stride;
|
int64_t stride;
|
||||||
uint8_t* volatile rgb = NULL;
|
uint8_t* volatile rgb = NULL;
|
||||||
|
|
||||||
|
if (data == NULL || data_size == 0 || pic == NULL) return 0;
|
||||||
|
|
||||||
context.data = data;
|
context.data = data;
|
||||||
context.data_size = data_size;
|
context.data_size = data_size;
|
||||||
|
|
||||||
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
|
png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL,
|
||||||
|
NULL, MallocFunc, FreeFunc);
|
||||||
if (png == NULL) goto End;
|
if (png == NULL) goto End;
|
||||||
|
|
||||||
png_set_error_fn(png, 0, error_function, NULL);
|
png_set_error_fn(png, 0, error_function, NULL);
|
||||||
@@ -232,6 +259,15 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LOCAL_PNG_PREREQ(1,5) || \
|
||||||
|
(LOCAL_PNG_PREREQ(1,4) && PNG_LIBPNG_VER_RELEASE >= 1)
|
||||||
|
// If it looks like the bitstream is going to need more memory than libpng's
|
||||||
|
// internal limit (default: 8M), try to (reasonably) raise it.
|
||||||
|
if (data_size > png_get_chunk_malloc_max(png) && data_size < (1u << 24)) {
|
||||||
|
png_set_chunk_malloc_max(png, data_size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
info = png_create_info_struct(png);
|
info = png_create_info_struct(png);
|
||||||
if (info == NULL) goto Error;
|
if (info == NULL) goto Error;
|
||||||
end_info = png_create_info_struct(png);
|
end_info = png_create_info_struct(png);
|
||||||
@@ -262,6 +298,16 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
|
has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply gamma correction if needed.
|
||||||
|
{
|
||||||
|
double image_gamma = 1 / 2.2, screen_gamma = 2.2;
|
||||||
|
int srgb_intent;
|
||||||
|
if (png_get_sRGB(png, info, &srgb_intent) ||
|
||||||
|
png_get_gAMA(png, info, &image_gamma)) {
|
||||||
|
png_set_gamma(png, screen_gamma, image_gamma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!keep_alpha) {
|
if (!keep_alpha) {
|
||||||
png_set_strip_alpha(png);
|
png_set_strip_alpha(png);
|
||||||
has_alpha = 0;
|
has_alpha = 0;
|
||||||
@@ -269,13 +315,20 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
|
|
||||||
num_passes = png_set_interlace_handling(png);
|
num_passes = png_set_interlace_handling(png);
|
||||||
png_read_update_info(png, info);
|
png_read_update_info(png, info);
|
||||||
stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb);
|
|
||||||
rgb = (uint8_t*)malloc(stride * height);
|
stride = (int64_t)(has_alpha ? 4 : 3) * width * sizeof(*rgb);
|
||||||
|
if (stride != (int)stride ||
|
||||||
|
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgb = (uint8_t*)malloc((size_t)stride * height);
|
||||||
if (rgb == NULL) goto Error;
|
if (rgb == NULL) goto Error;
|
||||||
for (p = 0; p < num_passes; ++p) {
|
for (p = 0; p < num_passes; ++p) {
|
||||||
|
png_bytep row = rgb;
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
png_bytep row = (png_bytep)(rgb + y * stride);
|
|
||||||
png_read_rows(png, &row, NULL, 1);
|
png_read_rows(png, &row, NULL, 1);
|
||||||
|
row += stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
png_read_end(png, end_info);
|
png_read_end(png, end_info);
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
//
|
//
|
||||||
// PNG decode.
|
// PNG decode.
|
||||||
|
|
||||||
#ifndef WEBP_EXAMPLES_PNGDEC_H_
|
#ifndef WEBP_IMAGEIO_PNGDEC_H_
|
||||||
#define WEBP_EXAMPLES_PNGDEC_H_
|
#define WEBP_IMAGEIO_PNGDEC_H_
|
||||||
|
|
||||||
#include "webp/types.h"
|
#include "webp/types.h"
|
||||||
|
|
||||||
@@ -34,4 +34,4 @@ int ReadPNG(const uint8_t* const data, size_t data_size,
|
|||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // WEBP_EXAMPLES_PNGDEC_H_
|
#endif // WEBP_IMAGEIO_PNGDEC_H_
|
||||||
296
imageio/pnmdec.c
Normal file
296
imageio/pnmdec.c
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
// Copyright 2017 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// (limited) PNM decoder
|
||||||
|
|
||||||
|
#include "./pnmdec.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "webp/encode.h"
|
||||||
|
#include "./imageio_util.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WIDTH_FLAG = 1 << 0,
|
||||||
|
HEIGHT_FLAG = 1 << 1,
|
||||||
|
DEPTH_FLAG = 1 << 2,
|
||||||
|
MAXVAL_FLAG = 1 << 3,
|
||||||
|
TUPLE_FLAG = 1 << 4,
|
||||||
|
ALL_NEEDED_FLAGS = WIDTH_FLAG | HEIGHT_FLAG | DEPTH_FLAG | MAXVAL_FLAG
|
||||||
|
} PNMFlags;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const uint8_t* data;
|
||||||
|
size_t data_size;
|
||||||
|
int width, height;
|
||||||
|
int bytes_per_px;
|
||||||
|
int depth; // 1 (grayscale), 2 (grayscale + alpha), 3 (rgb), 4 (rgba)
|
||||||
|
int max_value;
|
||||||
|
int type; // 5, 6 or 7
|
||||||
|
int seen_flags;
|
||||||
|
} PNMInfo;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// PNM decoding
|
||||||
|
|
||||||
|
#define MAX_LINE_SIZE 1024
|
||||||
|
static const size_t kMinPNMHeaderSize = 3;
|
||||||
|
|
||||||
|
static size_t ReadLine(const uint8_t* const data, size_t off, size_t data_size,
|
||||||
|
char out[MAX_LINE_SIZE + 1], size_t* const out_size) {
|
||||||
|
size_t i = 0;
|
||||||
|
*out_size = 0;
|
||||||
|
redo:
|
||||||
|
for (i = 0; i < MAX_LINE_SIZE && off < data_size; ++i) {
|
||||||
|
out[i] = data[off++];
|
||||||
|
if (out[i] == '\n') break;
|
||||||
|
}
|
||||||
|
if (off < data_size) {
|
||||||
|
if (i == 0) goto redo; // empty line
|
||||||
|
if (out[0] == '#') goto redo; // skip comment
|
||||||
|
}
|
||||||
|
out[i] = 0; // safety sentinel
|
||||||
|
*out_size = i;
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t FlagError(const char flag[]) {
|
||||||
|
fprintf(stderr, "PAM header error: flags '%s' already seen.\n", flag);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// inspired from http://netpbm.sourceforge.net/doc/pam.html
|
||||||
|
static size_t ReadPAMFields(PNMInfo* const info, size_t off) {
|
||||||
|
char out[MAX_LINE_SIZE + 1];
|
||||||
|
size_t out_size;
|
||||||
|
int tmp;
|
||||||
|
int expected_depth = -1;
|
||||||
|
assert(info != NULL);
|
||||||
|
while (1) {
|
||||||
|
off = ReadLine(info->data, off, info->data_size, out, &out_size);
|
||||||
|
if (off == 0) return 0;
|
||||||
|
if (sscanf(out, "WIDTH %d", &tmp) == 1) {
|
||||||
|
if (info->seen_flags & WIDTH_FLAG) return FlagError("WIDTH");
|
||||||
|
info->seen_flags |= WIDTH_FLAG;
|
||||||
|
info->width = tmp;
|
||||||
|
} else if (sscanf(out, "HEIGHT %d", &tmp) == 1) {
|
||||||
|
if (info->seen_flags & HEIGHT_FLAG) return FlagError("HEIGHT");
|
||||||
|
info->seen_flags |= HEIGHT_FLAG;
|
||||||
|
info->height = tmp;
|
||||||
|
} else if (sscanf(out, "DEPTH %d", &tmp) == 1) {
|
||||||
|
if (info->seen_flags & DEPTH_FLAG) return FlagError("DEPTH");
|
||||||
|
info->seen_flags |= DEPTH_FLAG;
|
||||||
|
info->depth = tmp;
|
||||||
|
} else if (sscanf(out, "MAXVAL %d", &tmp) == 1) {
|
||||||
|
if (info->seen_flags & MAXVAL_FLAG) return FlagError("MAXVAL");
|
||||||
|
info->seen_flags |= MAXVAL_FLAG;
|
||||||
|
info->max_value = tmp;
|
||||||
|
} else if (!strcmp(out, "TUPLTYPE RGB_ALPHA")) {
|
||||||
|
expected_depth = 4;
|
||||||
|
info->seen_flags |= TUPLE_FLAG;
|
||||||
|
} else if (!strcmp(out, "TUPLTYPE RGB")) {
|
||||||
|
expected_depth = 3;
|
||||||
|
info->seen_flags |= TUPLE_FLAG;
|
||||||
|
} else if (!strcmp(out, "TUPLTYPE GRAYSCALE_ALPHA")) {
|
||||||
|
expected_depth = 2;
|
||||||
|
info->seen_flags |= TUPLE_FLAG;
|
||||||
|
} else if (!strcmp(out, "TUPLTYPE GRAYSCALE")) {
|
||||||
|
expected_depth = 1;
|
||||||
|
info->seen_flags |= TUPLE_FLAG;
|
||||||
|
} else if (!strcmp(out, "ENDHDR")) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
static const char kEllipsis[] = " ...";
|
||||||
|
int i;
|
||||||
|
if (out_size > 20) sprintf(out + 20 - strlen(kEllipsis), kEllipsis);
|
||||||
|
for (i = 0; i < (int)strlen(out); ++i) {
|
||||||
|
// isprint() might trigger a "char-subscripts" warning if given a char.
|
||||||
|
if (!isprint((int)out[i])) out[i] = ' ';
|
||||||
|
}
|
||||||
|
fprintf(stderr, "PAM header error: unrecognized entry [%s]\n", out);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(info->seen_flags & ALL_NEEDED_FLAGS)) {
|
||||||
|
fprintf(stderr, "PAM header error: missing tags%s%s%s%s\n",
|
||||||
|
(info->seen_flags & WIDTH_FLAG) ? "" : " WIDTH",
|
||||||
|
(info->seen_flags & HEIGHT_FLAG) ? "" : " HEIGHT",
|
||||||
|
(info->seen_flags & DEPTH_FLAG) ? "" : " DEPTH",
|
||||||
|
(info->seen_flags & MAXVAL_FLAG) ? "" : " MAXVAL");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (expected_depth != -1 && info->depth != expected_depth) {
|
||||||
|
fprintf(stderr, "PAM header error: expected DEPTH %d but got DEPTH %d\n",
|
||||||
|
expected_depth, info->depth);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t ReadHeader(PNMInfo* const info) {
|
||||||
|
size_t off = 0;
|
||||||
|
char out[MAX_LINE_SIZE + 1];
|
||||||
|
size_t out_size;
|
||||||
|
if (info == NULL) return 0;
|
||||||
|
if (info->data == NULL || info->data_size < kMinPNMHeaderSize) return 0;
|
||||||
|
|
||||||
|
info->width = info->height = 0;
|
||||||
|
info->type = -1;
|
||||||
|
info->seen_flags = 0;
|
||||||
|
info->bytes_per_px = 0;
|
||||||
|
info->depth = 0;
|
||||||
|
info->max_value = 0;
|
||||||
|
|
||||||
|
off = ReadLine(info->data, off, info->data_size, out, &out_size);
|
||||||
|
if (off == 0 || sscanf(out, "P%d", &info->type) != 1) return 0;
|
||||||
|
if (info->type == 7) {
|
||||||
|
off = ReadPAMFields(info, off);
|
||||||
|
} else {
|
||||||
|
off = ReadLine(info->data, off, info->data_size, out, &out_size);
|
||||||
|
if (off == 0 || sscanf(out, "%d %d", &info->width, &info->height) != 2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
off = ReadLine(info->data, off, info->data_size, out, &out_size);
|
||||||
|
if (off == 0 || sscanf(out, "%d", &info->max_value) != 1) return 0;
|
||||||
|
|
||||||
|
// finish initializing missing fields
|
||||||
|
info->depth = (info->type == 5) ? 1 : 3;
|
||||||
|
}
|
||||||
|
// perform some basic numerical validation
|
||||||
|
if (info->width <= 0 || info->height <= 0 ||
|
||||||
|
info->type <= 0 || info->type >= 9 ||
|
||||||
|
info->depth <= 0 || info->depth > 4 ||
|
||||||
|
info->max_value <= 0 || info->max_value >= 65536) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
info->bytes_per_px = info->depth * (info->max_value > 255 ? 2 : 1);
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReadPNM(const uint8_t* const data, size_t data_size,
|
||||||
|
WebPPicture* const pic, int keep_alpha,
|
||||||
|
struct Metadata* const metadata) {
|
||||||
|
int ok = 0;
|
||||||
|
int i, j;
|
||||||
|
uint64_t stride, pixel_bytes, sample_size, depth;
|
||||||
|
uint8_t* rgb = NULL, *tmp_rgb;
|
||||||
|
size_t offset;
|
||||||
|
PNMInfo info;
|
||||||
|
|
||||||
|
info.data = data;
|
||||||
|
info.data_size = data_size;
|
||||||
|
offset = ReadHeader(&info);
|
||||||
|
if (offset == 0) {
|
||||||
|
fprintf(stderr, "Error parsing PNM header.\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.type < 5 || info.type > 7) {
|
||||||
|
fprintf(stderr, "Unsupported P%d PNM format.\n", info.type);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some basic validations.
|
||||||
|
if (pic == NULL) goto End;
|
||||||
|
if (info.width > WEBP_MAX_DIMENSION || info.height > WEBP_MAX_DIMENSION) {
|
||||||
|
fprintf(stderr, "Invalid %dx%d dimension for PNM\n",
|
||||||
|
info.width, info.height);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel_bytes = (uint64_t)info.width * info.height * info.bytes_per_px;
|
||||||
|
if (data_size < offset + pixel_bytes) {
|
||||||
|
fprintf(stderr, "Truncated PNM file (P%d).\n", info.type);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
sample_size = (info.max_value > 255) ? 2 : 1;
|
||||||
|
// final depth
|
||||||
|
depth = (info.depth == 1 || info.depth == 3 || !keep_alpha) ? 3 : 4;
|
||||||
|
stride = depth * info.width;
|
||||||
|
if (stride != (size_t)stride ||
|
||||||
|
!ImgIoUtilCheckSizeArgumentsOverflow(stride, info.height)) {
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgb = (uint8_t*)malloc((size_t)stride * info.height);
|
||||||
|
if (rgb == NULL) goto End;
|
||||||
|
|
||||||
|
// Convert input.
|
||||||
|
// We only optimize for the sample_size=1, max_value=255, depth=1 case.
|
||||||
|
tmp_rgb = rgb;
|
||||||
|
for (j = 0; j < info.height; ++j) {
|
||||||
|
const uint8_t* in = data + offset;
|
||||||
|
offset += info.bytes_per_px * info.width;
|
||||||
|
assert(offset <= data_size);
|
||||||
|
if (info.max_value == 255 && info.depth >= 3) {
|
||||||
|
// RGB or RGBA
|
||||||
|
if (info.depth == 3 || keep_alpha) {
|
||||||
|
memcpy(tmp_rgb, in, info.depth * info.width * sizeof(*in));
|
||||||
|
} else {
|
||||||
|
assert(info.depth == 4 && !keep_alpha);
|
||||||
|
for (i = 0; i < info.width; ++i) {
|
||||||
|
tmp_rgb[3 * i + 0] = in[4 * i + 0];
|
||||||
|
tmp_rgb[3 * i + 1] = in[4 * i + 1];
|
||||||
|
tmp_rgb[3 * i + 2] = in[4 * i + 2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unoptimized case, we need to handle non-trivial operations:
|
||||||
|
// * convert 16b to 8b (if max_value > 255)
|
||||||
|
// * rescale to [0..255] range (if max_value != 255)
|
||||||
|
// * drop the alpha channel (if keep_alpha is false)
|
||||||
|
const uint32_t round = info.max_value / 2;
|
||||||
|
int k = 0;
|
||||||
|
for (i = 0; i < info.width * info.depth; ++i) {
|
||||||
|
uint32_t v = (sample_size == 2) ? 256u * in[2 * i + 0] + in[2 * i + 1]
|
||||||
|
: in[i];
|
||||||
|
if (info.max_value != 255) v = (v * 255u + round) / info.max_value;
|
||||||
|
if (v > 255u) v = 255u;
|
||||||
|
if (info.depth > 2) {
|
||||||
|
if (!keep_alpha && info.depth == 4 && (i % 4) == 3) {
|
||||||
|
// skip alpha
|
||||||
|
} else {
|
||||||
|
tmp_rgb[k] = v;
|
||||||
|
k += 1;
|
||||||
|
}
|
||||||
|
} else if (info.depth == 1 || (i % 2) == 0) {
|
||||||
|
tmp_rgb[k + 0] = tmp_rgb[k + 1] = tmp_rgb[k + 2] = v;
|
||||||
|
k += 3;
|
||||||
|
} else if (keep_alpha && info.depth == 2) {
|
||||||
|
tmp_rgb[k] = v;
|
||||||
|
k += 1;
|
||||||
|
} else {
|
||||||
|
// skip alpha
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp_rgb += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebP conversion.
|
||||||
|
pic->width = info.width;
|
||||||
|
pic->height = info.height;
|
||||||
|
ok = (depth == 4) ? WebPPictureImportRGBA(pic, rgb, (int)stride)
|
||||||
|
: WebPPictureImportRGB(pic, rgb, (int)stride);
|
||||||
|
if (!ok) goto End;
|
||||||
|
|
||||||
|
ok = 1;
|
||||||
|
End:
|
||||||
|
free((void*)rgb);
|
||||||
|
|
||||||
|
(void)metadata;
|
||||||
|
(void)keep_alpha;
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
37
imageio/pnmdec.h
Normal file
37
imageio/pnmdec.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2017 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// partial PNM format decoder (ppm/pgm)
|
||||||
|
|
||||||
|
#ifndef WEBP_IMAGEIO_PNMDEC_H_
|
||||||
|
#define WEBP_IMAGEIO_PNMDEC_H_
|
||||||
|
|
||||||
|
#include "webp/types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Metadata;
|
||||||
|
struct WebPPicture;
|
||||||
|
|
||||||
|
// Reads a PNM file from 'data', returning the decoded output in 'pic'.
|
||||||
|
// The output is RGB or YUV depending on pic->use_argb value.
|
||||||
|
// Returns true on success.
|
||||||
|
// 'metadata' has no effect, but is kept for coherence with other signatures
|
||||||
|
// for image readers.
|
||||||
|
int ReadPNM(const uint8_t* const data, size_t data_size,
|
||||||
|
struct WebPPicture* const pic, int keep_alpha,
|
||||||
|
struct Metadata* const metadata);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WEBP_IMAGEIO_PNMDEC_H_
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "webp/config.h"
|
#include "webp/config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
#include <tiffio.h>
|
#include <tiffio.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
|
#include "./imageio_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
@@ -44,7 +46,7 @@ static int ExtractMetadataFromTIFF(TIFF* const tif, Metadata* const metadata) {
|
|||||||
(MetadataPayload*)((uint8_t*)metadata +
|
(MetadataPayload*)((uint8_t*)metadata +
|
||||||
kTIFFMetadataMap[i].storage_offset);
|
kTIFFMetadataMap[i].storage_offset);
|
||||||
void* tag_data;
|
void* tag_data;
|
||||||
uint32 tag_data_len;
|
uint32_t tag_data_len;
|
||||||
|
|
||||||
if (TIFFGetField(tif, kTIFFMetadataMap[i].tag, &tag_data_len, &tag_data) &&
|
if (TIFFGetField(tif, kTIFFMetadataMap[i].tag, &tag_data_len, &tag_data) &&
|
||||||
!MetadataCopy((const char*)tag_data, tag_data_len, payload)) {
|
!MetadataCopy((const char*)tag_data, tag_data_len, payload)) {
|
||||||
@@ -106,7 +108,7 @@ static void MyUnmapFile(thandle_t opaque, void* base, toff_t size) {
|
|||||||
static tsize_t MyRead(thandle_t opaque, void* dst, tsize_t size) {
|
static tsize_t MyRead(thandle_t opaque, void* dst, tsize_t size) {
|
||||||
MyData* const my_data = (MyData*)opaque;
|
MyData* const my_data = (MyData*)opaque;
|
||||||
if (my_data->pos + size > my_data->size) {
|
if (my_data->pos + size > my_data->size) {
|
||||||
size = my_data->size - my_data->pos;
|
size = (tsize_t)(my_data->size - my_data->pos);
|
||||||
}
|
}
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
memcpy(dst, my_data->data + my_data->pos, size);
|
memcpy(dst, my_data->data + my_data->pos, size);
|
||||||
@@ -115,18 +117,62 @@ static tsize_t MyRead(thandle_t opaque, void* dst, tsize_t size) {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unmultiply Argb data. Taken from dsp/alpha_processing
|
||||||
|
// (we don't want to force a dependency to a libdspdec library).
|
||||||
|
#define MFIX 24 // 24bit fixed-point arithmetic
|
||||||
|
#define HALF ((1u << MFIX) >> 1)
|
||||||
|
|
||||||
|
static uint32_t Unmult(uint8_t x, uint32_t mult) {
|
||||||
|
const uint32_t v = (x * mult + HALF) >> MFIX;
|
||||||
|
return (v > 255u) ? 255u : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE uint32_t GetScale(uint32_t a) {
|
||||||
|
return (255u << MFIX) / a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MFIX
|
||||||
|
#undef HALF
|
||||||
|
|
||||||
|
static void MultARGBRow(uint8_t* ptr, int width) {
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < width; ++x, ptr += 4) {
|
||||||
|
const uint32_t alpha = ptr[3];
|
||||||
|
if (alpha < 255) {
|
||||||
|
if (alpha == 0) { // alpha == 0
|
||||||
|
ptr[0] = ptr[1] = ptr[2] = 0;
|
||||||
|
} else {
|
||||||
|
const uint32_t scale = GetScale(alpha);
|
||||||
|
ptr[0] = Unmult(ptr[0], scale);
|
||||||
|
ptr[1] = Unmult(ptr[1], scale);
|
||||||
|
ptr[2] = Unmult(ptr[2], scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ReadTIFF(const uint8_t* const data, size_t data_size,
|
int ReadTIFF(const uint8_t* const data, size_t data_size,
|
||||||
WebPPicture* const pic, int keep_alpha,
|
WebPPicture* const pic, int keep_alpha,
|
||||||
Metadata* const metadata) {
|
Metadata* const metadata) {
|
||||||
MyData my_data = { data, (toff_t)data_size, 0 };
|
MyData my_data = { data, (toff_t)data_size, 0 };
|
||||||
TIFF* const tif = TIFFClientOpen("Memory", "r", &my_data,
|
TIFF* tif;
|
||||||
MyRead, MyRead, MySeek, MyClose,
|
uint32_t image_width, image_height, tile_width, tile_height;
|
||||||
MySize, MyMapFile, MyUnmapFile);
|
uint64_t stride;
|
||||||
uint32 width, height;
|
uint16_t samples_per_px = 0;
|
||||||
uint32* raster;
|
uint16_t extra_samples = 0;
|
||||||
|
uint16_t* extra_samples_ptr = NULL;
|
||||||
|
uint32_t* raster;
|
||||||
|
int64_t alloc_size;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
tdir_t dircount;
|
tdir_t dircount;
|
||||||
|
|
||||||
|
if (data == NULL || data_size == 0 || data_size > INT_MAX || pic == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tif = TIFFClientOpen("Memory", "r", &my_data,
|
||||||
|
MyRead, MyRead, MySeek, MyClose,
|
||||||
|
MySize, MyMapFile, MyUnmapFile);
|
||||||
if (tif == NULL) {
|
if (tif == NULL) {
|
||||||
fprintf(stderr, "Error! Cannot parse TIFF file\n");
|
fprintf(stderr, "Error! Cannot parse TIFF file\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -138,26 +184,75 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
"Only the first will be used, %d will be ignored.\n",
|
"Only the first will be used, %d will be ignored.\n",
|
||||||
dircount - 1);
|
dircount - 1);
|
||||||
}
|
}
|
||||||
|
if (!TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_px)) {
|
||||||
|
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 (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) &&
|
if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width) &&
|
||||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))) {
|
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height))) {
|
||||||
fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
|
fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
|
||||||
goto End;
|
goto End;
|
||||||
}
|
}
|
||||||
raster = (uint32*)_TIFFmalloc(width * height * sizeof(*raster));
|
stride = (uint64_t)image_width * sizeof(*raster);
|
||||||
|
if (!ImgIoUtilCheckSizeArgumentsOverflow(stride, image_height)) {
|
||||||
|
fprintf(stderr, "Error! TIFF image dimension (%d x %d) is too large.\n",
|
||||||
|
image_width, image_height);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
// According to spec, a tile can be bigger than the image. However it should
|
||||||
|
// be a multiple of 16 and not way too large, so check that it's not more
|
||||||
|
// than twice the image size, for dimensions above some arbitrary minimum
|
||||||
|
// 32. We also check that they respect WebP's dimension and memory limit.
|
||||||
|
// Note that a tile can be 6byte/px in some cases. Here we assume
|
||||||
|
// 4byte/px with sizeof(*raster), to be conservative.
|
||||||
|
if (TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width) &&
|
||||||
|
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height)) {
|
||||||
|
if ((tile_width > 32 && tile_width / 2 > image_width) ||
|
||||||
|
(tile_height > 32 && tile_height / 2 > image_height) ||
|
||||||
|
ImgIoUtilCheckSizeArgumentsOverflow(
|
||||||
|
(uint64_t)tile_width * sizeof(*raster), tile_height)) {
|
||||||
|
fprintf(stderr, "Error! TIFF tile dimension (%d x %d) is too large.\n",
|
||||||
|
tile_width, tile_height);
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (samples_per_px > 3 && !TIFFGetField(tif, TIFFTAG_EXTRASAMPLES,
|
||||||
|
&extra_samples, &extra_samples_ptr)) {
|
||||||
|
fprintf(stderr, "Error! Cannot retrieve TIFF ExtraSamples info.\n");
|
||||||
|
goto End;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _Tiffmalloc uses a signed type for size.
|
||||||
|
alloc_size = (int64_t)(stride * image_height);
|
||||||
|
if (alloc_size < 0 || alloc_size != (tsize_t)alloc_size) goto End;
|
||||||
|
|
||||||
|
raster = (uint32_t*)_TIFFmalloc((tsize_t)alloc_size);
|
||||||
if (raster != NULL) {
|
if (raster != NULL) {
|
||||||
if (TIFFReadRGBAImageOriented(tif, width, height, raster,
|
if (TIFFReadRGBAImageOriented(tif, image_width, image_height, raster,
|
||||||
ORIENTATION_TOPLEFT, 1)) {
|
ORIENTATION_TOPLEFT, 1)) {
|
||||||
const int stride = width * sizeof(*raster);
|
pic->width = image_width;
|
||||||
pic->width = width;
|
pic->height = image_height;
|
||||||
pic->height = height;
|
|
||||||
// TIFF data is ABGR
|
// TIFF data is ABGR
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
TIFFSwabArrayOfLong(raster, width * height);
|
TIFFSwabArrayOfLong(raster, image_width * image_height);
|
||||||
#endif
|
#endif
|
||||||
|
// if we have an alpha channel, we must un-multiply from rgbA to RGBA
|
||||||
|
if (extra_samples == 1 && extra_samples_ptr != NULL &&
|
||||||
|
extra_samples_ptr[0] == EXTRASAMPLE_ASSOCALPHA) {
|
||||||
|
uint32_t y;
|
||||||
|
uint8_t* tmp = (uint8_t*)raster;
|
||||||
|
for (y = 0; y < image_height; ++y) {
|
||||||
|
MultARGBRow(tmp, image_width);
|
||||||
|
tmp += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
ok = keep_alpha
|
ok = keep_alpha
|
||||||
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
|
? WebPPictureImportRGBA(pic, (const uint8_t*)raster, (int)stride)
|
||||||
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);
|
: WebPPictureImportRGBX(pic, (const uint8_t*)raster, (int)stride);
|
||||||
}
|
}
|
||||||
_TIFFfree(raster);
|
_TIFFfree(raster);
|
||||||
} else {
|
} else {
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
//
|
//
|
||||||
// TIFF decode.
|
// TIFF decode.
|
||||||
|
|
||||||
#ifndef WEBP_EXAMPLES_TIFFDEC_H_
|
#ifndef WEBP_IMAGEIO_TIFFDEC_H_
|
||||||
#define WEBP_EXAMPLES_TIFFDEC_H_
|
#define WEBP_IMAGEIO_TIFFDEC_H_
|
||||||
|
|
||||||
#include "webp/types.h"
|
#include "webp/types.h"
|
||||||
|
|
||||||
@@ -34,4 +34,4 @@ int ReadTIFF(const uint8_t* const data, size_t data_size,
|
|||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // WEBP_EXAMPLES_TIFFDEC_H_
|
#endif // WEBP_IMAGEIO_TIFFDEC_H_
|
||||||
244
imageio/webpdec.c
Normal file
244
imageio/webpdec.c
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
// Copyright 2014 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// WebP decode.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "webp/config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "./webpdec.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "webp/decode.h"
|
||||||
|
#include "webp/demux.h"
|
||||||
|
#include "webp/encode.h"
|
||||||
|
#include "../examples/unicode.h"
|
||||||
|
#include "./imageio_util.h"
|
||||||
|
#include "./metadata.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// WebP decoding
|
||||||
|
|
||||||
|
static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = {
|
||||||
|
"OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
|
||||||
|
"UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
|
||||||
|
};
|
||||||
|
|
||||||
|
static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
|
||||||
|
if (config->input.has_animation) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error! Decoding of an animated WebP file is not supported.\n"
|
||||||
|
" Use webpmux to extract the individual frames or\n"
|
||||||
|
" vwebp to view this image.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintWebPError(const char* const in_file, int status) {
|
||||||
|
WFPRINTF(stderr, "Decoding of %s failed.\n", (const W_CHAR*)in_file);
|
||||||
|
fprintf(stderr, "Status: %d", status);
|
||||||
|
if (status >= VP8_STATUS_OK && status <= VP8_STATUS_NOT_ENOUGH_DATA) {
|
||||||
|
fprintf(stderr, "(%s)", kStatusMessages[status]);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int LoadWebP(const char* const in_file,
|
||||||
|
const uint8_t** data, size_t* data_size,
|
||||||
|
WebPBitstreamFeatures* bitstream) {
|
||||||
|
VP8StatusCode status;
|
||||||
|
WebPBitstreamFeatures local_features;
|
||||||
|
if (!ImgIoUtilReadFile(in_file, data, data_size)) return 0;
|
||||||
|
|
||||||
|
if (bitstream == NULL) {
|
||||||
|
bitstream = &local_features;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = WebPGetFeatures(*data, *data_size, bitstream);
|
||||||
|
if (status != VP8_STATUS_OK) {
|
||||||
|
WebPFree((void*)*data);
|
||||||
|
*data = NULL;
|
||||||
|
*data_size = 0;
|
||||||
|
PrintWebPError(in_file, status);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
VP8StatusCode DecodeWebP(const uint8_t* const data, size_t data_size,
|
||||||
|
WebPDecoderConfig* const config) {
|
||||||
|
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
||||||
|
PrintAnimationWarning(config);
|
||||||
|
return WebPDecode(data, data_size, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
VP8StatusCode DecodeWebPIncremental(
|
||||||
|
const uint8_t* const data, size_t data_size,
|
||||||
|
WebPDecoderConfig* const config) {
|
||||||
|
VP8StatusCode status = VP8_STATUS_OK;
|
||||||
|
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
||||||
|
|
||||||
|
PrintAnimationWarning(config);
|
||||||
|
|
||||||
|
// Decoding call.
|
||||||
|
{
|
||||||
|
WebPIDecoder* const idec = WebPIDecode(data, data_size, config);
|
||||||
|
if (idec == NULL) {
|
||||||
|
fprintf(stderr, "Failed during WebPIDecode().\n");
|
||||||
|
return VP8_STATUS_OUT_OF_MEMORY;
|
||||||
|
} else {
|
||||||
|
status = WebPIUpdate(idec, data, data_size);
|
||||||
|
WebPIDelete(idec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Metadata
|
||||||
|
|
||||||
|
static int ExtractMetadata(const uint8_t* const data, size_t data_size,
|
||||||
|
Metadata* const metadata) {
|
||||||
|
WebPData webp_data = { data, data_size };
|
||||||
|
WebPDemuxer* const demux = WebPDemux(&webp_data);
|
||||||
|
WebPChunkIterator chunk_iter;
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
if (demux == NULL) return 0;
|
||||||
|
assert(metadata != NULL);
|
||||||
|
|
||||||
|
flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS);
|
||||||
|
|
||||||
|
if ((flags & ICCP_FLAG) && WebPDemuxGetChunk(demux, "ICCP", 1, &chunk_iter)) {
|
||||||
|
MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size,
|
||||||
|
&metadata->iccp);
|
||||||
|
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||||
|
}
|
||||||
|
if ((flags & EXIF_FLAG) && WebPDemuxGetChunk(demux, "EXIF", 1, &chunk_iter)) {
|
||||||
|
MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size,
|
||||||
|
&metadata->exif);
|
||||||
|
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||||
|
}
|
||||||
|
if ((flags & XMP_FLAG) && WebPDemuxGetChunk(demux, "XMP ", 1, &chunk_iter)) {
|
||||||
|
MetadataCopy((const char*)chunk_iter.chunk.bytes, chunk_iter.chunk.size,
|
||||||
|
&metadata->xmp);
|
||||||
|
WebPDemuxReleaseChunkIterator(&chunk_iter);
|
||||||
|
}
|
||||||
|
WebPDemuxDelete(demux);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int ReadWebP(const uint8_t* const data, size_t data_size,
|
||||||
|
WebPPicture* const pic,
|
||||||
|
int keep_alpha, Metadata* const metadata) {
|
||||||
|
int ok = 0;
|
||||||
|
VP8StatusCode status = VP8_STATUS_OK;
|
||||||
|
WebPDecoderConfig config;
|
||||||
|
WebPDecBuffer* const output_buffer = &config.output;
|
||||||
|
WebPBitstreamFeatures* const bitstream = &config.input;
|
||||||
|
|
||||||
|
if (data == NULL || data_size == 0 || pic == NULL) return 0;
|
||||||
|
|
||||||
|
if (!WebPInitDecoderConfig(&config)) {
|
||||||
|
fprintf(stderr, "Library version mismatch!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = WebPGetFeatures(data, data_size, bitstream);
|
||||||
|
if (status != VP8_STATUS_OK) {
|
||||||
|
PrintWebPError("input data", status);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
const int has_alpha = keep_alpha && bitstream->has_alpha;
|
||||||
|
uint64_t stride;
|
||||||
|
pic->width = bitstream->width;
|
||||||
|
pic->height = bitstream->height;
|
||||||
|
if (pic->use_argb) {
|
||||||
|
stride = (uint64_t)bitstream->width * 4;
|
||||||
|
} else {
|
||||||
|
stride = (uint64_t)bitstream->width * (has_alpha ? 5 : 3) / 2;
|
||||||
|
pic->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImgIoUtilCheckSizeArgumentsOverflow(stride, bitstream->height)) {
|
||||||
|
status = VP8_STATUS_OUT_OF_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = WebPPictureAlloc(pic);
|
||||||
|
if (!ok) {
|
||||||
|
status = VP8_STATUS_OUT_OF_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pic->use_argb) {
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
output_buffer->colorspace = MODE_ARGB;
|
||||||
|
#else
|
||||||
|
output_buffer->colorspace = MODE_BGRA;
|
||||||
|
#endif
|
||||||
|
output_buffer->u.RGBA.rgba = (uint8_t*)pic->argb;
|
||||||
|
output_buffer->u.RGBA.stride = pic->argb_stride * sizeof(uint32_t);
|
||||||
|
output_buffer->u.RGBA.size = output_buffer->u.RGBA.stride * pic->height;
|
||||||
|
} else {
|
||||||
|
output_buffer->colorspace = has_alpha ? MODE_YUVA : MODE_YUV;
|
||||||
|
output_buffer->u.YUVA.y = pic->y;
|
||||||
|
output_buffer->u.YUVA.u = pic->u;
|
||||||
|
output_buffer->u.YUVA.v = pic->v;
|
||||||
|
output_buffer->u.YUVA.a = has_alpha ? pic->a : NULL;
|
||||||
|
output_buffer->u.YUVA.y_stride = pic->y_stride;
|
||||||
|
output_buffer->u.YUVA.u_stride = pic->uv_stride;
|
||||||
|
output_buffer->u.YUVA.v_stride = pic->uv_stride;
|
||||||
|
output_buffer->u.YUVA.a_stride = has_alpha ? pic->a_stride : 0;
|
||||||
|
output_buffer->u.YUVA.y_size = pic->height * pic->y_stride;
|
||||||
|
output_buffer->u.YUVA.u_size = (pic->height + 1) / 2 * pic->uv_stride;
|
||||||
|
output_buffer->u.YUVA.v_size = (pic->height + 1) / 2 * pic->uv_stride;
|
||||||
|
output_buffer->u.YUVA.a_size = pic->height * pic->a_stride;
|
||||||
|
}
|
||||||
|
output_buffer->is_external_memory = 1;
|
||||||
|
|
||||||
|
status = DecodeWebP(data, data_size, &config);
|
||||||
|
ok = (status == VP8_STATUS_OK);
|
||||||
|
if (ok && !keep_alpha && pic->use_argb) {
|
||||||
|
// Need to wipe out the alpha value, as requested.
|
||||||
|
int x, y;
|
||||||
|
uint32_t* argb = pic->argb;
|
||||||
|
for (y = 0; y < pic->height; ++y) {
|
||||||
|
for (x = 0; x < pic->width; ++x) argb[x] |= 0xff000000u;
|
||||||
|
argb += pic->argb_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (0); // <- so we can 'break' out of the loop
|
||||||
|
|
||||||
|
if (status != VP8_STATUS_OK) {
|
||||||
|
PrintWebPError("input data", status);
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebPFreeDecBuffer(output_buffer);
|
||||||
|
|
||||||
|
if (ok && metadata != NULL) {
|
||||||
|
ok = ExtractMetadata(data, data_size, metadata);
|
||||||
|
if (!ok) {
|
||||||
|
PrintWebPError("metadata", VP8_STATUS_BITSTREAM_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) WebPPictureFree(pic);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
67
imageio/webpdec.h
Normal file
67
imageio/webpdec.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// Copyright 2014 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.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// WebP decode.
|
||||||
|
|
||||||
|
#ifndef WEBP_IMAGEIO_WEBPDEC_H_
|
||||||
|
#define WEBP_IMAGEIO_WEBPDEC_H_
|
||||||
|
|
||||||
|
#include "webp/decode.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Metadata;
|
||||||
|
struct WebPPicture;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// WebP decoding
|
||||||
|
|
||||||
|
// Prints an informative error message regarding decode failure of 'in_file'.
|
||||||
|
// 'status' is treated as a VP8StatusCode and if valid will be printed as a
|
||||||
|
// text string.
|
||||||
|
void PrintWebPError(const char* const in_file, int status);
|
||||||
|
|
||||||
|
// Reads a WebP from 'in_file', returning the contents and size in 'data' and
|
||||||
|
// 'data_size'. If not NULL, 'bitstream' is populated using WebPGetFeatures().
|
||||||
|
// Returns true on success.
|
||||||
|
int LoadWebP(const char* const in_file,
|
||||||
|
const uint8_t** data, size_t* data_size,
|
||||||
|
WebPBitstreamFeatures* bitstream);
|
||||||
|
|
||||||
|
// Decodes the WebP contained in 'data'.
|
||||||
|
// 'config' is a structure previously initialized by WebPInitDecoderConfig().
|
||||||
|
// 'config->output' should have the desired colorspace selected.
|
||||||
|
// Returns the decoder status. On success 'config->output' will contain the
|
||||||
|
// decoded picture.
|
||||||
|
VP8StatusCode DecodeWebP(const uint8_t* const data, size_t data_size,
|
||||||
|
WebPDecoderConfig* const config);
|
||||||
|
|
||||||
|
// Same as DecodeWebP(), but using the incremental decoder.
|
||||||
|
VP8StatusCode DecodeWebPIncremental(
|
||||||
|
const uint8_t* const data, size_t data_size,
|
||||||
|
WebPDecoderConfig* const config);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Decodes a WebP contained in 'data', returning the decoded output in 'pic'.
|
||||||
|
// Output is RGBA or YUVA, depending on pic->use_argb value.
|
||||||
|
// If 'keep_alpha' is true and the WebP has an alpha channel, the output is RGBA
|
||||||
|
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
||||||
|
// Returns true on success.
|
||||||
|
int ReadWebP(const uint8_t* const data, size_t data_size,
|
||||||
|
struct WebPPicture* const pic,
|
||||||
|
int keep_alpha, struct Metadata* const metadata);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WEBP_IMAGEIO_WEBPDEC_H_
|
||||||
@@ -29,12 +29,14 @@
|
|||||||
// code with COBJMACROS.
|
// code with COBJMACROS.
|
||||||
#include <ole2.h> // CreateStreamOnHGlobal()
|
#include <ole2.h> // CreateStreamOnHGlobal()
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
|
#include <tchar.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <wincodec.h>
|
#include <wincodec.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "../examples/unicode.h"
|
||||||
#include "./example_util.h"
|
#include "./imageio_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
#include "webp/encode.h"
|
||||||
|
|
||||||
#define IFS(fn) \
|
#define IFS(fn) \
|
||||||
do { \
|
do { \
|
||||||
@@ -85,10 +87,10 @@ WEBP_DEFINE_GUID(GUID_WICPixelFormat64bppRGBA_,
|
|||||||
|
|
||||||
static HRESULT OpenInputStream(const char* filename, IStream** stream) {
|
static HRESULT OpenInputStream(const char* filename, IStream** stream) {
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!strcmp(filename, "-")) {
|
if (!WSTRCMP(filename, "-")) {
|
||||||
const uint8_t* data = NULL;
|
const uint8_t* data = NULL;
|
||||||
size_t data_size = 0;
|
size_t data_size = 0;
|
||||||
const int ok = ExUtilReadFile(filename, &data, &data_size);
|
const int ok = ImgIoUtilReadFile(filename, &data, &data_size);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
HGLOBAL image = GlobalAlloc(GMEM_MOVEABLE, data_size);
|
HGLOBAL image = GlobalAlloc(GMEM_MOVEABLE, data_size);
|
||||||
if (image != NULL) {
|
if (image != NULL) {
|
||||||
@@ -108,11 +110,12 @@ static HRESULT OpenInputStream(const char* filename, IStream** stream) {
|
|||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IFS(SHCreateStreamOnFileA(filename, STGM_READ, stream));
|
IFS(SHCreateStreamOnFile((const LPTSTR)filename, STGM_READ, stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
fprintf(stderr, "Error opening input file %s (%08lx)\n", filename, hr);
|
_ftprintf(stderr, _T("Error opening input file %s (%08lx)\n"),
|
||||||
|
(const LPTSTR)filename, hr);
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@@ -131,7 +134,10 @@ static HRESULT ExtractICCP(IWICImagingFactory* const factory,
|
|||||||
IWICColorContext** color_contexts;
|
IWICColorContext** color_contexts;
|
||||||
|
|
||||||
IFS(IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count));
|
IFS(IWICBitmapFrameDecode_GetColorContexts(frame, 0, NULL, &count));
|
||||||
if (FAILED(hr) || count == 0) return hr;
|
if (FAILED(hr) || count == 0) {
|
||||||
|
// Treat unsupported operation as a non-fatal error. See crbug.com/webp/506.
|
||||||
|
return (hr == WINCODEC_ERR_UNSUPPORTEDOPERATION) ? S_OK : hr;
|
||||||
|
}
|
||||||
|
|
||||||
color_contexts = (IWICColorContext**)calloc(count, sizeof(*color_contexts));
|
color_contexts = (IWICColorContext**)calloc(count, sizeof(*color_contexts));
|
||||||
if (color_contexts == NULL) return E_OUTOFMEMORY;
|
if (color_contexts == NULL) return E_OUTOFMEMORY;
|
||||||
@@ -267,14 +273,21 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
WICPixelFormatGUID src_pixel_format = GUID_WICPixelFormatUndefined;
|
WICPixelFormatGUID src_pixel_format = GUID_WICPixelFormatUndefined;
|
||||||
const WICFormatImporter* importer = NULL;
|
const WICFormatImporter* importer = NULL;
|
||||||
GUID src_container_format = GUID_NULL_;
|
GUID src_container_format = GUID_NULL_;
|
||||||
|
// From Windows Kits\10\Include\10.0.19041.0\um\wincodec.h
|
||||||
|
WEBP_DEFINE_GUID(GUID_ContainerFormatWebp_,
|
||||||
|
0xe094b0e2, 0x67f2, 0x45b3,
|
||||||
|
0xb0, 0xea, 0x11, 0x53, 0x37, 0xca, 0x7c, 0xf3);
|
||||||
static const GUID* kAlphaContainers[] = {
|
static const GUID* kAlphaContainers[] = {
|
||||||
&GUID_ContainerFormatBmp,
|
&GUID_ContainerFormatBmp,
|
||||||
&GUID_ContainerFormatPng,
|
&GUID_ContainerFormatPng,
|
||||||
&GUID_ContainerFormatTiff,
|
&GUID_ContainerFormatTiff,
|
||||||
|
&GUID_ContainerFormatWebp_,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
int has_alpha = 0;
|
int has_alpha = 0;
|
||||||
int stride;
|
int64_t stride;
|
||||||
|
|
||||||
|
if (filename == NULL || pic == NULL) return 0;
|
||||||
|
|
||||||
IFS(CoInitialize(NULL));
|
IFS(CoInitialize(NULL));
|
||||||
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
||||||
@@ -293,9 +306,15 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
factory, stream, NULL,
|
factory, stream, NULL,
|
||||||
WICDecodeMetadataCacheOnDemand, &decoder));
|
WICDecodeMetadataCacheOnDemand, &decoder));
|
||||||
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
|
IFS(IWICBitmapDecoder_GetFrameCount(decoder, &frame_count));
|
||||||
if (SUCCEEDED(hr) && frame_count == 0) {
|
if (SUCCEEDED(hr)) {
|
||||||
fprintf(stderr, "No frame found in input file.\n");
|
if (frame_count == 0) {
|
||||||
hr = E_FAIL;
|
fprintf(stderr, "No frame found in input file.\n");
|
||||||
|
hr = E_FAIL;
|
||||||
|
} else if (frame_count > 1) {
|
||||||
|
// WIC will be tried before native WebP decoding so avoid duplicating the
|
||||||
|
// error message.
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
IFS(IWICBitmapDecoder_GetFrame(decoder, 0, &frame));
|
IFS(IWICBitmapDecoder_GetFrame(decoder, 0, &frame));
|
||||||
IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format));
|
IFS(IWICBitmapFrameDecode_GetPixelFormat(frame, &src_pixel_format));
|
||||||
@@ -334,14 +353,19 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
|
|
||||||
// Decode.
|
// Decode.
|
||||||
IFS(IWICFormatConverter_GetSize(converter, &width, &height));
|
IFS(IWICFormatConverter_GetSize(converter, &width, &height));
|
||||||
stride = importer->bytes_per_pixel * width * sizeof(*rgb);
|
stride = (int64_t)importer->bytes_per_pixel * width * sizeof(*rgb);
|
||||||
|
if (stride != (int)stride ||
|
||||||
|
!ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
rgb = (BYTE*)malloc(stride * height);
|
rgb = (BYTE*)malloc((size_t)stride * height);
|
||||||
if (rgb == NULL)
|
if (rgb == NULL)
|
||||||
hr = E_OUTOFMEMORY;
|
hr = E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
IFS(IWICFormatConverter_CopyPixels(converter, NULL,
|
IFS(IWICFormatConverter_CopyPixels(converter, NULL,
|
||||||
stride, stride * height, rgb));
|
(UINT)stride, (UINT)stride * height, rgb));
|
||||||
|
|
||||||
// WebP conversion.
|
// WebP conversion.
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
@@ -349,7 +373,7 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
pic->width = width;
|
pic->width = width;
|
||||||
pic->height = height;
|
pic->height = height;
|
||||||
pic->use_argb = 1; // For WIC, we always force to argb
|
pic->use_argb = 1; // For WIC, we always force to argb
|
||||||
ok = importer->import(pic, rgb, stride);
|
ok = importer->import(pic, rgb, (int)stride);
|
||||||
if (!ok) hr = E_FAIL;
|
if (!ok) hr = E_FAIL;
|
||||||
}
|
}
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
//
|
//
|
||||||
// Windows Imaging Component (WIC) decode.
|
// Windows Imaging Component (WIC) decode.
|
||||||
|
|
||||||
#ifndef WEBP_EXAMPLES_WICDEC_H_
|
#ifndef WEBP_IMAGEIO_WICDEC_H_
|
||||||
#define WEBP_EXAMPLES_WICDEC_H_
|
#define WEBP_IMAGEIO_WICDEC_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -31,4 +31,4 @@ int ReadPictureWithWIC(const char* const filename,
|
|||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // WEBP_EXAMPLES_WICDEC_H_
|
#endif // WEBP_IMAGEIO_WICDEC_H_
|
||||||
106
infra/common.sh
Normal file
106
infra/common.sh
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# Copyright (c) 2021, Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of Google nor the names of its contributors may
|
||||||
|
# be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
log_err() {
|
||||||
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Create build directory. Build directory will be deleted if it exists.
|
||||||
|
# Arguments:
|
||||||
|
# None.
|
||||||
|
# Returns:
|
||||||
|
# mkdir result.
|
||||||
|
#######################################
|
||||||
|
make_build_dir() {
|
||||||
|
if [[ "$#" -ne 1 ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local build_dir
|
||||||
|
build_dir="$1"
|
||||||
|
rm -rf "${build_dir}"
|
||||||
|
mkdir -p "${build_dir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Cleanup files from the build directory.
|
||||||
|
# Globals:
|
||||||
|
# LIBWEBP_ROOT repository's root path.
|
||||||
|
# Arguments:
|
||||||
|
# $1 build directory.
|
||||||
|
#######################################
|
||||||
|
cleanup() {
|
||||||
|
# $1 is not completely removed to allow for binary artifacts to be
|
||||||
|
# extracted.
|
||||||
|
find "${1:?"Build directory not defined"}" \
|
||||||
|
\( -name "*.[ao]" -o -name "*.l[ao]" \) -exec rm -f {} +
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Setup ccache for toolchain.
|
||||||
|
# Globals:
|
||||||
|
# PATH
|
||||||
|
# Arguments:
|
||||||
|
# None.
|
||||||
|
#######################################
|
||||||
|
setup_ccache() {
|
||||||
|
if [[ -x "$(command -v ccache)" ]]; then
|
||||||
|
export CCACHE_CPP2=yes
|
||||||
|
export PATH="/usr/lib/ccache:${PATH}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Detects whether test block should be run in the current test shard.
|
||||||
|
# Globals:
|
||||||
|
# TEST_TOTAL_SHARDS: Valid range: [1, N]. Defaults to 1.
|
||||||
|
# TEST_SHARD_INDEX: Valid range: [0, TEST_TOTAL_SHARDS). Defaults to 0.
|
||||||
|
# libwebp_test_id: current test number; incremented with each call.
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Returns:
|
||||||
|
# true if the shard is active
|
||||||
|
# false if the shard is inactive
|
||||||
|
#######################################
|
||||||
|
shard_should_run() {
|
||||||
|
TEST_TOTAL_SHARDS=${TEST_TOTAL_SHARDS:=1}
|
||||||
|
TEST_SHARD_INDEX=${TEST_SHARD_INDEX:=0}
|
||||||
|
libwebp_test_id=${libwebp_test_id:=-1}
|
||||||
|
: $((libwebp_test_id += 1))
|
||||||
|
|
||||||
|
if [[ "${TEST_SHARD_INDEX}" -lt 0 ||
|
||||||
|
"${TEST_SHARD_INDEX}" -ge "${TEST_TOTAL_SHARDS}" ]]; then
|
||||||
|
log_err "Invalid TEST_SHARD_INDEX (${TEST_SHARD_INDEX})!" \
|
||||||
|
"Expected [0, ${TEST_TOTAL_SHARDS})."
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ "$((libwebp_test_id % TEST_TOTAL_SHARDS))" -eq "${TEST_SHARD_INDEX}" ]]
|
||||||
|
}
|
||||||
401
infra/compile.sh
Executable file
401
infra/compile.sh
Executable file
@@ -0,0 +1,401 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Copyright (c) 2021, Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of Google nor the names of its contributors may
|
||||||
|
# be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
set -xe
|
||||||
|
LIBWEBP_ROOT="$(realpath "$(dirname "$0")/..")"
|
||||||
|
WORKSPACE=${WORKSPACE:-"$(mktemp -d -t webp.XXX)"}
|
||||||
|
|
||||||
|
# shellcheck source=infra/common.sh
|
||||||
|
source "${LIBWEBP_ROOT}/infra/common.sh"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat << EOF
|
||||||
|
Usage: compile.sh BUILD_TYPE TARGET
|
||||||
|
Options:
|
||||||
|
BUILD_TYPE supported build type: (shared, static, static-debug)
|
||||||
|
TARGET supported target platforms:
|
||||||
|
aarch64-linux-clang
|
||||||
|
aarch64-linux-gnu
|
||||||
|
arm-linux-gnueabi
|
||||||
|
arm-neon-linux-gnueabi
|
||||||
|
cmake
|
||||||
|
cmake-aarch64
|
||||||
|
cmake-arm
|
||||||
|
cmake-clang
|
||||||
|
disable-near-lossless
|
||||||
|
disable-sse4.1
|
||||||
|
disable-stats
|
||||||
|
force-aligned-32
|
||||||
|
force-aligned-64
|
||||||
|
gradle
|
||||||
|
i686-linux-asan
|
||||||
|
i686-linux-clang
|
||||||
|
i686-linux-gnu
|
||||||
|
i686-w64-mingw32
|
||||||
|
mips2el-linux-gnu
|
||||||
|
mips32dspr2el-linux-gnu
|
||||||
|
mips32eb-linux-gnu
|
||||||
|
mips32el-linux-gnu
|
||||||
|
mips32r2el-linux-gnu
|
||||||
|
mips32r5el-linux-gnu
|
||||||
|
mips64r2el-linux-gnu
|
||||||
|
mips64r6el-linux-gnu
|
||||||
|
native
|
||||||
|
reduce-csp
|
||||||
|
reduce-size
|
||||||
|
reduce-size-disable-stats
|
||||||
|
visibility-default-gnu
|
||||||
|
visibility-hidden-clang
|
||||||
|
visibility-hidden-gnu
|
||||||
|
wasm
|
||||||
|
x86_64-linux-clang
|
||||||
|
x86_64-linux-gnu
|
||||||
|
x86_64-linux-msan
|
||||||
|
x86_64-w64-mingw32
|
||||||
|
Environment variables:
|
||||||
|
WORKSPACE directory where the build is done
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
echo "Building libwebp in ${WORKSPACE}"
|
||||||
|
|
||||||
|
if [[ ! -d "${WORKSPACE}" ]]; then
|
||||||
|
log_err "${WORKSPACE} directory does not exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILD_TYPE=${1:?"Build type not defined.$(
|
||||||
|
echo
|
||||||
|
usage
|
||||||
|
)"}
|
||||||
|
TARGET=${2:?"Target not defined.$(
|
||||||
|
echo
|
||||||
|
usage
|
||||||
|
)"}
|
||||||
|
readonly BUILD_DIR="${WORKSPACE}/build-${BUILD_TYPE}"
|
||||||
|
|
||||||
|
trap 'cleanup ${BUILD_DIR}' EXIT
|
||||||
|
make_build_dir "${BUILD_DIR}"
|
||||||
|
|
||||||
|
config_flags=()
|
||||||
|
case "${BUILD_TYPE}" in
|
||||||
|
shared*) ;; # Valid BUILD_TYPE but no setup required
|
||||||
|
static*) config_flags+=("--disable-shared") ;;
|
||||||
|
experimental) config_flags+=("--enable-experimental") ;;
|
||||||
|
*)
|
||||||
|
log_err "Invalid BUILD_TYPE"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if grep -m 1 -q "enable-asserts" "${LIBWEBP_ROOT}/configure.ac"; then
|
||||||
|
config_flags+=("--enable-asserts")
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${TARGET}" in
|
||||||
|
aarch64-linux-clang)
|
||||||
|
TARGET="aarch64-linux-gnu"
|
||||||
|
CC="clang"
|
||||||
|
CC="${CC} --target=aarch64-linux-gnu"
|
||||||
|
export CC
|
||||||
|
export CFLAGS="-isystem /usr/aarch64-linux-gnu/include"
|
||||||
|
;;
|
||||||
|
arm-linux-gnueabi)
|
||||||
|
export CFLAGS="-O3 -march=armv7-a -mfloat-abi=softfp -ftree-vectorize"
|
||||||
|
;;
|
||||||
|
arm-neon-linux-gnueabi)
|
||||||
|
TARGET="arm-linux-gnueabi"
|
||||||
|
CFLAGS="-O3 -march=armv7-a -mfpu=neon -mfloat-abi=softfp -ftree-vectorize"
|
||||||
|
export CFLAGS
|
||||||
|
;;
|
||||||
|
mips2el-linux-gnu)
|
||||||
|
export CFLAGS="-EL -O2 -mips2"
|
||||||
|
TARGET="mipsel-linux-gnu"
|
||||||
|
;;
|
||||||
|
mips32el-linux-gnu)
|
||||||
|
export CFLAGS="-EL -O2 -mips32"
|
||||||
|
TARGET="mipsel-linux-gnu"
|
||||||
|
;;
|
||||||
|
mips32r2el-linux-gnu)
|
||||||
|
export CFLAGS="-EL -O2 -mips32r2"
|
||||||
|
TARGET="mipsel-linux-gnu"
|
||||||
|
;;
|
||||||
|
mips32dspr2el-linux-gnu)
|
||||||
|
export CFLAGS="-EL -O2 -mdspr2"
|
||||||
|
TARGET="mipsel-linux-gnu"
|
||||||
|
;;
|
||||||
|
mips32r5el-linux-gnu)
|
||||||
|
export CFLAGS="-EL -O2 -mips32r5 -mmsa"
|
||||||
|
TARGET="mipsel-linux-gnu"
|
||||||
|
;;
|
||||||
|
mips32eb-linux-gnu)
|
||||||
|
export CFLAGS="-EB -O2 -mips32"
|
||||||
|
TARGET="mips-linux-gnu"
|
||||||
|
;;
|
||||||
|
mips64r2el-linux-gnu)
|
||||||
|
export CFLAGS="-EL -O2 -mips64r2 -mabi=64"
|
||||||
|
TARGET="mips64el-linux-gnuabi64"
|
||||||
|
;;
|
||||||
|
mips64r6el-linux-gnu)
|
||||||
|
export CFLAGS="-EL -O2 -mips64r6 -mabi=64 -mmsa"
|
||||||
|
TARGET="mips-img-linux-gnu"
|
||||||
|
;;
|
||||||
|
i686-linux-gnu)
|
||||||
|
export CC="gcc -m32"
|
||||||
|
;;
|
||||||
|
i686-linux-clang)
|
||||||
|
TARGET="i686-linux-gnu"
|
||||||
|
export CC="clang -m32"
|
||||||
|
;;
|
||||||
|
i686-linux-asan)
|
||||||
|
TARGET="i686-linux-gnu"
|
||||||
|
export CC="clang -m32 -fsanitize=address"
|
||||||
|
;;
|
||||||
|
i686-linux-msan)
|
||||||
|
TARGET="i686-linux-gnu"
|
||||||
|
export CC="clang -m32 -fsanitize=memory"
|
||||||
|
;;
|
||||||
|
x86_64-linux-clang)
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
export CC=clang
|
||||||
|
;;
|
||||||
|
x86_64-linux-msan)
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
export CC="clang -fsanitize=memory"
|
||||||
|
;;
|
||||||
|
force-aligned-32)
|
||||||
|
config_flags+=("--enable-aligned")
|
||||||
|
TARGET="i686-linux-gnu"
|
||||||
|
export CC="gcc -m32"
|
||||||
|
;;
|
||||||
|
force-aligned-64)
|
||||||
|
config_flags+=("--enable-aligned")
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
;;
|
||||||
|
visibility-default-*)
|
||||||
|
export CFLAGS="-O2 -g -fvisibility=default"
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
;;
|
||||||
|
visibility-hidden-*)
|
||||||
|
export CFLAGS="-O2 -g -fvisibility=hidden"
|
||||||
|
if [[ "${TARGET}" = "visibility-hidden-clang" ]]; then
|
||||||
|
export CC=clang
|
||||||
|
fi
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
;;
|
||||||
|
disable-sse4.1)
|
||||||
|
grep "${TARGET}" "${LIBWEBP_ROOT}/configure.ac" || exit 0
|
||||||
|
config_flags+=("--${TARGET}")
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
;;
|
||||||
|
disable-near-lossless)
|
||||||
|
grep "${TARGET}" "${LIBWEBP_ROOT}/configure.ac" || exit 0
|
||||||
|
config_flags+=("--${TARGET}")
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
;;
|
||||||
|
disable-stats)
|
||||||
|
git -C "${LIBWEBP_ROOT}" grep WEBP_DISABLE_STATS || exit 0
|
||||||
|
export CFLAGS="-O2 -g -DWEBP_DISABLE_STATS"
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
;;
|
||||||
|
reduce-size)
|
||||||
|
git -C "${LIBWEBP_ROOT}" grep WEBP_REDUCE_SIZE || exit 0
|
||||||
|
export CFLAGS="-O2 -g -DWEBP_REDUCE_SIZE"
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
;;
|
||||||
|
reduce-size-disable-stats)
|
||||||
|
git -C "${LIBWEBP_ROOT}" grep -e WEBP_DISABLE_STATS -e WEBP_REDUCE_SIZE \
|
||||||
|
|| exit 0
|
||||||
|
export CFLAGS="-O2 -g -DWEBP_DISABLE_STATS -DWEBP_REDUCE_SIZE"
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
;;
|
||||||
|
reduce-csp)
|
||||||
|
git -C "${LIBWEBP_ROOT}" grep WEBP_REDUCE_CSP || exit 0
|
||||||
|
export CFLAGS="-O2 -g -DWEBP_REDUCE_CSP"
|
||||||
|
TARGET="x86_64-linux-gnu"
|
||||||
|
;;
|
||||||
|
x86_64-linux-gnu | *mingw32 | aarch64*) ;; # Default target configuration
|
||||||
|
# non-configure based builds
|
||||||
|
native)
|
||||||
|
setup_ccache
|
||||||
|
# exercise makefile.unix then quit
|
||||||
|
make -C "${LIBWEBP_ROOT}" -f makefile.unix -j all
|
||||||
|
for tgt in extras examples/anim_diff; do
|
||||||
|
grep -q -m 1 "${tgt}" "${LIBWEBP_ROOT}/makefile.unix" \
|
||||||
|
&& make -C "${LIBWEBP_ROOT}" -f makefile.unix -j "${tgt}"
|
||||||
|
done
|
||||||
|
[[ -d "${LIBWEBP_ROOT}/tests/fuzzer" ]] \
|
||||||
|
&& make -j -C "${LIBWEBP_ROOT}/tests/fuzzer" -f makefile.unix
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
cmake*)
|
||||||
|
setup_ccache
|
||||||
|
# exercise cmake then quit
|
||||||
|
opts=()
|
||||||
|
case "${TARGET}" in
|
||||||
|
cmake-clang)
|
||||||
|
opts+=("-DCMAKE_C_COMPILER=clang")
|
||||||
|
;;
|
||||||
|
cmake-arm)
|
||||||
|
opts+=("-DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc")
|
||||||
|
case "${GERRIT_BRANCH:-}" in
|
||||||
|
portable-intrinsics | 0.6.1) exit 0 ;;
|
||||||
|
*) ;; # Skip configuration
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
cmake-aarch64)
|
||||||
|
opts+=("-DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc")
|
||||||
|
case "${GERRIT_BRANCH:-}" in
|
||||||
|
portable-intrinsics | 0.6.1) exit 0 ;;
|
||||||
|
*) ;; # Skip configuration
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*) ;; # Skip configuration
|
||||||
|
esac
|
||||||
|
case "${BUILD_TYPE}" in
|
||||||
|
static*)
|
||||||
|
opts+=("-DBUILD_SHARED_LIBS=OFF")
|
||||||
|
;;
|
||||||
|
experimental)
|
||||||
|
opts+=("-DWEBP_EXPERIMENTAL_FEATURES=ON" "-DBUILD_SHARED_LIBS=ON")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
opts+=("-DBUILD_SHARED_LIBS=ON")
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
case "${BUILD_TYPE}" in
|
||||||
|
*debug) opts+=("-DCMAKE_BUILD_TYPE=Debug") ;;
|
||||||
|
*) opts+=("-DCMAKE_BUILD_TYPE=RelWithDebInfo") ;;
|
||||||
|
esac
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
opts+=("-DWEBP_BUILD_CWEBP=ON" "-DWEBP_BUILD_DWEBP=ON")
|
||||||
|
grep -m 1 -q WEBP_BUILD_GIF2WEBP "${LIBWEBP_ROOT}/CMakeLists.txt" \
|
||||||
|
&& opts+=("-DWEBP_BUILD_GIF2WEBP=ON")
|
||||||
|
grep -m 1 -q WEBP_BUILD_IMG2WEBP "${LIBWEBP_ROOT}/CMakeLists.txt" \
|
||||||
|
&& opts+=("-DWEBP_BUILD_IMG2WEBP=ON")
|
||||||
|
cmake "${opts[@]}" "${LIBWEBP_ROOT}"
|
||||||
|
make VERBOSE=1 -j
|
||||||
|
case "${BUILD_TYPE}" in
|
||||||
|
static)
|
||||||
|
mkdir -p examples
|
||||||
|
cp [cd]webp examples
|
||||||
|
;;
|
||||||
|
*) ;; # Skip configuration.
|
||||||
|
esac
|
||||||
|
|
||||||
|
grep "install" "${LIBWEBP_ROOT}/CMakeLists.txt" || exit 0
|
||||||
|
|
||||||
|
make DESTDIR="${BUILD_DIR}/webp-install" install/strip
|
||||||
|
mkdir tmp
|
||||||
|
cd tmp
|
||||||
|
cat > CMakeLists.txt << EOF
|
||||||
|
cmake_minimum_required(VERSION 2.8.7)
|
||||||
|
|
||||||
|
project(libwebp C)
|
||||||
|
|
||||||
|
find_package(WebP)
|
||||||
|
if (NOT WebP_FOUND)
|
||||||
|
message(FATAL_ERROR "WebP package not found")
|
||||||
|
endif ()
|
||||||
|
message("WebP_FOUND: \${WebP_FOUND}")
|
||||||
|
message("WebP_INCLUDE_DIRS: \${WebP_INCLUDE_DIRS}")
|
||||||
|
message("WebP_LIBRARIES: \${WebP_LIBRARIES}")
|
||||||
|
message("WEBP_INCLUDE_DIRS: \${WEBP_INCLUDE_DIRS}")
|
||||||
|
message("WEBP_LIBRARIES: \${WEBP_LIBRARIES}")
|
||||||
|
EOF
|
||||||
|
cmake . "${opts[@]}" \
|
||||||
|
"-DCMAKE_PREFIX_PATH=${BUILD_DIR}/webp-install/usr/local"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
gradle)
|
||||||
|
setup_ccache
|
||||||
|
# exercise gradle then quit
|
||||||
|
[[ -f "${LIBWEBP_ROOT}/gradlew" ]] || exit 0
|
||||||
|
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
# TODO -g / --gradle-user-home could be used if there's a race between jobs
|
||||||
|
"${LIBWEBP_ROOT}/gradlew" -p "${LIBWEBP_ROOT}" buildAllExecutables
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
wasm)
|
||||||
|
grep -m 1 -q WEBP_ENABLE_WASM "${LIBWEBP_ROOT}/CMakeLists.txt" || exit 0
|
||||||
|
opts+=("-DCMAKE_C_COMPILER=clang" "-DWEBP_ENABLE_WASM=ON")
|
||||||
|
opts+=("-DWEBP_BUILD_CWEBP=ON" "-DWEBP_BUILD_DWEBP=ON")
|
||||||
|
case "${BUILD_TYPE}" in
|
||||||
|
*debug) opts+=("-DCMAKE_BUILD_TYPE=Debug") ;;
|
||||||
|
*) opts+=("-DCMAKE_BUILD_TYPE=RelWithDebInfo") ;;
|
||||||
|
esac
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
cmake "${opts[@]}" "${LIBWEBP_ROOT}"
|
||||||
|
make VERBOSE=1 -j
|
||||||
|
mkdir examples
|
||||||
|
case "${BUILD_TYPE}" in
|
||||||
|
static)
|
||||||
|
mkdir -p examples
|
||||||
|
cp [cd]webp examples
|
||||||
|
;;
|
||||||
|
*) ;; # Skip configuration
|
||||||
|
esac
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_err "Invalid TARGET"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "${TARGET}" in
|
||||||
|
*mingw32) ;; # Skip configuration
|
||||||
|
*)
|
||||||
|
case "${TARGET}-${CC}" in
|
||||||
|
static-debug-gcc* | static-debug-)
|
||||||
|
CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage -O0 -g"
|
||||||
|
CXXFLAGS="${CXXFLAGS} -fprofile-arcs -ftest-coverage -O0 -g"
|
||||||
|
export CFLAGS CXXFLAGS
|
||||||
|
;;
|
||||||
|
*) ;; # This case should not be reached.
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
setup_ccache
|
||||||
|
|
||||||
|
cd "${LIBWEBP_ROOT}"
|
||||||
|
./autogen.sh
|
||||||
|
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
"${LIBWEBP_ROOT}/configure" \
|
||||||
|
--host "${TARGET}" --build "$("${LIBWEBP_ROOT}/config.guess")" \
|
||||||
|
--enable-everything "${config_flags[@]}"
|
||||||
|
make -j V=1
|
||||||
224
infra/compile_android.sh
Executable file
224
infra/compile_android.sh
Executable file
@@ -0,0 +1,224 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Copyright (c) 2021, Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of Google nor the names of its contributors may
|
||||||
|
# be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
set -xe
|
||||||
|
LIBWEBP_ROOT="$(realpath "$(dirname "$0")/..")"
|
||||||
|
readonly LIBWEBP_ROOT
|
||||||
|
readonly WORKSPACE=${WORKSPACE:-"$(mktemp -d -t webp.android.XXX)"}
|
||||||
|
# shellcheck source=infra/common.sh
|
||||||
|
source "${LIBWEBP_ROOT}/infra/common.sh"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat << EOF
|
||||||
|
Usage: $(basename "$0") BUILD_TYPE APP_ABI
|
||||||
|
Options:
|
||||||
|
BUILD_TYPE supported build types:
|
||||||
|
static
|
||||||
|
static-debug
|
||||||
|
shared
|
||||||
|
shared-debug
|
||||||
|
APP_ABI supported application binary interfaces:
|
||||||
|
armeabi-v7a
|
||||||
|
arm64-v8a
|
||||||
|
x86
|
||||||
|
x86_64
|
||||||
|
Environment variables:
|
||||||
|
WORKSPACE directory where the build is done.
|
||||||
|
ANDROID_NDK_DIR directory where the android ndk tools are.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
echo "Building libwebp for Android in ${WORKSPACE}"
|
||||||
|
|
||||||
|
if [[ ! -d "${WORKSPACE}" ]]; then
|
||||||
|
log_err "${WORKSPACE} directory does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
readonly BUILD_TYPE=${1:?"BUILD_TYPE is not defined.$(
|
||||||
|
echo
|
||||||
|
usage
|
||||||
|
)"}
|
||||||
|
readonly APP_ABI=${2:?"APP_ABI not defined.$(
|
||||||
|
echo
|
||||||
|
usage
|
||||||
|
)"}
|
||||||
|
readonly ANDROID_NDK_DIR=${ANDROID_NDK_DIR:?"ANDROID_NDK_DIR is not defined.$(
|
||||||
|
echo
|
||||||
|
usage
|
||||||
|
)"}
|
||||||
|
readonly BUILD_DIR="${WORKSPACE}/build-${BUILD_TYPE}"
|
||||||
|
readonly STANDALONE_ANDROID_DIR="${WORKSPACE}/android"
|
||||||
|
|
||||||
|
if [[ ! -x "${ANDROID_NDK_DIR}/ndk-build" ]]; then
|
||||||
|
log_err "unable to find ndk-build in ANDROID_NDK_DIR: ${ANDROID_NDK_DIR}."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CFLAGS=
|
||||||
|
LDFLAGS=
|
||||||
|
opts=()
|
||||||
|
case "${BUILD_TYPE}" in
|
||||||
|
*debug)
|
||||||
|
readonly APP_OPTIM="debug"
|
||||||
|
CFLAGS="-O0 -g"
|
||||||
|
opts+=("--enable-asserts")
|
||||||
|
;;
|
||||||
|
static* | shared*)
|
||||||
|
readonly APP_OPTIM="release"
|
||||||
|
CFLAGS="-O2 -g"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "${BUILD_TYPE}" in
|
||||||
|
shared*) readonly SHARED="1" ;;
|
||||||
|
*)
|
||||||
|
readonly SHARED="0"
|
||||||
|
CFLAGS="${CFLAGS} -fPIE"
|
||||||
|
LDFLAGS="${LDFLAGS} -Wl,-pie"
|
||||||
|
opts+=("--disable-shared")
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Create a fresh build directory
|
||||||
|
make_build_dir "${BUILD_DIR}"
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
ln -s "${LIBWEBP_ROOT}" jni
|
||||||
|
|
||||||
|
"${ANDROID_NDK_DIR}/ndk-build" -j2 \
|
||||||
|
APP_ABI="${APP_ABI}" \
|
||||||
|
APP_OPTIM="${APP_OPTIM}" \
|
||||||
|
ENABLE_SHARED="${SHARED}"
|
||||||
|
|
||||||
|
cd "${LIBWEBP_ROOT}"
|
||||||
|
./autogen.sh
|
||||||
|
|
||||||
|
case "${APP_ABI}" in
|
||||||
|
armeabi*) arch="arm" ;;
|
||||||
|
arm64*) arch="arm64" ;;
|
||||||
|
*) arch="${APP_ABI}" ;;
|
||||||
|
esac
|
||||||
|
# TODO(b/185520507): remove this and use the binaries from
|
||||||
|
# toolchains/llvm/prebuilt/ directly.
|
||||||
|
rm -rf "${STANDALONE_ANDROID_DIR}"
|
||||||
|
"${ANDROID_NDK_DIR}/build/tools/make_standalone_toolchain.py" \
|
||||||
|
--api 24 --arch "${arch}" --stl gnustl --install-dir \
|
||||||
|
"${STANDALONE_ANDROID_DIR}"
|
||||||
|
export PATH="${STANDALONE_ANDROID_DIR}/bin:${PATH}"
|
||||||
|
|
||||||
|
rm -rf "${BUILD_DIR}"
|
||||||
|
make_build_dir "${BUILD_DIR}"
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
|
||||||
|
case "${arch}" in
|
||||||
|
arm)
|
||||||
|
host="arm-linux-androideabi"
|
||||||
|
case "${APP_ABI}" in
|
||||||
|
armeabi) ;;
|
||||||
|
armeabi-v7a)
|
||||||
|
CFLAGS="${CFLAGS} -march=armv7-a -mfpu=neon -mfloat-abi=softfp"
|
||||||
|
;;
|
||||||
|
*) ;; # No configuration needed
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
arm64)
|
||||||
|
host="aarch64-linux-android"
|
||||||
|
;;
|
||||||
|
x86)
|
||||||
|
host="i686-linux-android"
|
||||||
|
;;
|
||||||
|
x86_64)
|
||||||
|
host="x86_64-linux-android"
|
||||||
|
;;
|
||||||
|
*) ;; # Skip configuration
|
||||||
|
esac
|
||||||
|
|
||||||
|
setup_ccache
|
||||||
|
CC="clang"
|
||||||
|
|
||||||
|
"${LIBWEBP_ROOT}/configure" --host "${host}" --build \
|
||||||
|
"$("${LIBWEBP_ROOT}/config.guess")" CC="${CC}" CFLAGS="${CFLAGS}" \
|
||||||
|
LDFLAGS="${LDFLAGS}" "${opts[@]}"
|
||||||
|
make -j
|
||||||
|
|
||||||
|
if [[ "${GERRIT_REFSPEC:-}" = "refs/heads/portable-intrinsics" ]] \
|
||||||
|
|| [[ "${GERRIT_BRANCH:-}" = "portable-intrinsics" ]]; then
|
||||||
|
cd "${WORKSPACE}"
|
||||||
|
rm -rf build && mkdir build
|
||||||
|
cd build
|
||||||
|
standalone="${WORKSPACE}/android"
|
||||||
|
cmake ../libwebp \
|
||||||
|
-DWEBP_BUILD_DWEBP=1 \
|
||||||
|
-DCMAKE_C_COMPILER="${standalone}/bin/clang" \
|
||||||
|
-DCMAKE_PREFIX_PATH="${standalone}/sysroot/usr/lib" \
|
||||||
|
-DCMAKE_C_FLAGS=-fPIE \
|
||||||
|
-DCMAKE_EXE_LINKER_FLAGS=-Wl,-pie \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DWEBP_ENABLE_WASM=1
|
||||||
|
make -j2
|
||||||
|
|
||||||
|
cd "${WORKSPACE}"
|
||||||
|
make_build_dir "${BUILD_DIR}"
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
case "${APP_ABI}" in
|
||||||
|
armeabi-v7a | arm64*)
|
||||||
|
cmake "${LIBWEBP_ROOT}" \
|
||||||
|
-DWEBP_BUILD_DWEBP=1 \
|
||||||
|
-DCMAKE_C_COMPILER="${standalone}/bin/clang" \
|
||||||
|
-DCMAKE_PREFIX_PATH="${standalone}/sysroot/usr/lib" \
|
||||||
|
-DCMAKE_C_FLAGS='-fPIE -DENABLE_NEON_BUILTIN_MULHI_INT16X8' \
|
||||||
|
-DCMAKE_EXE_LINKER_FLAGS=-Wl,-pie \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DWEBP_ENABLE_WASM=1
|
||||||
|
make -j2
|
||||||
|
;;
|
||||||
|
x86*)
|
||||||
|
cmake "${LIBWEBP_ROOT}" \
|
||||||
|
-DWEBP_BUILD_DWEBP=1 \
|
||||||
|
-DCMAKE_C_COMPILER="${standalone}/bin/clang" \
|
||||||
|
-DCMAKE_PREFIX_PATH="${standalone}/sysroot/usr/lib" \
|
||||||
|
-DCMAKE_C_FLAGS='-fPIE -DENABLE_X86_BUILTIN_MULHI_INT16X8' \
|
||||||
|
-DCMAKE_EXE_LINKER_FLAGS=-Wl,-pie \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DWEBP_ENABLE_WASM=1
|
||||||
|
make -j2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_err "APP_ABI not supported."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
75
infra/compile_js.sh
Executable file
75
infra/compile_js.sh
Executable file
@@ -0,0 +1,75 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Copyright (c) 2021, Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of Google nor the names of its contributors may
|
||||||
|
# be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
readonly WORKSPACE="${WORKSPACE:-"$(mktemp -d -t webp.js.XXX)"}"
|
||||||
|
readonly BUILD_DIR="${WORKSPACE}/webp_js/"
|
||||||
|
readonly LIBWEBP_ROOT="$(realpath "$(dirname "$0")/..")"
|
||||||
|
|
||||||
|
# shellcheck source=infra/common.sh
|
||||||
|
source "${LIBWEBP_ROOT}/infra/common.sh"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat << EOF
|
||||||
|
Usage: $(basename "$0")
|
||||||
|
Environment variables:
|
||||||
|
WORKSPACE directory where the build is done
|
||||||
|
EMSDK_DIR directory where emsdk is installed
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -d "${EMSDK_DIR:?Not defined}" ]] \
|
||||||
|
|| (log_err "${EMSDK_DIR} is not a valid directory." && exit 1)
|
||||||
|
|
||||||
|
# shellcheck source=/opt/emsdk/emsdk_env.sh
|
||||||
|
source "${EMSDK_DIR}/emsdk_env.sh"
|
||||||
|
|
||||||
|
readonly EMSCRIPTEN=${EMSCRIPTEN:-"${EMSDK}/upstream/emscripten"}
|
||||||
|
readonly \
|
||||||
|
EMSCRIPTEN_CMAKE_FILE="${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake"
|
||||||
|
make_build_dir "${BUILD_DIR}"
|
||||||
|
|
||||||
|
pushd "${BUILD_DIR}"
|
||||||
|
opts=("-GUnix Makefiles" "-DWEBP_BUILD_WEBP_JS=ON")
|
||||||
|
if [[ -z "$(command -v emcmake)" ]]; then
|
||||||
|
opts+=("-DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN_CMAKE_FILE}")
|
||||||
|
cmake \
|
||||||
|
"${opts[@]}" \
|
||||||
|
"${LIBWEBP_ROOT}"
|
||||||
|
make -j
|
||||||
|
else
|
||||||
|
emcmake cmake \
|
||||||
|
"${opts[@]}" \
|
||||||
|
"${LIBWEBP_ROOT}"
|
||||||
|
emmake make -j
|
||||||
|
fi
|
||||||
|
popd
|
||||||
98
infra/run_static_analysis.sh
Executable file
98
infra/run_static_analysis.sh
Executable file
@@ -0,0 +1,98 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Copyright (c) 2021, Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# * Neither the name of Google nor the names of its contributors may
|
||||||
|
# be used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
set -xe
|
||||||
|
|
||||||
|
LIBWEBP_ROOT="$(realpath "$(dirname "$0")/..")"
|
||||||
|
readonly LIBWEBP_ROOT
|
||||||
|
readonly WORKSPACE=${WORKSPACE:-"$(mktemp -d -t webp.scanbuild.XXX)"}
|
||||||
|
|
||||||
|
# shellcheck source=infra/common.sh
|
||||||
|
source "${LIBWEBP_ROOT}/infra/common.sh"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat << EOF
|
||||||
|
Usage: $(basename "$0") MODE
|
||||||
|
Options:
|
||||||
|
MODE supported scan modes: (shallow|deep)
|
||||||
|
Environment variables:
|
||||||
|
WORKSPACE directory where the build is done.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Wrap clang-tools scan-build.
|
||||||
|
# Globals:
|
||||||
|
# OUTPUT_DIR target directory where scan-build report is generated.
|
||||||
|
# MODE scan-build mode
|
||||||
|
# Arguments:
|
||||||
|
# $* scan-build additional args.
|
||||||
|
# Returns:
|
||||||
|
# scan-build retcode
|
||||||
|
#######################################
|
||||||
|
scan_build() {
|
||||||
|
scan-build -o "${OUTPUT_DIR}" --use-analyzer="$(command -v clang)" \
|
||||||
|
-analyzer-config mode="${MODE}" "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
MODE=${1:?"MODE is not specified.$(
|
||||||
|
echo
|
||||||
|
usage
|
||||||
|
)"}
|
||||||
|
|
||||||
|
readonly OUTPUT_DIR="${WORKSPACE}/output-${MODE}"
|
||||||
|
readonly BUILD_DIR="${WORKSPACE}/build"
|
||||||
|
|
||||||
|
make_build_dir "${OUTPUT_DIR}"
|
||||||
|
make_build_dir "${BUILD_DIR}"
|
||||||
|
|
||||||
|
cd "${LIBWEBP_ROOT}"
|
||||||
|
./autogen.sh
|
||||||
|
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
grep -m 1 -q 'enable-asserts' "${LIBWEBP_ROOT}/configure.ac" \
|
||||||
|
&& args='--enable-asserts'
|
||||||
|
scan_build "${LIBWEBP_ROOT}/configure" --enable-everything "${args}"
|
||||||
|
scan_build make -j4
|
||||||
|
|
||||||
|
index="$(find "${OUTPUT_DIR}" -name index.html)"
|
||||||
|
if [[ -f "${index}" ]]; then
|
||||||
|
mv "$(dirname "${index}")/"* .
|
||||||
|
else
|
||||||
|
# make a empty report to wipe out any old bug reports.
|
||||||
|
cat << EOT > index.html
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
No bugs reported.
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
EOT
|
||||||
|
fi
|
||||||
80
iosbuild.sh
80
iosbuild.sh
@@ -1,16 +1,21 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# This script generates 'WebP.framework'. An iOS app can decode WebP images
|
# This script generates 'WebP.framework' and 'WebPDecoder.framework',
|
||||||
# by including 'WebP.framework'.
|
# 'WebPDemux.framework' and 'WebPMux.framework'.
|
||||||
|
# An iOS app can decode WebP images by including 'WebPDecoder.framework' and
|
||||||
|
# both encode and decode WebP images by including 'WebP.framework'.
|
||||||
#
|
#
|
||||||
# Run ./iosbuild.sh to generate 'WebP.framework' under the current directory
|
# Run ./iosbuild.sh to generate the frameworks under the current directory
|
||||||
# (previous build will be erased if it exists).
|
# (the previous build will be erased if it exists).
|
||||||
#
|
#
|
||||||
# This script is inspired by the build script written by Carson McDonald.
|
# This script is inspired by the build script written by Carson McDonald.
|
||||||
# (http://www.ioncannon.net/programming/1483/using-webp-to-reduce-native-ios-app-size/).
|
# (http://www.ioncannon.net/programming/1483/using-webp-to-reduce-native-ios-app-size/).
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# Set this variable based on the desired minimum deployment target.
|
||||||
|
readonly IOS_MIN_VERSION=6.0
|
||||||
|
|
||||||
# Extract the latest SDK version from the final field of the form: iphoneosX.Y
|
# Extract the latest SDK version from the final field of the form: iphoneosX.Y
|
||||||
readonly SDK=$(xcodebuild -showsdks \
|
readonly SDK=$(xcodebuild -showsdks \
|
||||||
| grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
|
| grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
|
||||||
@@ -33,36 +38,56 @@ readonly SRCDIR=$(dirname $0)
|
|||||||
readonly TOPDIR=$(pwd)
|
readonly TOPDIR=$(pwd)
|
||||||
readonly BUILDDIR="${TOPDIR}/iosbuild"
|
readonly BUILDDIR="${TOPDIR}/iosbuild"
|
||||||
readonly TARGETDIR="${TOPDIR}/WebP.framework"
|
readonly TARGETDIR="${TOPDIR}/WebP.framework"
|
||||||
|
readonly DECTARGETDIR="${TOPDIR}/WebPDecoder.framework"
|
||||||
|
readonly MUXTARGETDIR="${TOPDIR}/WebPMux.framework"
|
||||||
|
readonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.framework"
|
||||||
readonly DEVELOPER=$(xcode-select --print-path)
|
readonly DEVELOPER=$(xcode-select --print-path)
|
||||||
readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
|
readonly PLATFORMSROOT="${DEVELOPER}/Platforms"
|
||||||
readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
|
readonly LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
|
||||||
LIBLIST=''
|
LIBLIST=''
|
||||||
|
DECLIBLIST=''
|
||||||
|
MUXLIBLIST=''
|
||||||
|
DEMUXLIBLIST=''
|
||||||
|
|
||||||
if [[ -z "${SDK}" ]]; then
|
if [[ -z "${SDK}" ]]; then
|
||||||
echo "iOS SDK not available"
|
echo "iOS SDK not available"
|
||||||
exit 1
|
exit 1
|
||||||
elif [[ ${SDK%%.*} -gt 8 ]]; then
|
elif [[ ${SDK%%.*} -gt 8 ]]; then
|
||||||
EXTRA_CFLAGS="-fembed-bitcode"
|
EXTRA_CFLAGS="-fembed-bitcode"
|
||||||
elif [[ ${SDK} < 6.0 ]]; then
|
elif [[ ${SDK%%.*} -le 6 ]]; then
|
||||||
echo "You need iOS SDK version 6.0 or above"
|
echo "You need iOS SDK version 6.0 or above"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
echo "iOS SDK Version ${SDK}"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf ${BUILDDIR}
|
echo "Xcode Version: ${XCODE}"
|
||||||
rm -rf ${TARGETDIR}
|
echo "iOS SDK Version: ${SDK}"
|
||||||
mkdir -p ${BUILDDIR}
|
|
||||||
mkdir -p ${TARGETDIR}/Headers/
|
if [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \
|
||||||
|
|| -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" ]]; then
|
||||||
|
cat << EOF
|
||||||
|
WARNING: The following directories will be deleted:
|
||||||
|
WARNING: ${BUILDDIR}
|
||||||
|
WARNING: ${TARGETDIR}
|
||||||
|
WARNING: ${DECTARGETDIR}
|
||||||
|
WARNING: ${MUXTARGETDIR}
|
||||||
|
WARNING: ${DEMUXTARGETDIR}
|
||||||
|
WARNING: The build will continue in 5 seconds...
|
||||||
|
EOF
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
rm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \
|
||||||
|
${MUXTARGETDIR} ${DEMUXTARGETDIR}
|
||||||
|
mkdir -p ${BUILDDIR} ${TARGETDIR}/Headers/ ${DECTARGETDIR}/Headers/ \
|
||||||
|
${MUXTARGETDIR}/Headers/ ${DEMUXTARGETDIR}/Headers/
|
||||||
|
|
||||||
if [[ ! -e ${SRCDIR}/configure ]]; then
|
if [[ ! -e ${SRCDIR}/configure ]]; then
|
||||||
if ! (cd ${SRCDIR} && sh autogen.sh); then
|
if ! (cd ${SRCDIR} && sh autogen.sh); then
|
||||||
cat <<EOT
|
cat << EOF
|
||||||
Error creating configure script!
|
Error creating configure script!
|
||||||
This script requires the autoconf/automake and libtool to build. MacPorts can
|
This script requires the autoconf/automake and libtool to build. MacPorts can
|
||||||
be used to obtain these:
|
be used to obtain these:
|
||||||
http://www.macports.org/install.php
|
http://www.macports.org/install.php
|
||||||
EOT
|
EOF
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -96,7 +121,7 @@ for PLATFORM in ${PLATFORMS}; do
|
|||||||
SDKROOT="${PLATFORMSROOT}/"
|
SDKROOT="${PLATFORMSROOT}/"
|
||||||
SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
|
SDKROOT+="${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK}.sdk/"
|
||||||
CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
|
CFLAGS="-arch ${ARCH2:-${ARCH}} -pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
|
||||||
CFLAGS+=" -miphoneos-version-min=6.0 ${EXTRA_CFLAGS}"
|
CFLAGS+=" -miphoneos-version-min=${IOS_MIN_VERSION} ${EXTRA_CFLAGS}"
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
export PATH="${DEVROOT}/usr/bin:${OLDPATH}"
|
export PATH="${DEVROOT}/usr/bin:${OLDPATH}"
|
||||||
@@ -104,15 +129,19 @@ for PLATFORM in ${PLATFORMS}; do
|
|||||||
--build=$(${SRCDIR}/config.guess) \
|
--build=$(${SRCDIR}/config.guess) \
|
||||||
--disable-shared --enable-static \
|
--disable-shared --enable-static \
|
||||||
--enable-libwebpdecoder --enable-swap-16bit-csp \
|
--enable-libwebpdecoder --enable-swap-16bit-csp \
|
||||||
|
--enable-libwebpmux \
|
||||||
CFLAGS="${CFLAGS}"
|
CFLAGS="${CFLAGS}"
|
||||||
set +x
|
set +x
|
||||||
|
|
||||||
# run make only in the src/ directory to create libwebpdecoder.a
|
# run make only in the src/ directory to create libwebp.a/libwebpdecoder.a
|
||||||
cd src/
|
cd src/
|
||||||
make V=0
|
make V=0
|
||||||
make install
|
make install
|
||||||
|
|
||||||
LIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a"
|
LIBLIST+=" ${ROOTDIR}/lib/libwebp.a"
|
||||||
|
DECLIBLIST+=" ${ROOTDIR}/lib/libwebpdecoder.a"
|
||||||
|
MUXLIBLIST+=" ${ROOTDIR}/lib/libwebpmux.a"
|
||||||
|
DEMUXLIBLIST+=" ${ROOTDIR}/lib/libwebpdemux.a"
|
||||||
|
|
||||||
make clean
|
make clean
|
||||||
cd ..
|
cd ..
|
||||||
@@ -120,5 +149,22 @@ for PLATFORM in ${PLATFORMS}; do
|
|||||||
export PATH=${OLDPATH}
|
export PATH=${OLDPATH}
|
||||||
done
|
done
|
||||||
|
|
||||||
cp -a ${SRCDIR}/src/webp/*.h ${TARGETDIR}/Headers/
|
echo "LIBLIST = ${LIBLIST}"
|
||||||
|
cp -a ${SRCDIR}/src/webp/{decode,encode,types}.h ${TARGETDIR}/Headers/
|
||||||
${LIPO} -create ${LIBLIST} -output ${TARGETDIR}/WebP
|
${LIPO} -create ${LIBLIST} -output ${TARGETDIR}/WebP
|
||||||
|
|
||||||
|
echo "DECLIBLIST = ${DECLIBLIST}"
|
||||||
|
cp -a ${SRCDIR}/src/webp/{decode,types}.h ${DECTARGETDIR}/Headers/
|
||||||
|
${LIPO} -create ${DECLIBLIST} -output ${DECTARGETDIR}/WebPDecoder
|
||||||
|
|
||||||
|
echo "MUXLIBLIST = ${MUXLIBLIST}"
|
||||||
|
cp -a ${SRCDIR}/src/webp/{types,mux,mux_types}.h \
|
||||||
|
${MUXTARGETDIR}/Headers/
|
||||||
|
${LIPO} -create ${MUXLIBLIST} -output ${MUXTARGETDIR}/WebPMux
|
||||||
|
|
||||||
|
echo "DEMUXLIBLIST = ${DEMUXLIBLIST}"
|
||||||
|
cp -a ${SRCDIR}/src/webp/{decode,types,mux_types,demux}.h \
|
||||||
|
${DEMUXTARGETDIR}/Headers/
|
||||||
|
${LIPO} -create ${DEMUXLIBLIST} -output ${DEMUXTARGETDIR}/WebPDemux
|
||||||
|
|
||||||
|
echo "SUCCESS"
|
||||||
|
|||||||
349
makefile.unix
349
makefile.unix
@@ -3,7 +3,7 @@
|
|||||||
# It will not install the libraries system-wide, but just create the 'cwebp'
|
# It will not install the libraries system-wide, but just create the 'cwebp'
|
||||||
# and 'dwebp' tools in the examples/ directory, along with the static
|
# and 'dwebp' tools in the examples/ directory, along with the static
|
||||||
# libraries 'src/libwebp.a', 'src/libwebpdecoder.a', 'src/mux/libwebpmux.a',
|
# libraries 'src/libwebp.a', 'src/libwebpdecoder.a', 'src/mux/libwebpmux.a',
|
||||||
# 'src/demux/libwebpdemux.a' and 'src/libwebpextras.a'.
|
# 'src/demux/libwebpdemux.a' and 'extras/libwebpextras.a'.
|
||||||
#
|
#
|
||||||
# To build the library and examples, use:
|
# To build the library and examples, use:
|
||||||
# make -f makefile.unix
|
# make -f makefile.unix
|
||||||
@@ -25,13 +25,26 @@ ifeq ($(strip $(shell uname)), Darwin)
|
|||||||
# Failure observed with: gcc 4.2.1 and 4.0.1.
|
# Failure observed with: gcc 4.2.1 and 4.0.1.
|
||||||
EXTRA_FLAGS += -fno-common
|
EXTRA_FLAGS += -fno-common
|
||||||
EXTRA_FLAGS += -DHAVE_GLUT_GLUT_H
|
EXTRA_FLAGS += -DHAVE_GLUT_GLUT_H
|
||||||
|
EXTRA_FLAGS += -Wno-deprecated-declarations
|
||||||
EXTRA_FLAGS += -I/opt/local/include
|
EXTRA_FLAGS += -I/opt/local/include
|
||||||
EXTRA_LIBS += -L/opt/local/lib
|
EXTRA_LIBS += -L/opt/local/lib
|
||||||
GL_LIBS = -framework GLUT -framework OpenGL
|
GL_LIBS = -framework GLUT -framework OpenGL
|
||||||
else
|
else
|
||||||
|
EXTRA_FLAGS += -I/usr/local/include
|
||||||
|
EXTRA_LIBS += -L/usr/local/lib
|
||||||
GL_LIBS = -lglut -lGL
|
GL_LIBS = -lglut -lGL
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# SDL flags: use sdl-config if it exists
|
||||||
|
SDL_CONFIG = $(shell sdl-config --version 2> /dev/null)
|
||||||
|
ifneq ($(SDL_CONFIG),)
|
||||||
|
SDL_LIBS = $(shell sdl-config --libs)
|
||||||
|
SDL_FLAGS = $(shell sdl-config --cflags)
|
||||||
|
else
|
||||||
|
# use best-guess
|
||||||
|
SDL_LIBS = -lSDL
|
||||||
|
SDL_FLAGS =
|
||||||
|
endif
|
||||||
|
|
||||||
# To install libraries on Mac OS X:
|
# To install libraries on Mac OS X:
|
||||||
# 1. Install MacPorts (http://www.macports.org/install.php)
|
# 1. Install MacPorts (http://www.macports.org/install.php)
|
||||||
@@ -51,11 +64,8 @@ endif
|
|||||||
# 'make -f makefile.unix EXTRA_FLAGS=-m32' to that effect.
|
# 'make -f makefile.unix EXTRA_FLAGS=-m32' to that effect.
|
||||||
# EXTRA_FLAGS += -m32
|
# EXTRA_FLAGS += -m32
|
||||||
|
|
||||||
# Extra flags to enable experimental features and code
|
|
||||||
# EXTRA_FLAGS += -DWEBP_EXPERIMENTAL_FEATURES
|
|
||||||
|
|
||||||
# Extra flags to enable byte swap for 16 bit colorspaces.
|
# Extra flags to enable byte swap for 16 bit colorspaces.
|
||||||
# EXTRA_FLAGS += -DWEBP_SWAP_16BIT_CSP
|
# EXTRA_FLAGS += -DWEBP_SWAP_16BIT_CSP=1
|
||||||
|
|
||||||
# Extra flags to enable multi-threading
|
# Extra flags to enable multi-threading
|
||||||
EXTRA_FLAGS += -DWEBP_USE_THREAD
|
EXTRA_FLAGS += -DWEBP_USE_THREAD
|
||||||
@@ -79,42 +89,53 @@ EXTRA_FLAGS += -DWEBP_HAVE_SSE41
|
|||||||
src/dsp/%_sse41.o: EXTRA_FLAGS += -msse4.1
|
src/dsp/%_sse41.o: EXTRA_FLAGS += -msse4.1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# AVX2-specific flags:
|
|
||||||
ifeq ($(HAVE_AVX2), 1)
|
|
||||||
EXTRA_FLAGS += -DWEBP_HAVE_AVX2
|
|
||||||
src/dsp/%_avx2.o: EXTRA_FLAGS += -mavx2
|
|
||||||
endif
|
|
||||||
|
|
||||||
# NEON-specific flags:
|
# NEON-specific flags:
|
||||||
# EXTRA_FLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8
|
# EXTRA_FLAGS += -march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8
|
||||||
# -> seems to make the overall lib slower: -fno-split-wide-types
|
# -> seems to make the overall lib slower: -fno-split-wide-types
|
||||||
|
|
||||||
|
# MIPS (MSA) 32-bit build specific flags for mips32r5 (p5600):
|
||||||
|
# EXTRA_FLAGS += -mips32r5 -mabi=32 -mtune=p5600 -mmsa -mfp64
|
||||||
|
# EXTRA_FLAGS += -msched-weight -mload-store-pairs
|
||||||
|
|
||||||
|
# MIPS (MSA) 64-bit build specific flags for mips64r6 (i6400):
|
||||||
|
# EXTRA_FLAGS += -mips64r6 -mabi=64 -mtune=i6400 -mmsa -mfp64
|
||||||
|
# EXTRA_FLAGS += -msched-weight -mload-store-pairs
|
||||||
|
|
||||||
#### Nothing should normally be changed below this line ####
|
#### Nothing should normally be changed below this line ####
|
||||||
|
|
||||||
AR = ar
|
AR = ar
|
||||||
ARFLAGS = r
|
ARFLAGS = r
|
||||||
CPPFLAGS = -Isrc/ -Wall
|
CPPFLAGS = -I. -Isrc/ -Wall
|
||||||
CFLAGS = -O3 -DNDEBUG $(EXTRA_FLAGS)
|
ifeq ($(DEBUG), 1)
|
||||||
|
CFLAGS = -g
|
||||||
|
else
|
||||||
|
CFLAGS = -O3 -DNDEBUG
|
||||||
|
endif
|
||||||
|
CFLAGS += $(EXTRA_FLAGS)
|
||||||
CC = gcc
|
CC = gcc
|
||||||
INSTALL = install
|
INSTALL = install
|
||||||
GROFF = /usr/bin/groff
|
GROFF = /usr/bin/groff
|
||||||
COL = /usr/bin/col
|
COL = /usr/bin/col
|
||||||
LDFLAGS = $(EXTRA_LIBS) $(EXTRA_FLAGS) -lm
|
LDFLAGS = $(EXTRA_LIBS) $(EXTRA_FLAGS) -lm
|
||||||
|
|
||||||
|
ifdef BITTRACE
|
||||||
|
CFLAGS += -DBITTRACE=$(BITTRACE)
|
||||||
|
endif
|
||||||
|
|
||||||
ANIM_UTIL_OBJS = \
|
ANIM_UTIL_OBJS = \
|
||||||
examples/anim_util.o \
|
examples/anim_util.o \
|
||||||
|
|
||||||
DEC_OBJS = \
|
DEC_OBJS = \
|
||||||
src/dec/alpha.o \
|
src/dec/alpha_dec.o \
|
||||||
src/dec/buffer.o \
|
src/dec/buffer_dec.o \
|
||||||
src/dec/frame.o \
|
src/dec/frame_dec.o \
|
||||||
src/dec/idec.o \
|
src/dec/idec_dec.o \
|
||||||
src/dec/io.o \
|
src/dec/io_dec.o \
|
||||||
src/dec/quant.o \
|
src/dec/quant_dec.o \
|
||||||
src/dec/tree.o \
|
src/dec/tree_dec.o \
|
||||||
src/dec/vp8.o \
|
src/dec/vp8_dec.o \
|
||||||
src/dec/vp8l.o \
|
src/dec/vp8l_dec.o \
|
||||||
src/dec/webp.o \
|
src/dec/webp_dec.o \
|
||||||
|
|
||||||
DEMUX_OBJS = \
|
DEMUX_OBJS = \
|
||||||
src/demux/anim_decode.o \
|
src/demux/anim_decode.o \
|
||||||
@@ -123,6 +144,7 @@ DEMUX_OBJS = \
|
|||||||
DSP_DEC_OBJS = \
|
DSP_DEC_OBJS = \
|
||||||
src/dsp/alpha_processing.o \
|
src/dsp/alpha_processing.o \
|
||||||
src/dsp/alpha_processing_mips_dsp_r2.o \
|
src/dsp/alpha_processing_mips_dsp_r2.o \
|
||||||
|
src/dsp/alpha_processing_neon.o \
|
||||||
src/dsp/alpha_processing_sse2.o \
|
src/dsp/alpha_processing_sse2.o \
|
||||||
src/dsp/alpha_processing_sse41.o \
|
src/dsp/alpha_processing_sse41.o \
|
||||||
src/dsp/cpu.o \
|
src/dsp/cpu.o \
|
||||||
@@ -130,82 +152,99 @@ DSP_DEC_OBJS = \
|
|||||||
src/dsp/dec_clip_tables.o \
|
src/dsp/dec_clip_tables.o \
|
||||||
src/dsp/dec_mips32.o \
|
src/dsp/dec_mips32.o \
|
||||||
src/dsp/dec_mips_dsp_r2.o \
|
src/dsp/dec_mips_dsp_r2.o \
|
||||||
|
src/dsp/dec_msa.o \
|
||||||
src/dsp/dec_neon.o \
|
src/dsp/dec_neon.o \
|
||||||
src/dsp/dec_sse2.o \
|
src/dsp/dec_sse2.o \
|
||||||
src/dsp/dec_sse41.o \
|
src/dsp/dec_sse41.o \
|
||||||
src/dsp/filters.o \
|
src/dsp/filters.o \
|
||||||
src/dsp/filters_mips_dsp_r2.o \
|
src/dsp/filters_mips_dsp_r2.o \
|
||||||
|
src/dsp/filters_msa.o \
|
||||||
|
src/dsp/filters_neon.o \
|
||||||
src/dsp/filters_sse2.o \
|
src/dsp/filters_sse2.o \
|
||||||
src/dsp/lossless.o \
|
src/dsp/lossless.o \
|
||||||
src/dsp/lossless_mips_dsp_r2.o \
|
src/dsp/lossless_mips_dsp_r2.o \
|
||||||
|
src/dsp/lossless_msa.o \
|
||||||
src/dsp/lossless_neon.o \
|
src/dsp/lossless_neon.o \
|
||||||
src/dsp/lossless_sse2.o \
|
src/dsp/lossless_sse2.o \
|
||||||
|
src/dsp/lossless_sse41.o \
|
||||||
src/dsp/rescaler.o \
|
src/dsp/rescaler.o \
|
||||||
src/dsp/rescaler_mips32.o \
|
src/dsp/rescaler_mips32.o \
|
||||||
src/dsp/rescaler_mips_dsp_r2.o \
|
src/dsp/rescaler_mips_dsp_r2.o \
|
||||||
|
src/dsp/rescaler_msa.o \
|
||||||
src/dsp/rescaler_neon.o \
|
src/dsp/rescaler_neon.o \
|
||||||
src/dsp/rescaler_sse2.o \
|
src/dsp/rescaler_sse2.o \
|
||||||
src/dsp/upsampling.o \
|
src/dsp/upsampling.o \
|
||||||
src/dsp/upsampling_mips_dsp_r2.o \
|
src/dsp/upsampling_mips_dsp_r2.o \
|
||||||
|
src/dsp/upsampling_msa.o \
|
||||||
src/dsp/upsampling_neon.o \
|
src/dsp/upsampling_neon.o \
|
||||||
src/dsp/upsampling_sse2.o \
|
src/dsp/upsampling_sse2.o \
|
||||||
|
src/dsp/upsampling_sse41.o \
|
||||||
src/dsp/yuv.o \
|
src/dsp/yuv.o \
|
||||||
src/dsp/yuv_mips32.o \
|
src/dsp/yuv_mips32.o \
|
||||||
src/dsp/yuv_mips_dsp_r2.o \
|
src/dsp/yuv_mips_dsp_r2.o \
|
||||||
|
src/dsp/yuv_neon.o \
|
||||||
src/dsp/yuv_sse2.o \
|
src/dsp/yuv_sse2.o \
|
||||||
|
src/dsp/yuv_sse41.o \
|
||||||
|
|
||||||
DSP_ENC_OBJS = \
|
DSP_ENC_OBJS = \
|
||||||
src/dsp/argb.o \
|
|
||||||
src/dsp/argb_mips_dsp_r2.o \
|
|
||||||
src/dsp/argb_sse2.o \
|
|
||||||
src/dsp/cost.o \
|
src/dsp/cost.o \
|
||||||
src/dsp/cost_mips32.o \
|
src/dsp/cost_mips32.o \
|
||||||
src/dsp/cost_mips_dsp_r2.o \
|
src/dsp/cost_mips_dsp_r2.o \
|
||||||
|
src/dsp/cost_neon.o \
|
||||||
src/dsp/cost_sse2.o \
|
src/dsp/cost_sse2.o \
|
||||||
src/dsp/enc.o \
|
src/dsp/enc.o \
|
||||||
src/dsp/enc_avx2.o \
|
|
||||||
src/dsp/enc_mips32.o \
|
src/dsp/enc_mips32.o \
|
||||||
src/dsp/enc_mips_dsp_r2.o \
|
src/dsp/enc_mips_dsp_r2.o \
|
||||||
|
src/dsp/enc_msa.o \
|
||||||
src/dsp/enc_neon.o \
|
src/dsp/enc_neon.o \
|
||||||
src/dsp/enc_sse2.o \
|
src/dsp/enc_sse2.o \
|
||||||
src/dsp/enc_sse41.o \
|
src/dsp/enc_sse41.o \
|
||||||
src/dsp/lossless_enc.o \
|
src/dsp/lossless_enc.o \
|
||||||
src/dsp/lossless_enc_mips32.o \
|
src/dsp/lossless_enc_mips32.o \
|
||||||
src/dsp/lossless_enc_mips_dsp_r2.o \
|
src/dsp/lossless_enc_mips_dsp_r2.o \
|
||||||
|
src/dsp/lossless_enc_msa.o \
|
||||||
src/dsp/lossless_enc_neon.o \
|
src/dsp/lossless_enc_neon.o \
|
||||||
src/dsp/lossless_enc_sse2.o \
|
src/dsp/lossless_enc_sse2.o \
|
||||||
src/dsp/lossless_enc_sse41.o \
|
src/dsp/lossless_enc_sse41.o \
|
||||||
|
src/dsp/ssim.o \
|
||||||
|
src/dsp/ssim_sse2.o \
|
||||||
|
|
||||||
ENC_OBJS = \
|
ENC_OBJS = \
|
||||||
src/enc/alpha.o \
|
src/enc/alpha_enc.o \
|
||||||
src/enc/analysis.o \
|
src/enc/analysis_enc.o \
|
||||||
src/enc/backward_references.o \
|
src/enc/backward_references_cost_enc.o \
|
||||||
src/enc/config.o \
|
src/enc/backward_references_enc.o \
|
||||||
src/enc/cost.o \
|
src/enc/config_enc.o \
|
||||||
src/enc/delta_palettization.o \
|
src/enc/cost_enc.o \
|
||||||
src/enc/filter.o \
|
src/enc/filter_enc.o \
|
||||||
src/enc/frame.o \
|
src/enc/frame_enc.o \
|
||||||
src/enc/histogram.o \
|
src/enc/histogram_enc.o \
|
||||||
src/enc/iterator.o \
|
src/enc/iterator_enc.o \
|
||||||
src/enc/near_lossless.o \
|
src/enc/near_lossless_enc.o \
|
||||||
src/enc/picture.o \
|
src/enc/picture_enc.o \
|
||||||
src/enc/picture_csp.o \
|
src/enc/picture_csp_enc.o \
|
||||||
src/enc/picture_psnr.o \
|
src/enc/picture_psnr_enc.o \
|
||||||
src/enc/picture_rescale.o \
|
src/enc/picture_rescale_enc.o \
|
||||||
src/enc/picture_tools.o \
|
src/enc/picture_tools_enc.o \
|
||||||
src/enc/quant.o \
|
src/enc/predictor_enc.o \
|
||||||
src/enc/syntax.o \
|
src/enc/quant_enc.o \
|
||||||
src/enc/token.o \
|
src/enc/syntax_enc.o \
|
||||||
src/enc/tree.o \
|
src/enc/token_enc.o \
|
||||||
src/enc/vp8l.o \
|
src/enc/tree_enc.o \
|
||||||
src/enc/webpenc.o \
|
src/enc/vp8l_enc.o \
|
||||||
|
src/enc/webp_enc.o \
|
||||||
|
|
||||||
EX_FORMAT_DEC_OBJS = \
|
EX_FORMAT_DEC_OBJS = \
|
||||||
examples/jpegdec.o \
|
imageio/image_dec.o \
|
||||||
examples/metadata.o \
|
imageio/jpegdec.o \
|
||||||
examples/pngdec.o \
|
imageio/metadata.o \
|
||||||
examples/tiffdec.o \
|
imageio/pngdec.o \
|
||||||
examples/webpdec.o \
|
imageio/pnmdec.o \
|
||||||
|
imageio/tiffdec.o \
|
||||||
|
imageio/webpdec.o \
|
||||||
|
|
||||||
|
EX_FORMAT_ENC_OBJS = \
|
||||||
|
imageio/image_enc.o \
|
||||||
|
|
||||||
EX_UTIL_OBJS = \
|
EX_UTIL_OBJS = \
|
||||||
examples/example_util.o \
|
examples/example_util.o \
|
||||||
@@ -213,6 +252,9 @@ EX_UTIL_OBJS = \
|
|||||||
GIFDEC_OBJS = \
|
GIFDEC_OBJS = \
|
||||||
examples/gifdec.o \
|
examples/gifdec.o \
|
||||||
|
|
||||||
|
IMAGE_UTIL_OBJS = \
|
||||||
|
imageio/imageio_util.o \
|
||||||
|
|
||||||
MUX_OBJS = \
|
MUX_OBJS = \
|
||||||
src/mux/anim_encode.o \
|
src/mux/anim_encode.o \
|
||||||
src/mux/muxedit.o \
|
src/mux/muxedit.o \
|
||||||
@@ -220,23 +262,24 @@ MUX_OBJS = \
|
|||||||
src/mux/muxread.o \
|
src/mux/muxread.o \
|
||||||
|
|
||||||
UTILS_DEC_OBJS = \
|
UTILS_DEC_OBJS = \
|
||||||
src/utils/bit_reader.o \
|
src/utils/bit_reader_utils.o \
|
||||||
src/utils/color_cache.o \
|
src/utils/color_cache_utils.o \
|
||||||
src/utils/filters.o \
|
src/utils/filters_utils.o \
|
||||||
src/utils/huffman.o \
|
src/utils/huffman_utils.o \
|
||||||
src/utils/quant_levels_dec.o \
|
src/utils/quant_levels_dec_utils.o \
|
||||||
src/utils/random.o \
|
src/utils/random_utils.o \
|
||||||
src/utils/rescaler.o \
|
src/utils/rescaler_utils.o \
|
||||||
src/utils/thread.o \
|
src/utils/thread_utils.o \
|
||||||
src/utils/utils.o \
|
src/utils/utils.o \
|
||||||
|
|
||||||
UTILS_ENC_OBJS = \
|
UTILS_ENC_OBJS = \
|
||||||
src/utils/bit_writer.o \
|
src/utils/bit_writer_utils.o \
|
||||||
src/utils/huffman_encode.o \
|
src/utils/huffman_encode_utils.o \
|
||||||
src/utils/quant_levels.o \
|
src/utils/quant_levels_utils.o \
|
||||||
|
|
||||||
EXTRA_OBJS = \
|
EXTRA_OBJS = \
|
||||||
src/extras/extras.o \
|
extras/extras.o \
|
||||||
|
extras/quality_estimate.o \
|
||||||
|
|
||||||
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
|
LIBWEBPDECODER_OBJS = $(DEC_OBJS) $(DSP_DEC_OBJS) $(UTILS_DEC_OBJS)
|
||||||
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
|
LIBWEBP_OBJS = $(LIBWEBPDECODER_OBJS) $(ENC_OBJS) $(DSP_ENC_OBJS) \
|
||||||
@@ -254,111 +297,171 @@ HDRS_INSTALLED = \
|
|||||||
src/webp/types.h \
|
src/webp/types.h \
|
||||||
|
|
||||||
HDRS = \
|
HDRS = \
|
||||||
src/dec/alphai.h \
|
src/dec/alphai_dec.h \
|
||||||
src/dec/common.h \
|
src/dec/common_dec.h \
|
||||||
src/dec/decode_vp8.h \
|
src/dec/vp8_dec.h \
|
||||||
src/dec/vp8i.h \
|
src/dec/vp8i_dec.h \
|
||||||
src/dec/vp8li.h \
|
src/dec/vp8li_dec.h \
|
||||||
src/dec/webpi.h \
|
src/dec/webpi_dec.h \
|
||||||
|
src/dsp/common_sse2.h \
|
||||||
src/dsp/dsp.h \
|
src/dsp/dsp.h \
|
||||||
src/dsp/lossless.h \
|
src/dsp/lossless.h \
|
||||||
|
src/dsp/lossless_common.h \
|
||||||
src/dsp/mips_macro.h \
|
src/dsp/mips_macro.h \
|
||||||
|
src/dsp/msa_macro.h \
|
||||||
src/dsp/neon.h \
|
src/dsp/neon.h \
|
||||||
src/dsp/yuv.h \
|
src/dsp/yuv.h \
|
||||||
src/enc/backward_references.h \
|
src/enc/backward_references_enc.h \
|
||||||
src/enc/cost.h \
|
src/enc/cost_enc.h \
|
||||||
src/enc/delta_palettization.h \
|
src/enc/histogram_enc.h \
|
||||||
src/enc/histogram.h \
|
src/enc/vp8i_enc.h \
|
||||||
src/enc/vp8enci.h \
|
src/enc/vp8li_enc.h \
|
||||||
src/enc/vp8li.h \
|
src/mux/animi.h \
|
||||||
src/mux/muxi.h \
|
src/mux/muxi.h \
|
||||||
src/utils/bit_reader.h \
|
src/utils/bit_reader_utils.h \
|
||||||
src/utils/bit_reader_inl.h \
|
src/utils/bit_reader_inl_utils.h \
|
||||||
src/utils/bit_writer.h \
|
src/utils/bit_writer_utils.h \
|
||||||
src/utils/color_cache.h \
|
src/utils/color_cache_utils.h \
|
||||||
src/utils/endian_inl.h \
|
src/utils/endian_inl_utils.h \
|
||||||
src/utils/filters.h \
|
src/utils/filters_utils.h \
|
||||||
src/utils/huffman.h \
|
src/utils/huffman_utils.h \
|
||||||
src/utils/huffman_encode.h \
|
src/utils/huffman_encode_utils.h \
|
||||||
src/utils/quant_levels.h \
|
src/utils/quant_levels_utils.h \
|
||||||
src/utils/quant_levels_dec.h \
|
src/utils/quant_levels_dec_utils.h \
|
||||||
src/utils/random.h \
|
src/utils/random_utils.h \
|
||||||
src/utils/rescaler.h \
|
src/utils/rescaler_utils.h \
|
||||||
src/utils/thread.h \
|
src/utils/thread_utils.h \
|
||||||
src/utils/utils.h \
|
src/utils/utils.h \
|
||||||
src/webp/format_constants.h \
|
src/webp/format_constants.h \
|
||||||
$(HDRS_INSTALLED) \
|
$(HDRS_INSTALLED) \
|
||||||
|
|
||||||
OUT_LIBS = examples/libexample_util.a src/libwebpdecoder.a src/libwebp.a
|
OUT_LIBS = examples/libexample_util.a
|
||||||
EXTRA_LIB = src/libwebpextras.a
|
OUT_LIBS += imageio/libimageio_util.a
|
||||||
|
OUT_LIBS += imageio/libimagedec.a
|
||||||
|
OUT_LIBS += imageio/libimageenc.a
|
||||||
|
OUT_LIBS += src/libwebpdecoder.a
|
||||||
|
OUT_LIBS += src/libwebp.a
|
||||||
|
EXTRA_LIB = extras/libwebpextras.a
|
||||||
OUT_EXAMPLES = examples/cwebp examples/dwebp
|
OUT_EXAMPLES = examples/cwebp examples/dwebp
|
||||||
EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux \
|
EXTRA_EXAMPLES = examples/gif2webp examples/vwebp examples/webpmux \
|
||||||
examples/anim_diff
|
examples/anim_diff examples/anim_dump \
|
||||||
|
examples/img2webp examples/webpinfo
|
||||||
|
OTHER_EXAMPLES = extras/get_disto extras/webp_quality extras/vwebp_sdl
|
||||||
|
|
||||||
OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES)
|
OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES)
|
||||||
ifeq ($(MAKECMDGOALS),clean)
|
ifeq ($(MAKECMDGOALS),clean)
|
||||||
OUTPUT += $(EXTRA_EXAMPLES)
|
OUTPUT += $(EXTRA_EXAMPLES) $(OTHER_EXAMPLES)
|
||||||
OUTPUT += src/demux/libwebpdemux.a src/mux/libwebpmux.a $(EXTRA_LIB)
|
OUTPUT += src/demux/libwebpdemux.a src/mux/libwebpmux.a $(EXTRA_LIB)
|
||||||
OUTPUT += examples/libgifdec.a examples/libanim_util.a
|
OUTPUT += examples/libgifdec.a examples/libanim_util.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ex: $(OUT_EXAMPLES)
|
ex: $(OUT_EXAMPLES)
|
||||||
all: ex $(EXTRA_EXAMPLES)
|
all: ex $(EXTRA_EXAMPLES) $(OTHER_EXAMPLES)
|
||||||
extras: $(EXTRA_LIB)
|
extras: $(EXTRA_LIB)
|
||||||
|
|
||||||
$(EX_FORMAT_DEC_OBJS): %.o: %.h
|
$(EX_FORMAT_DEC_OBJS): %.o: %.h
|
||||||
|
|
||||||
# special dependencies:
|
# special dependencies:
|
||||||
# tree.c/vp8.c/bit_reader.c <-> bit_reader_inl.h, endian_inl.h
|
# tree_dec.c/vp8_dec.c/bit_reader_utils.c <->
|
||||||
# bit_writer.c <-> endian_inl.h
|
# bit_reader_inl_utils.h, endian_inl_utils.h
|
||||||
src/dec/tree.o: src/utils/bit_reader_inl.h src/utils/endian_inl.h
|
# bit_writer_utils.c <-> endian_inl_utils.h
|
||||||
src/dec/vp8.o: src/utils/bit_reader_inl.h src/utils/endian_inl.h
|
src/dec/tree_dec.o: src/utils/bit_reader_inl_utils.h
|
||||||
src/utils/bit_reader.o: src/utils/bit_reader_inl.h src/utils/endian_inl.h
|
src/dec/tree_dec.o: src/utils/endian_inl_utils.h
|
||||||
src/utils/bit_writer.o: src/utils/endian_inl.h
|
src/dec/vp8_dec.o: src/utils/bit_reader_inl_utils.h src/utils/endian_inl_utils.h
|
||||||
|
src/utils/bit_reader_utils.o: src/utils/bit_reader_inl_utils.h
|
||||||
|
src/utils/bit_reader_utils.o: src/utils/endian_inl_utils.h
|
||||||
|
src/utils/bit_writer_utils.o: src/utils/endian_inl_utils.h
|
||||||
|
|
||||||
%.o: %.c $(HDRS)
|
%.o: %.c $(HDRS)
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
examples/libanim_util.a: $(ANIM_UTIL_OBJS)
|
examples/libanim_util.a: $(ANIM_UTIL_OBJS)
|
||||||
examples/libexample_util.a: $(EX_UTIL_OBJS)
|
examples/libexample_util.a: $(EX_UTIL_OBJS)
|
||||||
examples/libgifdec.a: $(GIFDEC_OBJS)
|
examples/libgifdec.a: $(GIFDEC_OBJS)
|
||||||
|
extras/libwebpextras.a: $(LIBWEBPEXTRA_OBJS)
|
||||||
|
imageio/libimagedec.a: $(EX_FORMAT_DEC_OBJS)
|
||||||
|
imageio/libimageenc.a: $(EX_FORMAT_ENC_OBJS)
|
||||||
|
imageio/libimageio_util.a: $(IMAGE_UTIL_OBJS)
|
||||||
src/libwebpdecoder.a: $(LIBWEBPDECODER_OBJS)
|
src/libwebpdecoder.a: $(LIBWEBPDECODER_OBJS)
|
||||||
src/libwebp.a: $(LIBWEBP_OBJS)
|
src/libwebp.a: $(LIBWEBP_OBJS)
|
||||||
src/mux/libwebpmux.a: $(LIBWEBPMUX_OBJS)
|
src/mux/libwebpmux.a: $(LIBWEBPMUX_OBJS)
|
||||||
src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS)
|
src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS)
|
||||||
src/libwebpextras.a: $(LIBWEBPEXTRA_OBJS)
|
|
||||||
|
|
||||||
%.a:
|
%.a:
|
||||||
$(AR) $(ARFLAGS) $@ $^
|
$(AR) $(ARFLAGS) $@ $^
|
||||||
|
|
||||||
examples/anim_diff: examples/anim_diff.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS)
|
examples/anim_diff: examples/anim_diff.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS)
|
||||||
examples/cwebp: examples/cwebp.o $(EX_FORMAT_DEC_OBJS)
|
examples/anim_dump: examples/anim_dump.o $(ANIM_UTIL_OBJS) $(GIFDEC_OBJS)
|
||||||
|
examples/cwebp: examples/cwebp.o
|
||||||
examples/dwebp: examples/dwebp.o
|
examples/dwebp: examples/dwebp.o
|
||||||
examples/gif2webp: examples/gif2webp.o $(GIFDEC_OBJS)
|
examples/gif2webp: examples/gif2webp.o $(GIFDEC_OBJS)
|
||||||
examples/vwebp: examples/vwebp.o
|
examples/vwebp: examples/vwebp.o
|
||||||
examples/webpmux: examples/webpmux.o
|
examples/webpmux: examples/webpmux.o
|
||||||
|
examples/img2webp: examples/img2webp.o
|
||||||
|
examples/webpinfo: examples/webpinfo.o
|
||||||
|
|
||||||
examples/anim_diff: examples/libanim_util.a examples/libgifdec.a
|
examples/anim_diff: examples/libanim_util.a examples/libgifdec.a
|
||||||
examples/anim_diff: src/demux/libwebpdemux.a examples/libexample_util.a
|
examples/anim_diff: src/demux/libwebpdemux.a examples/libexample_util.a
|
||||||
examples/anim_diff: src/libwebp.a
|
examples/anim_diff: imageio/libimageio_util.a src/libwebp.a
|
||||||
examples/anim_diff: EXTRA_LIBS += $(GIF_LIBS)
|
examples/anim_diff: override EXTRA_LIBS += $(GIF_LIBS)
|
||||||
examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF
|
examples/anim_diff: EXTRA_FLAGS += -DWEBP_HAVE_GIF
|
||||||
examples/cwebp: examples/libexample_util.a src/libwebp.a
|
examples/anim_dump: examples/libanim_util.a examples/libgifdec.a
|
||||||
examples/cwebp: EXTRA_LIBS += $(CWEBP_LIBS)
|
examples/anim_dump: src/demux/libwebpdemux.a
|
||||||
examples/dwebp: examples/libexample_util.a src/libwebpdecoder.a
|
examples/anim_dump: examples/libexample_util.a
|
||||||
examples/dwebp: EXTRA_LIBS += $(DWEBP_LIBS)
|
examples/anim_dump: imageio/libimageio_util.a
|
||||||
examples/gif2webp: examples/libexample_util.a examples/libgifdec.a
|
examples/anim_dump: imageio/libimageenc.a
|
||||||
examples/gif2webp: src/mux/libwebpmux.a src/libwebp.a
|
examples/anim_dump: src/libwebp.a
|
||||||
examples/gif2webp: EXTRA_LIBS += $(GIF_LIBS)
|
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: override EXTRA_LIBS += $(CWEBP_LIBS)
|
||||||
|
examples/dwebp: examples/libexample_util.a
|
||||||
|
examples/dwebp: imageio/libimagedec.a
|
||||||
|
examples/dwebp: src/demux/libwebpdemux.a
|
||||||
|
examples/dwebp: imageio/libimageenc.a
|
||||||
|
examples/dwebp: imageio/libimageio_util.a
|
||||||
|
examples/dwebp: src/libwebp.a
|
||||||
|
examples/dwebp: override EXTRA_LIBS += $(DWEBP_LIBS)
|
||||||
|
examples/gif2webp: examples/libexample_util.a imageio/libimageio_util.a
|
||||||
|
examples/gif2webp: examples/libgifdec.a src/mux/libwebpmux.a src/libwebp.a
|
||||||
|
examples/gif2webp: override EXTRA_LIBS += $(GIF_LIBS)
|
||||||
examples/gif2webp: EXTRA_FLAGS += -DWEBP_HAVE_GIF
|
examples/gif2webp: EXTRA_FLAGS += -DWEBP_HAVE_GIF
|
||||||
examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a
|
examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a
|
||||||
examples/vwebp: src/libwebp.a
|
examples/vwebp: imageio/libimageio_util.a src/libwebp.a
|
||||||
examples/vwebp: EXTRA_LIBS += $(GL_LIBS)
|
examples/vwebp: override EXTRA_LIBS += $(GL_LIBS)
|
||||||
examples/vwebp: EXTRA_FLAGS += -DWEBP_HAVE_GL
|
examples/vwebp: EXTRA_FLAGS += -DWEBP_HAVE_GL
|
||||||
examples/webpmux: examples/libexample_util.a src/mux/libwebpmux.a
|
examples/webpmux: examples/libexample_util.a imageio/libimageio_util.a
|
||||||
examples/webpmux: src/libwebpdecoder.a
|
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: override EXTRA_LIBS += $(CWEBP_LIBS)
|
||||||
|
examples/webpinfo: examples/libexample_util.a imageio/libimageio_util.a
|
||||||
|
examples/webpinfo: src/libwebpdecoder.a
|
||||||
|
|
||||||
$(OUT_EXAMPLES) $(EXTRA_EXAMPLES):
|
extras/get_disto: extras/get_disto.o
|
||||||
|
extras/get_disto: imageio/libimagedec.a
|
||||||
|
extras/get_disto: src/demux/libwebpdemux.a
|
||||||
|
extras/get_disto: imageio/libimageio_util.a
|
||||||
|
extras/get_disto: src/libwebp.a
|
||||||
|
extras/get_disto: override EXTRA_LIBS += $(CWEBP_LIBS)
|
||||||
|
|
||||||
|
extras/webp_quality: extras/webp_quality.o
|
||||||
|
extras/webp_quality: imageio/libimageio_util.a
|
||||||
|
extras/webp_quality: $(EXTRA_LIB) src/libwebp.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: EXTRA_FLAGS += -DWEBP_HAVE_SDL $(SDL_FLAGS)
|
||||||
|
extras/vwebp_sdl: override EXTRA_LIBS += $(SDL_LIBS)
|
||||||
|
|
||||||
|
$(OUT_EXAMPLES) $(EXTRA_EXAMPLES) $(OTHER_EXAMPLES):
|
||||||
$(CC) -o $@ $^ $(LDFLAGS)
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
dist: DESTDIR := dist
|
dist: DESTDIR := dist
|
||||||
@@ -372,9 +475,10 @@ dist: all
|
|||||||
$(INSTALL) -m644 src/demux/libwebpdemux.a $(DESTDIR)/lib
|
$(INSTALL) -m644 src/demux/libwebpdemux.a $(DESTDIR)/lib
|
||||||
$(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib
|
$(INSTALL) -m644 src/mux/libwebpmux.a $(DESTDIR)/lib
|
||||||
umask 022; \
|
umask 022; \
|
||||||
for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1; do \
|
for m in man/[cdv]webp.1 man/gif2webp.1 man/webpmux.1 \
|
||||||
|
man/img2webp.1 man/webpinfo.1; do \
|
||||||
basenam=$$(basename $$m .1); \
|
basenam=$$(basename $$m .1); \
|
||||||
$(GROFF) -t -e -man -T utf8 $$m \
|
$(GROFF) -t -e -man -T ascii $$m \
|
||||||
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \
|
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.txt; \
|
||||||
$(GROFF) -t -e -man -T html $$m \
|
$(GROFF) -t -e -man -T html $$m \
|
||||||
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.html; \
|
| $(COL) -bx >$(DESTDIR)/doc/$${basenam}.html; \
|
||||||
@@ -383,11 +487,12 @@ dist: all
|
|||||||
clean:
|
clean:
|
||||||
$(RM) $(OUTPUT) *~ \
|
$(RM) $(OUTPUT) *~ \
|
||||||
examples/*.o examples/*~ \
|
examples/*.o examples/*~ \
|
||||||
|
extras/*.o extras/*~ \
|
||||||
|
imageio/*.o imageio/*~ \
|
||||||
src/dec/*.o src/dec/*~ \
|
src/dec/*.o src/dec/*~ \
|
||||||
src/demux/*.o src/demux/*~ \
|
src/demux/*.o src/demux/*~ \
|
||||||
src/dsp/*.o src/dsp/*~ \
|
src/dsp/*.o src/dsp/*~ \
|
||||||
src/enc/*.o src/enc/*~ \
|
src/enc/*.o src/enc/*~ \
|
||||||
src/extras/*.o src/extras/*~ \
|
|
||||||
src/mux/*.o src/mux/*~ \
|
src/mux/*.o src/mux/*~ \
|
||||||
src/utils/*.o src/utils/*~ \
|
src/utils/*.o src/utils/*~ \
|
||||||
src/webp/*~ man/*~ doc/*~ swig/*~ \
|
src/webp/*~ man/*~ doc/*~ swig/*~ \
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
man_MANS = cwebp.1 dwebp.1
|
man_MANS = cwebp.1 dwebp.1
|
||||||
if WANT_MUX
|
if BUILD_MUX
|
||||||
man_MANS += webpmux.1
|
man_MANS += webpmux.1
|
||||||
endif
|
endif
|
||||||
if BUILD_GIF2WEBP
|
if BUILD_GIF2WEBP
|
||||||
man_MANS += gif2webp.1
|
man_MANS += gif2webp.1
|
||||||
endif
|
endif
|
||||||
|
if BUILD_IMG2WEBP
|
||||||
|
man_MANS += img2webp.1
|
||||||
|
endif
|
||||||
if BUILD_VWEBP
|
if BUILD_VWEBP
|
||||||
man_MANS += vwebp.1
|
man_MANS += vwebp.1
|
||||||
endif
|
endif
|
||||||
|
if BUILD_WEBPINFO
|
||||||
|
man_MANS += webpinfo.1
|
||||||
|
endif
|
||||||
EXTRA_DIST = $(man_MANS)
|
EXTRA_DIST = $(man_MANS)
|
||||||
|
|||||||
45
man/cwebp.1
45
man/cwebp.1
@@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH CWEBP 1 "December 14, 2015"
|
.TH CWEBP 1 "November 19, 2020"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
cwebp \- compress an image file to a WebP file
|
cwebp \- compress an image file to a WebP file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -13,6 +13,7 @@ command.
|
|||||||
.PP
|
.PP
|
||||||
\fBcwebp\fP compresses an image using the WebP format.
|
\fBcwebp\fP compresses an image using the WebP format.
|
||||||
Input format can be either PNG, JPEG, TIFF, WebP or raw Y'CbCr samples.
|
Input format can be either PNG, JPEG, TIFF, WebP or raw Y'CbCr samples.
|
||||||
|
Note: Animated PNG and WebP files are not supported.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
The basic options are:
|
The basic options are:
|
||||||
.TP
|
.TP
|
||||||
@@ -41,10 +42,12 @@ the invisible pixel values (R/G/B or Y/U/V) will be preserved only if the
|
|||||||
\-exact option is used.
|
\-exact option is used.
|
||||||
.TP
|
.TP
|
||||||
.BI \-near_lossless " int
|
.BI \-near_lossless " int
|
||||||
Use near\-lossless image preprocessing. This option adjusts pixel values
|
Specify the level of near\-lossless image preprocessing. This option adjusts
|
||||||
to help compressibility, but has minimal impact on the visual quality.
|
pixel values to help compressibility, but has minimal impact on the visual
|
||||||
It triggers lossless compression mode automatically.
|
quality. It triggers lossless compression mode automatically. The range is 0
|
||||||
Range is 0 (maximum preprocessing) to 100 (no preprocessing, the default).
|
(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
|
.TP
|
||||||
.BI \-q " float
|
.BI \-q " float
|
||||||
Specify the compression factor for RGB channels between 0 and 100. The default
|
Specify the compression factor for RGB channels between 0 and 100. The default
|
||||||
@@ -98,8 +101,7 @@ Crop the source to a rectangle with top\-left corner at coordinates
|
|||||||
This cropping area must be fully contained within the source rectangle.
|
This cropping area must be fully contained within the source rectangle.
|
||||||
.TP
|
.TP
|
||||||
.B \-mt
|
.B \-mt
|
||||||
Use multi\-threading for encoding, if possible. This option is only effective
|
Use multi\-threading for encoding, if possible.
|
||||||
when using lossy compression on a source with a transparency channel.
|
|
||||||
.TP
|
.TP
|
||||||
.B \-low_memory
|
.B \-low_memory
|
||||||
Reduce memory usage of lossy encoding by saving four times the compressed
|
Reduce memory usage of lossy encoding by saving four times the compressed
|
||||||
@@ -117,17 +119,28 @@ or without alpha).
|
|||||||
.TP
|
.TP
|
||||||
.BI \-size " int
|
.BI \-size " int
|
||||||
Specify a target size (in bytes) to try and reach for the compressed output.
|
Specify a target size (in bytes) to try and reach for the compressed output.
|
||||||
Compressor will make several pass of partial encoding in order to get as
|
The compressor will make several passes of partial encoding in order to get as
|
||||||
close as possible to this target.
|
close as possible to this target. If both \fB\-size\fP and \fB\-psnr\fP
|
||||||
|
are used, \fB\-size\fP value will prevail.
|
||||||
.TP
|
.TP
|
||||||
.BI \-psnr " float
|
.BI \-psnr " float
|
||||||
Specify a target PSNR (in dB) to try and reach for the compressed output.
|
Specify a target PSNR (in dB) to try and reach for the compressed output.
|
||||||
Compressor will make several pass of partial encoding in order to get as
|
The compressor will make several passes of partial encoding in order to get as
|
||||||
close as possible to this target.
|
close as possible to this target. If both \fB\-size\fP and \fB\-psnr\fP
|
||||||
|
are used, \fB\-size\fP value will prevail.
|
||||||
.TP
|
.TP
|
||||||
.BI \-pass " int
|
.BI \-pass " int
|
||||||
Set a maximum number of passes to use during the dichotomy used by
|
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.
|
options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10, default is 1.
|
||||||
|
If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't
|
||||||
|
specified, a default value of '6' passes will be used.
|
||||||
|
.TP
|
||||||
|
.BI \-qrange " int int
|
||||||
|
Specifies the permissible interval for the quality factor. This is particularly
|
||||||
|
useful when using multi-pass (\fB\-size\fP or \fB\-psnr\fP options).
|
||||||
|
Default is 0 100.
|
||||||
|
If the quality factor is outside this range, it will be clamped.
|
||||||
|
If the minimum value must be less or equal to the maximum one.
|
||||||
.TP
|
.TP
|
||||||
.B \-af
|
.B \-af
|
||||||
Turns auto\-filter on. This algorithm will spend additional time optimizing
|
Turns auto\-filter on. This algorithm will spend additional time optimizing
|
||||||
@@ -162,12 +175,16 @@ Use strong filtering (if filtering is being used thanks to the
|
|||||||
Disable strong filtering (if filtering is being used thanks to the
|
Disable strong filtering (if filtering is being used thanks to the
|
||||||
\fB\-f\fP option) and use simple filtering instead.
|
\fB\-f\fP option) and use simple filtering instead.
|
||||||
.TP
|
.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.
|
||||||
|
.TP
|
||||||
.BI \-sns " int
|
.BI \-sns " int
|
||||||
Specify the amplitude of the spatial noise shaping. Spatial noise shaping
|
Specify the amplitude of the spatial noise shaping. Spatial noise shaping
|
||||||
(or \fBsns\fP for short) refers to a general collection of built\-in algorithms
|
(or \fBsns\fP for short) refers to a general collection of built\-in algorithms
|
||||||
used to decide which area of the picture should use relatively less bits,
|
used to decide which area of the picture should use relatively less bits,
|
||||||
and where else to better transfer these bits. The possible range goes from
|
and where else to better transfer these bits. The possible range goes from
|
||||||
0 (algorithm is off) to 100 (the maximal effect). The default value is 80.
|
0 (algorithm is off) to 100 (the maximal effect). The default value is 50.
|
||||||
.TP
|
.TP
|
||||||
.BI \-segments " int
|
.BI \-segments " int
|
||||||
Change the number of partitions to use during the segmentation of the
|
Change the number of partitions to use during the segmentation of the
|
||||||
@@ -218,7 +235,7 @@ Report encoding progress in percent.
|
|||||||
Do not print anything.
|
Do not print anything.
|
||||||
.TP
|
.TP
|
||||||
.B \-short
|
.B \-short
|
||||||
Only print brief information (output file size and PSNR) for testing purpose.
|
Only print brief information (output file size and PSNR) for testing purposes.
|
||||||
.TP
|
.TP
|
||||||
.BI \-map " int
|
.BI \-map " int
|
||||||
Output additional ASCII\-map of encoding information. Possible map values
|
Output additional ASCII\-map of encoding information. Possible map values
|
||||||
@@ -277,7 +294,7 @@ Note: each input format may not support all combinations.
|
|||||||
Disable all assembly optimizations.
|
Disable all assembly optimizations.
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report all bugs to our issue tracker:
|
Please report all bugs to the issue tracker:
|
||||||
https://bugs.chromium.org/p/webp
|
https://bugs.chromium.org/p/webp
|
||||||
.br
|
.br
|
||||||
Patches welcome! See this page to get started:
|
Patches welcome! See this page to get started:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH DWEBP 1 "December 11, 2015"
|
.TH DWEBP 1 "November 19, 2020"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
dwebp \- decompress a WebP file to an image file
|
dwebp \- decompress a WebP file to an image file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -12,6 +12,7 @@ This manual page documents the
|
|||||||
command.
|
command.
|
||||||
.PP
|
.PP
|
||||||
\fBdwebp\fP decompresses WebP files into PNG, PAM, PPM or PGM images.
|
\fBdwebp\fP decompresses WebP files into PNG, PAM, PPM or PGM images.
|
||||||
|
Note: Animated WebP files are not supported.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
The basic options are:
|
The basic options are:
|
||||||
.TP
|
.TP
|
||||||
@@ -108,7 +109,7 @@ Print extra information (decoding time in particular).
|
|||||||
Disable all assembly optimizations.
|
Disable all assembly optimizations.
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report all bugs to our issue tracker:
|
Please report all bugs to the issue tracker:
|
||||||
https://bugs.chromium.org/p/webp
|
https://bugs.chromium.org/p/webp
|
||||||
.br
|
.br
|
||||||
Patches welcome! See this page to get started:
|
Patches welcome! See this page to get started:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH GIF2WEBP 1 "December 11, 2015"
|
.TH GIF2WEBP 1 "May 1, 2020"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
gif2webp \- Convert a GIF image to WebP
|
gif2webp \- Convert a GIF image to WebP
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -20,6 +20,12 @@ Specify the name of the output WebP file. If omitted, \fBgif2webp\fP will
|
|||||||
perform conversion but only report statistics.
|
perform conversion but only report statistics.
|
||||||
Using "\-" as output name will direct output to 'stdout'.
|
Using "\-" as output name will direct output to 'stdout'.
|
||||||
.TP
|
.TP
|
||||||
|
.BI \-\- " string
|
||||||
|
Explicitly specify the input file. This option is useful if the input
|
||||||
|
file starts with an '\-' for instance. This option must appear \fBlast\fP.
|
||||||
|
Any other options afterward will be ignored. If the input file is "\-",
|
||||||
|
the data will be read from \fIstdin\fP instead of a file.
|
||||||
|
.TP
|
||||||
.B \-h, \-help
|
.B \-h, \-help
|
||||||
Usage information.
|
Usage information.
|
||||||
.TP
|
.TP
|
||||||
@@ -56,9 +62,9 @@ larger file size and lower compression quality.
|
|||||||
.TP
|
.TP
|
||||||
.BI \-min_size
|
.BI \-min_size
|
||||||
Encode image to achieve smallest size. This disables key frame insertion and
|
Encode image to achieve smallest size. This disables key frame insertion and
|
||||||
picks the dispose method resulting in smallest output for each frame. It uses
|
picks the dispose method resulting in the smallest output for each frame. It
|
||||||
lossless compression by default, but can be combined with \-q, \-m, \-lossy or
|
uses lossless compression by default, but can be combined with \-q, \-m,
|
||||||
\-mixed options.
|
\-lossy or \-mixed options.
|
||||||
.TP
|
.TP
|
||||||
.BI \-kmin " int
|
.BI \-kmin " int
|
||||||
.TP
|
.TP
|
||||||
@@ -68,8 +74,9 @@ Specify the minimum and maximum distance between consecutive key frames
|
|||||||
some key frames into the output animation as needed so that this criteria is
|
some key frames into the output animation as needed so that this criteria is
|
||||||
satisfied.
|
satisfied.
|
||||||
.br
|
.br
|
||||||
A 'kmin' value of 0 will turn off insertion of key frames. A 'kmax' value of 0
|
A 'kmax' value of 0 will turn off insertion of key frames. A 'kmax' value of 1
|
||||||
will result in all frames being key frames.
|
will result in all frames being key frames. 'kmin' value is not taken into
|
||||||
|
account in both these special cases.
|
||||||
Typical values are in the range 3 to 30. Default values are kmin = 9,
|
Typical values are in the range 3 to 30. Default values are kmin = 9,
|
||||||
kmax = 17 for lossless compression and kmin = 3, kmax = 5 for lossy compression.
|
kmax = 17 for lossless compression and kmin = 3, kmax = 5 for lossy compression.
|
||||||
.br
|
.br
|
||||||
@@ -107,8 +114,11 @@ the value the smoother the picture will appear. Typical values are usually in
|
|||||||
the range of 20 to 50.
|
the range of 20 to 50.
|
||||||
.TP
|
.TP
|
||||||
.B \-mt
|
.B \-mt
|
||||||
Use multi-threading for encoding, if possible. This option is only effective
|
Use multi-threading for encoding, if possible.
|
||||||
when using lossy compression.
|
.TP
|
||||||
|
.B \-loop_compatibility
|
||||||
|
If enabled, handle the loop information in a compatible fashion for Chrome
|
||||||
|
version prior to M62 (inclusive) and Firefox.
|
||||||
.TP
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
Print extra information.
|
Print extra information.
|
||||||
@@ -117,7 +127,7 @@ Print extra information.
|
|||||||
Do not print anything.
|
Do not print anything.
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report all bugs to our issue tracker:
|
Please report all bugs to the issue tracker:
|
||||||
https://bugs.chromium.org/p/webp
|
https://bugs.chromium.org/p/webp
|
||||||
.br
|
.br
|
||||||
Patches welcome! See this page to get started:
|
Patches welcome! See this page to get started:
|
||||||
@@ -133,6 +143,8 @@ gif2webp \-lossy \-m 3 picture.gif \-o picture_lossy.webp
|
|||||||
gif2webp \-lossy \-f 50 picture.gif \-o picture.webp
|
gif2webp \-lossy \-f 50 picture.gif \-o picture.webp
|
||||||
.br
|
.br
|
||||||
gif2webp \-q 70 \-o picture.webp \-\- \-\-\-picture.gif
|
gif2webp \-q 70 \-o picture.webp \-\- \-\-\-picture.gif
|
||||||
|
.br
|
||||||
|
cat picture.gif | gif2webp \-o \- \-\- \- > output.webp
|
||||||
|
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
\fBgif2webp\fP is a part of libwebp and was written by the WebP team.
|
\fBgif2webp\fP is a part of libwebp and was written by the WebP team.
|
||||||
|
|||||||
105
man/img2webp.1
Normal file
105
man/img2webp.1
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
|
.TH IMG2WEBP 1 "May 1, 2020"
|
||||||
|
.SH NAME
|
||||||
|
img2webp \- create animated WebP file from a sequence of input images.
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B img2webp
|
||||||
|
[file_level_options] [files] [per_frame_options...]
|
||||||
|
.br
|
||||||
|
.B img2webp argument_file_name
|
||||||
|
.br
|
||||||
|
.SH DESCRIPTION
|
||||||
|
This manual page documents the
|
||||||
|
.B img2webp
|
||||||
|
command.
|
||||||
|
.PP
|
||||||
|
\fBimg2webp\fP compresses a sequence of images using the animated WebP format.
|
||||||
|
Input images can either be PNG, JPEG, TIFF or WebP.
|
||||||
|
If a single file name (not starting with the character '\-') is supplied as
|
||||||
|
the argument, the command line arguments are actually tokenized from this file.
|
||||||
|
This allows for easy scripting or using a large number of arguments.
|
||||||
|
.SH FILE-LEVEL OPTIONS
|
||||||
|
The file-level options are applied at the beginning of the compression process,
|
||||||
|
before the input frames are read.
|
||||||
|
.TP
|
||||||
|
.BI \-o " string
|
||||||
|
Specify the name of the output WebP file.
|
||||||
|
.TP
|
||||||
|
.BI \-min_size
|
||||||
|
Encode images to achieve smallest size. This disables key frame insertion and
|
||||||
|
picks the parameters resulting in the smallest output for each frame. It uses
|
||||||
|
lossless compression by default, but can be combined with \-q, \-m, \-lossy or
|
||||||
|
\-mixed options.
|
||||||
|
.TP
|
||||||
|
.BI \-kmin " int
|
||||||
|
.TP
|
||||||
|
.BI \-kmax " int
|
||||||
|
Specify the minimum and maximum distance between consecutive key frames
|
||||||
|
(independently decodable frames) in the output animation. The tool will insert
|
||||||
|
some key frames into the output animation as needed so that this criteria is
|
||||||
|
satisfied.
|
||||||
|
.br
|
||||||
|
.B \-mixed
|
||||||
|
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 \-loop " int
|
||||||
|
Specifies the number of times the animation should loop. Using '0'
|
||||||
|
means 'loop indefinitely'.
|
||||||
|
.TP
|
||||||
|
.BI \-v
|
||||||
|
Be more verbose.
|
||||||
|
.TP
|
||||||
|
.B \-h, \-help
|
||||||
|
A short usage summary.
|
||||||
|
.TP
|
||||||
|
.B \-version
|
||||||
|
Print the version numbers of the relevant libraries used.
|
||||||
|
|
||||||
|
.SH PER-FRAME OPTIONS
|
||||||
|
The per-frame options are applied for the images following as arguments in the
|
||||||
|
command line. They can be modified any number of times preceding each particular
|
||||||
|
input image.
|
||||||
|
.TP
|
||||||
|
.BI \-d " int
|
||||||
|
Specify the image duration in milliseconds.
|
||||||
|
.TP
|
||||||
|
.B \-lossless, \-lossy
|
||||||
|
Compress the next image(s) using lossless or lossy compression mode. The
|
||||||
|
default mode is lossless.
|
||||||
|
.TP
|
||||||
|
.BI \-q " float
|
||||||
|
Specify the compression factor between 0 and 100. The default is 75.
|
||||||
|
.TP
|
||||||
|
.BI \-m " int
|
||||||
|
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.
|
||||||
|
|
||||||
|
.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:
|
||||||
|
http://www.webmproject.org/code/contribute/submitting\-patches/
|
||||||
|
|
||||||
|
.SH AUTHORS
|
||||||
|
\fBimg2webp\fP is a part of libwebp and was written by the WebP team.
|
||||||
|
.br
|
||||||
|
The latest source tree is available at
|
||||||
|
https://chromium.googlesource.com/webm/libwebp
|
||||||
|
.PP
|
||||||
|
This manual page was written by Pascal Massimino <pascal.massimino@gmail.com>,
|
||||||
|
for the Debian project (and may be used by others).
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR webpmux (1),
|
||||||
|
.BR gif2webp (1)
|
||||||
|
.br
|
||||||
|
Please refer to http://developers.google.com/speed/webp/ for additional
|
||||||
|
information.
|
||||||
14
man/vwebp.1
14
man/vwebp.1
@@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH VWEBP 1 "December 11, 2015"
|
.TH VWEBP 1 "June 5, 2019"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
vwebp \- decompress a WebP file and display it in a window
|
vwebp \- decompress a WebP file and display it in a window
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -38,6 +38,10 @@ It helps by smoothing gradients and avoiding banding artifacts. Default: 50.
|
|||||||
By default, quantized transparency planes are dithered during decompression,
|
By default, quantized transparency planes are dithered during decompression,
|
||||||
to smooth the gradients. This flag will prevent this dithering.
|
to smooth the gradients. This flag will prevent this dithering.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-usebgcolor
|
||||||
|
Fill transparent areas with the bitstream's own background color instead of
|
||||||
|
checkerboard only. Default is white for non-animated images.
|
||||||
|
.TP
|
||||||
.B \-mt
|
.B \-mt
|
||||||
Use multi-threading for decoding, if possible.
|
Use multi-threading for decoding, if possible.
|
||||||
.TP
|
.TP
|
||||||
@@ -56,14 +60,20 @@ the data will be read from \fIstdin\fP instead of a file.
|
|||||||
.B 'c'
|
.B 'c'
|
||||||
Toggle use of color profile.
|
Toggle use of color profile.
|
||||||
.TP
|
.TP
|
||||||
|
.B 'b'
|
||||||
|
Toggle display of background color.
|
||||||
|
.TP
|
||||||
.B 'i'
|
.B 'i'
|
||||||
Overlay file information.
|
Overlay file information.
|
||||||
.TP
|
.TP
|
||||||
|
.B 'd'
|
||||||
|
Disable blending and disposal process, for debugging purposes.
|
||||||
|
.TP
|
||||||
.B 'q' / 'Q' / ESC
|
.B 'q' / 'Q' / ESC
|
||||||
Quit.
|
Quit.
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report all bugs to our issue tracker:
|
Please report all bugs to the issue tracker:
|
||||||
https://bugs.chromium.org/p/webp
|
https://bugs.chromium.org/p/webp
|
||||||
.br
|
.br
|
||||||
Patches welcome! See this page to get started:
|
Patches welcome! See this page to get started:
|
||||||
|
|||||||
80
man/webpinfo.1
Normal file
80
man/webpinfo.1
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
|
.TH WEBPINFO 1 "November 24, 2017"
|
||||||
|
.SH NAME
|
||||||
|
webpinfo \- print out the chunk level structure of WebP files
|
||||||
|
along with basic integrity checks.
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B webpinfo
|
||||||
|
.I OPTIONS
|
||||||
|
.I INPUT
|
||||||
|
.br
|
||||||
|
.B webpinfo [\-h|\-help|\-H|\-longhelp]
|
||||||
|
.br
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
This manual page documents the
|
||||||
|
.B webpinfo
|
||||||
|
command.
|
||||||
|
.PP
|
||||||
|
\fBwebpinfo\fP 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.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-version
|
||||||
|
Print the version number (as major.minor.revision) and exit.
|
||||||
|
.TP
|
||||||
|
.B \-quiet
|
||||||
|
Do not show chunk parsing information.
|
||||||
|
.TP
|
||||||
|
.B \-diag
|
||||||
|
Show parsing error diagnosis.
|
||||||
|
.TP
|
||||||
|
.B \-summary
|
||||||
|
Show chunk stats summary.
|
||||||
|
.TP
|
||||||
|
.BI \-bitstream_info
|
||||||
|
Parse bitstream header.
|
||||||
|
.TP
|
||||||
|
.B \-h, \-help
|
||||||
|
A short usage summary.
|
||||||
|
.TP
|
||||||
|
.B \-H, \-longhelp
|
||||||
|
Detailed usage instructions.
|
||||||
|
|
||||||
|
.SH INPUT
|
||||||
|
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:
|
||||||
|
http://www.webmproject.org/code/contribute/submitting\-patches/
|
||||||
|
|
||||||
|
.SH EXAMPLES
|
||||||
|
.br
|
||||||
|
webpinfo \-h
|
||||||
|
.br
|
||||||
|
webpinfo \-diag \-summary input_file.webp
|
||||||
|
.br
|
||||||
|
webpinfo \-bitstream_info input_file_1.webp input_file_2.webp
|
||||||
|
.br
|
||||||
|
webpinfo *.webp
|
||||||
|
|
||||||
|
.SH AUTHORS
|
||||||
|
\fBwebpinfo\fP is a part of libwebp and was written by the WebP team.
|
||||||
|
.br
|
||||||
|
The latest source tree is available at
|
||||||
|
https://chromium.googlesource.com/webm/libwebp
|
||||||
|
.PP
|
||||||
|
This manual page was written by Hui Su <huisu@google.com>,
|
||||||
|
for the Debian project (and may be used by others).
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR webpmux (1)
|
||||||
|
.br
|
||||||
|
Please refer to http://developers.google.com/speed/webp/ for additional
|
||||||
|
information.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
.\" Hey, EMACS: -*- nroff -*-
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
.TH WEBPMUX 1 "December 11, 2015"
|
.TH WEBPMUX 1 "November 3, 2021"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
webpmux \- create animated WebP files from non\-animated WebP images, extract
|
webpmux \- create animated WebP files from non\-animated WebP images, extract
|
||||||
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
|
frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
|
||||||
@@ -35,12 +35,21 @@ frames from animated WebP images, and manage XMP/EXIF metadata and ICC profile.
|
|||||||
.I OUTPUT
|
.I OUTPUT
|
||||||
.RE
|
.RE
|
||||||
.br
|
.br
|
||||||
|
.B webpmux \-duration
|
||||||
|
.I DURATION OPTIONS
|
||||||
|
.B [ \-duration ... ]
|
||||||
|
.I INPUT
|
||||||
|
.B \-o
|
||||||
|
.I OUTPUT
|
||||||
|
.br
|
||||||
.B webpmux \-info
|
.B webpmux \-info
|
||||||
.I INPUT
|
.I INPUT
|
||||||
.br
|
.br
|
||||||
.B webpmux [\-h|\-help]
|
.B webpmux [\-h|\-help]
|
||||||
.br
|
.br
|
||||||
.B webpmux \-version
|
.B webpmux \-version
|
||||||
|
.br
|
||||||
|
.B webpmux argument_file_name
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
This manual page documents the
|
This manual page documents the
|
||||||
.B webpmux
|
.B webpmux
|
||||||
@@ -48,6 +57,9 @@ command.
|
|||||||
.PP
|
.PP
|
||||||
\fBwebpmux\fP can be used to create/extract from animated WebP files, as well as
|
\fBwebpmux\fP can be used to create/extract from animated WebP files, as well as
|
||||||
to add/extract/strip XMP/EXIF metadata and ICC profile.
|
to add/extract/strip XMP/EXIF metadata and ICC profile.
|
||||||
|
If a single file name (not starting with the character '\-') is supplied as
|
||||||
|
the argument, the command line arguments are actually tokenized from this file.
|
||||||
|
This allows for easy scripting or using a large number of arguments.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.SS GET_OPTIONS (\-get):
|
.SS GET_OPTIONS (\-get):
|
||||||
.TP
|
.TP
|
||||||
@@ -65,6 +77,17 @@ Get nth frame from an animated image. (n = 0 has a special meaning: last frame).
|
|||||||
|
|
||||||
.SS SET_OPTIONS (\-set)
|
.SS SET_OPTIONS (\-set)
|
||||||
.TP
|
.TP
|
||||||
|
.BI loop " loop_count
|
||||||
|
Set loop count on an animated file.
|
||||||
|
.P
|
||||||
|
Where: 'loop_count' must be in range [0, 65535].
|
||||||
|
.TP
|
||||||
|
.BI bgcolor " A,R,G,B
|
||||||
|
Set the background color of the canvas on an animated file.
|
||||||
|
.P
|
||||||
|
where: 'A', 'R', 'G' and 'B' are integers in the range 0 to 255 specifying the
|
||||||
|
Alpha, Red, Green and Blue component values respectively.
|
||||||
|
.TP
|
||||||
.BI icc " file.icc
|
.BI icc " file.icc
|
||||||
Set ICC profile.
|
Set ICC profile.
|
||||||
.P
|
.P
|
||||||
@@ -91,6 +114,42 @@ Strip EXIF metadata.
|
|||||||
.B xmp
|
.B xmp
|
||||||
Strip XMP metadata.
|
Strip XMP metadata.
|
||||||
|
|
||||||
|
.SS DURATION_OPTIONS (\-duration)
|
||||||
|
Amend the duration of a specific interval of frames. This option is only
|
||||||
|
effective on animated WebP and has no effect on a single-frame file.
|
||||||
|
.TP
|
||||||
|
.I duration[,start[,end]]
|
||||||
|
Where:
|
||||||
|
.br
|
||||||
|
.B duration
|
||||||
|
is the duration for the interval in milliseconds (mandatory).
|
||||||
|
Must be non-negative.
|
||||||
|
.br
|
||||||
|
.B start
|
||||||
|
is the starting frame index of the interval (optional).
|
||||||
|
.br
|
||||||
|
.B end
|
||||||
|
is the ending frame index (inclusive) of the interval (optional).
|
||||||
|
.TP
|
||||||
|
The three typical usages of this option are:
|
||||||
|
.br
|
||||||
|
.B -duration d
|
||||||
|
set the duration to 'd' for the whole animation.
|
||||||
|
.br
|
||||||
|
.B -duration d,f
|
||||||
|
set the duration of frame 'f' to 'd'.
|
||||||
|
.br
|
||||||
|
.B -duration d,start,end
|
||||||
|
set the duration to 'd' for the whole [start,end] interval.
|
||||||
|
.TP
|
||||||
|
.P
|
||||||
|
Note that the frames outside of the [start, end] interval will remain untouched.
|
||||||
|
The 'end' value '0' has the special meaning 'last frame of the animation'.
|
||||||
|
.TP
|
||||||
|
.I Reminder:
|
||||||
|
frame indexing starts at '1'.
|
||||||
|
.br
|
||||||
|
|
||||||
.SS FRAME_OPTIONS (\-frame)
|
.SS FRAME_OPTIONS (\-frame)
|
||||||
Create an animated WebP file from multiple (non\-animated) WebP images.
|
Create an animated WebP file from multiple (non\-animated) WebP images.
|
||||||
.TP
|
.TP
|
||||||
@@ -128,7 +187,7 @@ Output file in WebP format.
|
|||||||
The nature of EXIF, XMP and ICC data is not checked and is assumed to be valid.
|
The nature of EXIF, XMP and ICC data is not checked and is assumed to be valid.
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report all bugs to our issue tracker:
|
Please report all bugs to the issue tracker:
|
||||||
https://bugs.chromium.org/p/webp
|
https://bugs.chromium.org/p/webp
|
||||||
.br
|
.br
|
||||||
Patches welcome! See this page to get started:
|
Patches welcome! See this page to get started:
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
# The mux, demux and extras libraries depend on libwebp, thus the '.' to force
|
# The mux and demux libraries depend on libwebp, thus the '.' to force
|
||||||
# the build order so it's available to them.
|
# the build order so it's available to them.
|
||||||
SUBDIRS = dec enc dsp utils .
|
SUBDIRS = dec enc dsp utils .
|
||||||
if WANT_MUX
|
if BUILD_MUX
|
||||||
SUBDIRS += mux
|
SUBDIRS += mux
|
||||||
endif
|
endif
|
||||||
if WANT_DEMUX
|
if BUILD_DEMUX
|
||||||
SUBDIRS += demux
|
SUBDIRS += demux
|
||||||
endif
|
endif
|
||||||
if WANT_EXTRAS
|
|
||||||
SUBDIRS += extras
|
|
||||||
endif
|
|
||||||
|
|
||||||
lib_LTLIBRARIES = libwebp.la
|
lib_LTLIBRARIES = libwebp.la
|
||||||
|
|
||||||
@@ -25,6 +22,7 @@ commondir = $(includedir)/webp
|
|||||||
libwebp_la_SOURCES =
|
libwebp_la_SOURCES =
|
||||||
libwebpinclude_HEADERS =
|
libwebpinclude_HEADERS =
|
||||||
libwebpinclude_HEADERS += webp/encode.h
|
libwebpinclude_HEADERS += webp/encode.h
|
||||||
|
|
||||||
noinst_HEADERS =
|
noinst_HEADERS =
|
||||||
noinst_HEADERS += webp/format_constants.h
|
noinst_HEADERS += webp/format_constants.h
|
||||||
|
|
||||||
@@ -38,7 +36,7 @@ libwebp_la_LIBADD += utils/libwebputils.la
|
|||||||
# other than the ones listed on the command line, i.e., after linking, it will
|
# other than the ones listed on the command line, i.e., after linking, it will
|
||||||
# not have unresolved symbols. Some platforms (Windows among them) require all
|
# not have unresolved symbols. Some platforms (Windows among them) require all
|
||||||
# symbols in shared libraries to be resolved at library creation.
|
# symbols in shared libraries to be resolved at library creation.
|
||||||
libwebp_la_LDFLAGS = -no-undefined -version-info 6:0:0
|
libwebp_la_LDFLAGS = -no-undefined -version-info 8:2:1
|
||||||
libwebpincludedir = $(includedir)/webp
|
libwebpincludedir = $(includedir)/webp
|
||||||
pkgconfig_DATA = libwebp.pc
|
pkgconfig_DATA = libwebp.pc
|
||||||
|
|
||||||
@@ -50,7 +48,7 @@ if BUILD_LIBWEBPDECODER
|
|||||||
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
|
libwebpdecoder_la_LIBADD += dsp/libwebpdspdecode.la
|
||||||
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
libwebpdecoder_la_LIBADD += utils/libwebputilsdecode.la
|
||||||
|
|
||||||
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 2:0:0
|
libwebpdecoder_la_LDFLAGS = -no-undefined -version-info 4:2:1
|
||||||
pkgconfig_DATA += libwebpdecoder.pc
|
pkgconfig_DATA += libwebpdecoder.pc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,23 @@
|
|||||||
|
AM_CPPFLAGS += -I$(top_builddir) -I$(top_srcdir)
|
||||||
noinst_LTLIBRARIES = libwebpdecode.la
|
noinst_LTLIBRARIES = libwebpdecode.la
|
||||||
|
|
||||||
libwebpdecode_la_SOURCES =
|
libwebpdecode_la_SOURCES =
|
||||||
libwebpdecode_la_SOURCES += alpha.c
|
libwebpdecode_la_SOURCES += alpha_dec.c
|
||||||
libwebpdecode_la_SOURCES += alphai.h
|
libwebpdecode_la_SOURCES += alphai_dec.h
|
||||||
libwebpdecode_la_SOURCES += buffer.c
|
libwebpdecode_la_SOURCES += buffer_dec.c
|
||||||
libwebpdecode_la_SOURCES += common.h
|
libwebpdecode_la_SOURCES += common_dec.h
|
||||||
libwebpdecode_la_SOURCES += decode_vp8.h
|
libwebpdecode_la_SOURCES += vp8_dec.h
|
||||||
libwebpdecode_la_SOURCES += frame.c
|
libwebpdecode_la_SOURCES += frame_dec.c
|
||||||
libwebpdecode_la_SOURCES += idec.c
|
libwebpdecode_la_SOURCES += idec_dec.c
|
||||||
libwebpdecode_la_SOURCES += io.c
|
libwebpdecode_la_SOURCES += io_dec.c
|
||||||
libwebpdecode_la_SOURCES += quant.c
|
libwebpdecode_la_SOURCES += quant_dec.c
|
||||||
libwebpdecode_la_SOURCES += tree.c
|
libwebpdecode_la_SOURCES += tree_dec.c
|
||||||
libwebpdecode_la_SOURCES += vp8.c
|
libwebpdecode_la_SOURCES += vp8_dec.c
|
||||||
libwebpdecode_la_SOURCES += vp8i.h
|
libwebpdecode_la_SOURCES += vp8i_dec.h
|
||||||
libwebpdecode_la_SOURCES += vp8l.c
|
libwebpdecode_la_SOURCES += vp8l_dec.c
|
||||||
libwebpdecode_la_SOURCES += vp8li.h
|
libwebpdecode_la_SOURCES += vp8li_dec.h
|
||||||
libwebpdecode_la_SOURCES += webp.c
|
libwebpdecode_la_SOURCES += webp_dec.c
|
||||||
libwebpdecode_la_SOURCES += webpi.h
|
libwebpdecode_la_SOURCES += webpi_dec.h
|
||||||
|
|
||||||
libwebpdecodeinclude_HEADERS =
|
libwebpdecodeinclude_HEADERS =
|
||||||
libwebpdecodeinclude_HEADERS += ../webp/decode.h
|
libwebpdecodeinclude_HEADERS += ../webp/decode.h
|
||||||
@@ -24,5 +25,5 @@ libwebpdecodeinclude_HEADERS += ../webp/types.h
|
|||||||
noinst_HEADERS =
|
noinst_HEADERS =
|
||||||
noinst_HEADERS += ../webp/format_constants.h
|
noinst_HEADERS += ../webp/format_constants.h
|
||||||
|
|
||||||
libwebpdecode_la_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)
|
libwebpdecode_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
libwebpdecodeincludedir = $(includedir)/webp
|
libwebpdecodeincludedir = $(includedir)/webp
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user